Repository: BrowserSync/browser-sync Branch: master Commit: dc74bc0a6bcb Files: 682 Total size: 3.2 MB Directory structure: gitextract_5fuwfm2s/ ├── .editorconfig ├── .gitattributes ├── .github/ │ └── workflows/ │ └── main.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── changelog.js ├── examples/ │ ├── 404.js │ ├── basic/ │ │ └── run.js │ ├── callback.js │ ├── express.js │ ├── less.js │ ├── middleware.css.injection.js │ ├── notify-styles.js │ ├── options.snippetOptions.js │ ├── proxy.gzip.js │ ├── proxy.headers.js │ ├── proxy.localhost.js │ ├── proxy.middleware.js │ ├── proxy.middleware.multi.js │ ├── proxy.proxyRes.js │ ├── proxy.rewriteRules.advanced.js │ ├── proxy.rewriteRules.simple.js │ ├── proxy.secure.js │ ├── proxy.vhost.js │ ├── server.basedir.js │ ├── server.basedir.mulitple.js │ ├── server.default.js │ ├── server.gzip.js │ ├── server.http2.js │ ├── server.latency.js │ ├── server.middleware.js │ ├── server.middleware.multiple.js │ ├── server.proxy.js │ ├── server.secure.js │ ├── server.secure.pfx.js │ ├── server.watch.js │ └── snippet/ │ ├── index.html │ └── run.js ├── lerna.json ├── nx.json ├── package.json ├── packages/ │ ├── browser-sync/ │ │ ├── .gitignore │ │ ├── .prettierignore │ │ ├── certs/ │ │ │ ├── browsersync.pfx │ │ │ ├── gen.sh │ │ │ ├── server.crt │ │ │ ├── server.csr │ │ │ └── server.key │ │ ├── cli-options/ │ │ │ ├── opts.init.json │ │ │ ├── opts.recipe.json │ │ │ ├── opts.reload.json │ │ │ └── opts.start.json │ │ ├── lib/ │ │ │ ├── args.js │ │ │ ├── async-tasks.js │ │ │ ├── async.js │ │ │ ├── bin.ts │ │ │ ├── browser-sync.js │ │ │ ├── cli/ │ │ │ │ ├── cli-info.js │ │ │ │ ├── cli-options.ts │ │ │ │ ├── command.init.js │ │ │ │ ├── command.recipe.js │ │ │ │ ├── command.reload.js │ │ │ │ ├── command.start.ts │ │ │ │ └── transforms/ │ │ │ │ ├── addCwdToWatchOptions.ts │ │ │ │ ├── addDefaultIgnorePatterns.ts │ │ │ │ ├── addToFilesOption.ts │ │ │ │ ├── appendServerDirectoryOption.ts │ │ │ │ ├── appendServerIndexOption.ts │ │ │ │ ├── copyCLIIgnoreToWatchOptions.ts │ │ │ │ ├── handleExtensionsOption.ts │ │ │ │ ├── handleFilesOption.ts │ │ │ │ ├── handleGhostModeOption.ts │ │ │ │ ├── handleHostOption.ts │ │ │ │ ├── handlePortsOption.ts │ │ │ │ ├── handleProxyOption.ts │ │ │ │ └── handleServerOption.ts │ │ │ ├── config.js │ │ │ ├── connect-utils.js │ │ │ ├── default-config.js │ │ │ ├── file-event-handler.js │ │ │ ├── file-utils.js │ │ │ ├── file-watcher.js │ │ │ ├── hooks.js │ │ │ ├── http-protocol.js │ │ │ ├── index.js │ │ │ ├── internal-events.js │ │ │ ├── lodash.custom.js │ │ │ ├── logger.js │ │ │ ├── options.ts │ │ │ ├── plugins.js │ │ │ ├── public/ │ │ │ │ ├── exit.js │ │ │ │ ├── init.ts │ │ │ │ ├── notify.js │ │ │ │ ├── pause.js │ │ │ │ ├── public-utils.js │ │ │ │ ├── reload.js │ │ │ │ ├── resume.js │ │ │ │ └── stream.js │ │ │ ├── server/ │ │ │ │ ├── index.js │ │ │ │ ├── proxy-server.js │ │ │ │ ├── proxy-utils.js │ │ │ │ ├── serve-static-wrapper.ts │ │ │ │ ├── snippet-server.js │ │ │ │ ├── static-server.js │ │ │ │ └── utils.js │ │ │ ├── snippet.js │ │ │ ├── sockets.ts │ │ │ ├── tunnel.js │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── package.json │ │ ├── readme.md │ │ ├── templates/ │ │ │ ├── cli-template.js │ │ │ ├── connector.tmpl │ │ │ ├── script-tags-simple.html │ │ │ └── script-tags.html │ │ ├── test/ │ │ │ ├── env.js │ │ │ ├── fixtures/ │ │ │ │ ├── .tmp/ │ │ │ │ │ └── temp.css │ │ │ │ ├── alt/ │ │ │ │ │ └── index.htm │ │ │ │ ├── assets/ │ │ │ │ │ ├── import.css │ │ │ │ │ ├── import2.css │ │ │ │ │ ├── print.css │ │ │ │ │ └── style.css │ │ │ │ ├── base.html │ │ │ │ ├── bootstrap/ │ │ │ │ │ ├── css/ │ │ │ │ │ │ ├── bootstrap-grid.css │ │ │ │ │ │ ├── bootstrap-reboot.css │ │ │ │ │ │ ├── bootstrap.css │ │ │ │ │ │ └── justified-nav.css │ │ │ │ │ ├── index.html │ │ │ │ │ └── js/ │ │ │ │ │ ├── bootstrap.bundle.js │ │ │ │ │ └── bootstrap.js │ │ │ │ ├── bootstrap.html │ │ │ │ ├── bower.html │ │ │ │ ├── bower_components/ │ │ │ │ │ └── app.css │ │ │ │ ├── config/ │ │ │ │ │ ├── config.js │ │ │ │ │ ├── si-config-partial.js │ │ │ │ │ ├── si-config-ports.js │ │ │ │ │ ├── si-config-proxy.js │ │ │ │ │ ├── si-config.js │ │ │ │ │ └── si-default-config.js │ │ │ │ ├── css/ │ │ │ │ │ ├── bootstrap-less.css │ │ │ │ │ ├── bootstrap-scss.css │ │ │ │ │ └── bootstrap.css │ │ │ │ ├── fonts/ │ │ │ │ │ └── roboto/ │ │ │ │ │ ├── Roboto-Regular-demo.html │ │ │ │ │ └── stylesheet.css │ │ │ │ ├── forms.html │ │ │ │ ├── iframe.html │ │ │ │ ├── images.html │ │ │ │ ├── import-link.html │ │ │ │ ├── import.html │ │ │ │ ├── index-amd.html │ │ │ │ ├── index-large.html │ │ │ │ ├── index-urls.html │ │ │ │ ├── index.html │ │ │ │ ├── inputs.html │ │ │ │ ├── js/ │ │ │ │ │ ├── default.js │ │ │ │ │ └── main.js │ │ │ │ ├── less/ │ │ │ │ │ └── bootstrap.less │ │ │ │ ├── less.html │ │ │ │ ├── links.html │ │ │ │ ├── plugin.js │ │ │ │ ├── proxy-headers.html │ │ │ │ ├── proxy-ip.html │ │ │ │ ├── proxy-vhost.html │ │ │ │ ├── rewrites/ │ │ │ │ │ ├── comment.expected.html │ │ │ │ │ ├── comment.html │ │ │ │ │ ├── escaped.1.expected.html │ │ │ │ │ ├── escaped.1.html │ │ │ │ │ ├── hashes.expected.html │ │ │ │ │ └── hashes.input.html │ │ │ │ ├── sass.html │ │ │ │ ├── scrolling.html │ │ │ │ ├── scss/ │ │ │ │ │ └── bootstrap-scss.scss │ │ │ │ ├── socket.io.html │ │ │ │ ├── stylus/ │ │ │ │ │ └── bootstrap.styl │ │ │ │ ├── svg.html │ │ │ │ ├── tailwind/ │ │ │ │ │ └── index.html │ │ │ │ ├── test.txt │ │ │ │ ├── test2.txt │ │ │ │ ├── username.github.io/ │ │ │ │ │ └── index.html │ │ │ │ └── watch-func.txt │ │ │ ├── fixtures2/ │ │ │ │ └── style-alt.css │ │ │ ├── protractor/ │ │ │ │ ├── _run.js │ │ │ │ ├── bs.init.js │ │ │ │ ├── config.multi.js │ │ │ │ ├── config.single.js │ │ │ │ ├── logger.js │ │ │ │ ├── runProtractor.js │ │ │ │ ├── setup.js │ │ │ │ ├── setup.single.js │ │ │ │ ├── tests/ │ │ │ │ │ ├── actions.clicks.js │ │ │ │ │ ├── actions.scroll.js │ │ │ │ │ ├── proxy.interactions.js │ │ │ │ │ ├── proxy.rewrites.js │ │ │ │ │ ├── server.interactions.js │ │ │ │ │ ├── snippet.injection.js │ │ │ │ │ ├── with.baseurl.https.js │ │ │ │ │ ├── with.baseurl.js │ │ │ │ │ └── with.socket.io.js │ │ │ │ ├── tests.multi.js │ │ │ │ ├── tests.single.js │ │ │ │ └── utils.js │ │ │ ├── specs/ │ │ │ │ ├── api/ │ │ │ │ │ ├── init.active.js │ │ │ │ │ ├── init.exit.js │ │ │ │ │ ├── init.js │ │ │ │ │ ├── init.notify.js │ │ │ │ │ ├── init.pause.js │ │ │ │ │ ├── init.reload.deprecated.js │ │ │ │ │ ├── init.reload.js │ │ │ │ │ ├── init.reload.multi.js │ │ │ │ │ ├── init.reload.stream.js │ │ │ │ │ ├── init.reload.stream.noop.js │ │ │ │ │ ├── init.returns.js │ │ │ │ │ ├── init.sockets.js │ │ │ │ │ └── watch.js │ │ │ │ ├── cli/ │ │ │ │ │ ├── cli.exec.js │ │ │ │ │ ├── cli.get.config.js │ │ │ │ │ ├── cli.help.js │ │ │ │ │ ├── cli.info.js │ │ │ │ │ ├── cli.options.files.js │ │ │ │ │ ├── cli.options.ghost.js │ │ │ │ │ ├── cli.options.ignore.js │ │ │ │ │ ├── cli.options.ports.js │ │ │ │ │ ├── cli.options.proxy.js │ │ │ │ │ ├── cli.options.server.js │ │ │ │ │ ├── cli.options.watch.js │ │ │ │ │ └── cli.options.watchOptions.cwd.js │ │ │ │ ├── commands/ │ │ │ │ │ ├── recipes.js │ │ │ │ │ └── reload.js │ │ │ │ ├── e2e/ │ │ │ │ │ ├── cli/ │ │ │ │ │ │ ├── e2e.cli.conf.js │ │ │ │ │ │ ├── e2e.cli.error.js │ │ │ │ │ │ ├── e2e.cli.files.js │ │ │ │ │ │ ├── e2e.cli.init.js │ │ │ │ │ │ ├── e2e.cli.plugins.js │ │ │ │ │ │ ├── e2e.cli.proxy.js │ │ │ │ │ │ ├── e2e.cli.proxy.ws.js │ │ │ │ │ │ ├── e2e.cli.server.js │ │ │ │ │ │ ├── e2e.cli.snippet.js │ │ │ │ │ │ └── e2e.cli.ui.js │ │ │ │ │ ├── commands.server.json │ │ │ │ │ ├── e2e.events.js │ │ │ │ │ ├── e2e.fail.js │ │ │ │ │ ├── e2e.online.js │ │ │ │ │ ├── e2e.options.callbacks.js │ │ │ │ │ ├── e2e.options.cors.js │ │ │ │ │ ├── e2e.options.js │ │ │ │ │ ├── e2e.options.logPrefix.js │ │ │ │ │ ├── e2e.options.logSnippet.js │ │ │ │ │ ├── e2e.options.open.browsers.js │ │ │ │ │ ├── e2e.options.open.js │ │ │ │ │ ├── e2e.options.port.js │ │ │ │ │ ├── e2e.options.script.async.js │ │ │ │ │ ├── e2e.options.scriptpath.js │ │ │ │ │ ├── e2e.options.serveStatic.js │ │ │ │ │ ├── e2e.options.single.js │ │ │ │ │ ├── e2e.options.snippet.js │ │ │ │ │ ├── e2e.options.sockets.js │ │ │ │ │ ├── e2e.options.startPath.js │ │ │ │ │ ├── e2e.snippet.js │ │ │ │ │ ├── files/ │ │ │ │ │ │ ├── e2e.file.changed.js │ │ │ │ │ │ ├── e2e.file.options.js │ │ │ │ │ │ └── e2e.file.watching.js │ │ │ │ │ ├── middleware/ │ │ │ │ │ │ ├── middleware.option.js │ │ │ │ │ │ ├── middleware.proxy.option.js │ │ │ │ │ │ └── middleware.server.option.js │ │ │ │ │ ├── proxy/ │ │ │ │ │ │ ├── e2e.proxy.cookies.js │ │ │ │ │ │ ├── e2e.proxy.error.js │ │ │ │ │ │ ├── e2e.proxy.external.js │ │ │ │ │ │ ├── e2e.proxy.js │ │ │ │ │ │ ├── e2e.proxy.proxy.options.js │ │ │ │ │ │ ├── e2e.proxy.req.headers.js │ │ │ │ │ │ ├── e2e.proxy.req.headers.obj.js │ │ │ │ │ │ ├── e2e.proxy.rewrite.rules.add.js │ │ │ │ │ │ ├── e2e.proxy.rewrite.rules.js │ │ │ │ │ │ ├── e2e.proxy.rewrite.rules.remove.js │ │ │ │ │ │ ├── e2e.proxy.rewrite.rules.replace.js │ │ │ │ │ │ ├── e2e.proxy.secure.js │ │ │ │ │ │ ├── e2e.proxy.snippet.js │ │ │ │ │ │ └── e2e.proxy.ws.js │ │ │ │ │ └── server/ │ │ │ │ │ ├── e2e.server.404.js │ │ │ │ │ ├── e2e.server.dirs.js │ │ │ │ │ ├── e2e.server.httpModule.js │ │ │ │ │ ├── e2e.server.js │ │ │ │ │ ├── e2e.server.middleware.js │ │ │ │ │ ├── e2e.server.newapi.js │ │ │ │ │ ├── e2e.server.newapi2.js │ │ │ │ │ ├── e2e.server.rewrite.rules.add.js │ │ │ │ │ ├── e2e.server.rewrite.rules.js │ │ │ │ │ ├── e2e.server.rewrite.rules.remove.js │ │ │ │ │ ├── e2e.server.rewrite.rules.replace.js │ │ │ │ │ ├── e2e.server.routes.js │ │ │ │ │ ├── e2e.server.secure.custom.js │ │ │ │ │ ├── e2e.server.secure.js │ │ │ │ │ ├── e2e.server.secure.pfx.js │ │ │ │ │ ├── e2e.server.serveStatic.extensions.js │ │ │ │ │ ├── e2e.server.serveStatic.js │ │ │ │ │ └── e2e.server.tunnel.js │ │ │ │ ├── files/ │ │ │ │ │ ├── files.event-handler.js │ │ │ │ │ ├── files.watching.debounce.js │ │ │ │ │ ├── files.watching.delay.js │ │ │ │ │ └── files.watching.js │ │ │ │ ├── hooks/ │ │ │ │ │ └── files.watch.hook.js │ │ │ │ ├── http-protocol/ │ │ │ │ │ └── http.reload.js │ │ │ │ ├── instances/ │ │ │ │ │ ├── multi.emitter.js │ │ │ │ │ ├── multi.get.js │ │ │ │ │ ├── multi.has.js │ │ │ │ │ ├── multi.init.js │ │ │ │ │ ├── multi.js │ │ │ │ │ ├── multi.plugins.js │ │ │ │ │ ├── multi.proxy.js │ │ │ │ │ └── single.js │ │ │ │ ├── logger/ │ │ │ │ │ ├── logger.baseDir.js │ │ │ │ │ └── logger.files.changed.js │ │ │ │ ├── options/ │ │ │ │ │ └── options.set.js │ │ │ │ ├── plugins/ │ │ │ │ │ ├── bs.options.js │ │ │ │ │ ├── connector.js │ │ │ │ │ ├── files.js │ │ │ │ │ ├── hooks.js │ │ │ │ │ ├── logger.js │ │ │ │ │ ├── options.js │ │ │ │ │ ├── ui.error.js │ │ │ │ │ ├── ui.js │ │ │ │ │ ├── user.plugins.add.middleware.js │ │ │ │ │ ├── user.plugins.cleanup.js │ │ │ │ │ ├── user.plugins.error.js │ │ │ │ │ ├── user.plugins.inline.enabled.js │ │ │ │ │ ├── user.plugins.inline.error.js │ │ │ │ │ ├── user.plugins.inline.js │ │ │ │ │ ├── user.plugins.inline.obj.js │ │ │ │ │ ├── user.plugins.inline.obj.reference.js │ │ │ │ │ ├── user.plugins.inline.options.js │ │ │ │ │ ├── user.plugins.js │ │ │ │ │ ├── user.plugins.proxy.js │ │ │ │ │ └── user.plugins.serve.files.js │ │ │ │ ├── resp-mod/ │ │ │ │ │ └── rewrite-links.js │ │ │ │ ├── server/ │ │ │ │ │ └── server.snippet.js │ │ │ │ └── utils/ │ │ │ │ ├── utils.connect.js │ │ │ │ ├── utils.default.callback.js │ │ │ │ ├── utils.fail.js │ │ │ │ ├── utils.getHostIp.js │ │ │ │ ├── utils.getUrl.js │ │ │ │ ├── utils.getUrls.js │ │ │ │ ├── utils.js │ │ │ │ ├── utils.setUrlOptions.js │ │ │ │ └── utils.verifyOptions.js │ │ │ └── utils.js │ │ └── tsconfig.json │ ├── browser-sync-client/ │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE-MIT │ │ ├── README.md │ │ ├── index.js │ │ ├── lib/ │ │ │ ├── browser.utils.ts │ │ │ ├── dom-effects/ │ │ │ │ ├── link-replace.dom-effect.ts │ │ │ │ ├── prop-set.dom-effect.ts │ │ │ │ ├── set-scroll.dom-effect.ts │ │ │ │ ├── set-window-name.dom-effect.ts │ │ │ │ └── style-set.dom-effect.ts │ │ │ ├── dom-effects.ts │ │ │ ├── effects/ │ │ │ │ ├── browser-reload.effect.ts │ │ │ │ ├── browser-set-location.effect.ts │ │ │ │ ├── file-reload.effect.ts │ │ │ │ ├── set-element-toggle-value.effect.ts │ │ │ │ ├── set-element-value.effect.ts │ │ │ │ ├── set-options.effect.ts │ │ │ │ ├── set-scroll.ts │ │ │ │ └── simulate-click.effect.ts │ │ │ ├── effects.ts │ │ │ ├── index.ts │ │ │ ├── listeners/ │ │ │ │ ├── clicks.listener.ts │ │ │ │ ├── form-inputs.listener.ts │ │ │ │ ├── form-toggles.listener.ts │ │ │ │ └── scroll.listener.ts │ │ │ ├── listeners.ts │ │ │ ├── log.ts │ │ │ ├── messages/ │ │ │ │ ├── BrowserLocation.ts │ │ │ │ ├── BrowserNotify.ts │ │ │ │ ├── BrowserReload.ts │ │ │ │ ├── ClickEvent.ts │ │ │ │ ├── Connection.ts │ │ │ │ ├── Disconnect.ts │ │ │ │ ├── FileReload.ts │ │ │ │ ├── FormToggleEvent.ts │ │ │ │ ├── KeyupEvent.ts │ │ │ │ ├── OptionsSet.ts │ │ │ │ └── ScrollEvent.ts │ │ │ ├── notify.ts │ │ │ ├── scroll-restore.ts │ │ │ ├── socket-messages.ts │ │ │ ├── socket.ts │ │ │ ├── types/ │ │ │ │ ├── socket.ts │ │ │ │ └── types.d.ts │ │ │ ├── types.ts │ │ │ ├── utils.ts │ │ │ └── vendor/ │ │ │ ├── Reloader.ts │ │ │ ├── Timer.ts │ │ │ └── logger.ts │ │ ├── package.json │ │ ├── test/ │ │ │ ├── .jshintrc │ │ │ ├── client-new/ │ │ │ │ ├── bs.options.js │ │ │ │ ├── code-sync.js │ │ │ │ ├── emitter.js │ │ │ │ ├── ghostmode.click.js │ │ │ │ ├── ghostmode.forms.inputs.js │ │ │ │ ├── ghostmode.forms.js │ │ │ │ ├── ghostmode.forms.submit.js │ │ │ │ ├── ghostmode.forms.toggles.js │ │ │ │ ├── ghostmode.js │ │ │ │ ├── ghostmode.location.js │ │ │ │ ├── ghostmode.scroll.js │ │ │ │ ├── index.js │ │ │ │ ├── libs/ │ │ │ │ │ └── assert.js │ │ │ │ ├── notify.js │ │ │ │ ├── socket.js │ │ │ │ ├── stubs/ │ │ │ │ │ └── bs.js │ │ │ │ └── utils.js │ │ │ ├── fixtures/ │ │ │ │ ├── css/ │ │ │ │ │ └── style.css │ │ │ │ ├── forms.html │ │ │ │ ├── index-large.html │ │ │ │ ├── index-urls.html │ │ │ │ ├── index.html │ │ │ │ ├── inputs.html │ │ │ │ ├── less.html │ │ │ │ ├── links.html │ │ │ │ ├── proxy-headers.html │ │ │ │ ├── proxy-ip.html │ │ │ │ ├── proxy-vhost.html │ │ │ │ ├── sass.html │ │ │ │ └── scrolling.html │ │ │ ├── karma.conf.ci.js │ │ │ ├── karma.conf.js │ │ │ ├── middleware/ │ │ │ │ ├── file.js │ │ │ │ └── middleware.js │ │ │ └── test.conf.js │ │ ├── tsconfig.json │ │ └── webpack.config.js │ └── browser-sync-ui/ │ ├── .editorconfig │ ├── .gitignore │ ├── .jshintrc │ ├── LICENSE │ ├── README.md │ ├── crossbow.yaml │ ├── example.stream.js │ ├── index.js │ ├── lib/ │ │ ├── UI.js │ │ ├── async-tasks.js │ │ ├── async.js │ │ ├── client-elements.js │ │ ├── client-js.js │ │ ├── config.js │ │ ├── directive-stripper.js │ │ ├── hooks.js │ │ ├── opts.js │ │ ├── plugins/ │ │ │ ├── connections/ │ │ │ │ ├── connections.client.js │ │ │ │ ├── connections.directive.html │ │ │ │ ├── connections.html │ │ │ │ ├── connections.plugin.js │ │ │ │ └── lib/ │ │ │ │ └── connections.js │ │ │ ├── help/ │ │ │ │ ├── help.client.js │ │ │ │ ├── help.directive.html │ │ │ │ ├── help.html │ │ │ │ └── help.plugin.js │ │ │ ├── history/ │ │ │ │ ├── history.client.js │ │ │ │ ├── history.directive.html │ │ │ │ ├── history.html │ │ │ │ ├── history.js │ │ │ │ └── history.plugin.js │ │ │ ├── network-throttle/ │ │ │ │ ├── network-throttle.client.js │ │ │ │ ├── network-throttle.directive.html │ │ │ │ ├── network-throttle.html │ │ │ │ ├── network-throttle.js │ │ │ │ ├── network-throttle.plugin.js │ │ │ │ ├── targets.js │ │ │ │ └── throttle-server.js │ │ │ ├── overview/ │ │ │ │ ├── overview.client.js │ │ │ │ ├── overview.html │ │ │ │ ├── overview.plugin.js │ │ │ │ ├── snippet-info.html │ │ │ │ └── url-info.html │ │ │ ├── plugins/ │ │ │ │ ├── plugins.client.js │ │ │ │ ├── plugins.html │ │ │ │ └── plugins.plugin.js │ │ │ ├── remote-debug/ │ │ │ │ ├── client-files.js │ │ │ │ ├── compression.html │ │ │ │ ├── compression.js │ │ │ │ ├── css/ │ │ │ │ │ ├── pesticide-depth.css │ │ │ │ │ └── pesticide.css │ │ │ │ ├── latency/ │ │ │ │ │ ├── latency.client.js │ │ │ │ │ ├── latency.html │ │ │ │ │ └── latency.js │ │ │ │ ├── no-cache.html │ │ │ │ ├── no-cache.js │ │ │ │ ├── overlay-grid/ │ │ │ │ │ ├── css/ │ │ │ │ │ │ ├── grid-overlay-horizontal.css │ │ │ │ │ │ └── grid-overlay-vertical.css │ │ │ │ │ ├── js/ │ │ │ │ │ │ └── grid-overlay.js │ │ │ │ │ ├── overlay-grid.client.js │ │ │ │ │ ├── overlay-grid.html │ │ │ │ │ └── overlay-grid.js │ │ │ │ ├── remote-debug.client.js │ │ │ │ ├── remote-debug.html │ │ │ │ └── remote-debug.plugin.js │ │ │ └── sync-options/ │ │ │ ├── sync-options.client.js │ │ │ ├── sync-options.html │ │ │ └── sync-options.plugin.js │ │ ├── resolve-plugins.js │ │ ├── server.js │ │ ├── transform.options.js │ │ ├── transforms.js │ │ ├── urls.js │ │ └── utils.js │ ├── package.json │ ├── public/ │ │ ├── css/ │ │ │ ├── components.css │ │ │ └── core.css │ │ ├── img/ │ │ │ └── icons/ │ │ │ └── preview.html │ │ ├── index.html │ │ └── js/ │ │ └── app.js │ ├── src/ │ │ ├── crossbow/ │ │ │ ├── _config.yml │ │ │ ├── _includes/ │ │ │ │ ├── enable.disable.hbs │ │ │ │ ├── form.input.checkbox.hbs │ │ │ │ ├── form.input.text.hbs │ │ │ │ ├── header.hbs │ │ │ │ ├── icon.hbs │ │ │ │ └── nav.hbs │ │ │ ├── _layouts/ │ │ │ │ ├── components.hbs │ │ │ │ ├── main.hbs │ │ │ │ └── parent.hbs │ │ │ ├── components/ │ │ │ │ ├── button-bars.hbs │ │ │ │ ├── buttons.hbs │ │ │ │ ├── footer.hbs │ │ │ │ ├── forms.hbs │ │ │ │ ├── header.hbs │ │ │ │ ├── heading.hbs │ │ │ │ ├── help-content.hbs │ │ │ │ ├── lists.hbs │ │ │ │ ├── panels.hbs │ │ │ │ ├── switches.hbs │ │ │ │ └── type.hbs │ │ │ ├── components.hbs │ │ │ ├── content/ │ │ │ │ └── help.content.hbs │ │ │ ├── help.hbs │ │ │ ├── history.hbs │ │ │ ├── network-throttle.hbs │ │ │ ├── plugins.hbs │ │ │ ├── remote-debug.hbs │ │ │ ├── server-info-snippet.hbs │ │ │ ├── server-info.hbs │ │ │ └── sync-options.hbs │ │ ├── scripts/ │ │ │ ├── angular.js │ │ │ ├── app.js │ │ │ ├── directives/ │ │ │ │ ├── icon.js │ │ │ │ ├── link-to.js │ │ │ │ ├── new-tab.js │ │ │ │ └── switch.js │ │ │ ├── directives.js │ │ │ ├── editor.js │ │ │ ├── filters.js │ │ │ ├── main/ │ │ │ │ └── controller.js │ │ │ ├── module.js │ │ │ ├── modules/ │ │ │ │ ├── bsClients.js │ │ │ │ ├── bsDisconnect.js │ │ │ │ ├── bsHistory.js │ │ │ │ ├── bsNotify.js │ │ │ │ ├── bsSocket.js │ │ │ │ └── bsStore.js │ │ │ ├── services/ │ │ │ │ ├── Options.js │ │ │ │ └── Pages.js │ │ │ └── utils.js │ │ ├── scss/ │ │ │ ├── _vars.scss │ │ │ ├── components.scss │ │ │ ├── core.scss │ │ │ ├── modules/ │ │ │ │ ├── _mixins.scss │ │ │ │ └── _reset.scss │ │ │ ├── theme/ │ │ │ │ ├── _animations.scss │ │ │ │ ├── _base.scss │ │ │ │ ├── _buttons.scss │ │ │ │ ├── _cloak.scss │ │ │ │ ├── _code.scss │ │ │ │ ├── _custom-icons.scss │ │ │ │ ├── _disconnect.scss │ │ │ │ ├── _footer.scss │ │ │ │ ├── _forms.scss │ │ │ │ ├── _grid.scss │ │ │ │ ├── _header.scss │ │ │ │ ├── _headings.scss │ │ │ │ ├── _helpers.scss │ │ │ │ ├── _links.scss │ │ │ │ ├── _lists.scss │ │ │ │ ├── _main-content.scss │ │ │ │ ├── _misc.scss │ │ │ │ ├── _msgs.scss │ │ │ │ ├── _notifications.scss │ │ │ │ ├── _panel.scss │ │ │ │ ├── _paragraphs.scss │ │ │ │ ├── _section-nav.scss │ │ │ │ ├── _sidebar.scss │ │ │ │ ├── _spinner.scss │ │ │ │ ├── _state.scss │ │ │ │ ├── _svg.scss │ │ │ │ ├── _switch.scss │ │ │ │ └── _top-bar.scss │ │ │ └── vendor/ │ │ │ ├── _fonts.scss │ │ │ └── _normalize.scss │ │ └── svg-template.tmpl │ ├── static/ │ │ ├── components/ │ │ │ ├── button-bars.html │ │ │ ├── buttons.html │ │ │ ├── footer.html │ │ │ ├── forms.html │ │ │ ├── header.html │ │ │ ├── heading.html │ │ │ ├── help-content.html │ │ │ ├── lists.html │ │ │ ├── panels.html │ │ │ ├── switches.html │ │ │ └── type.html │ │ └── content/ │ │ └── help.content.html │ ├── tasks/ │ │ ├── crossbow.js │ │ └── icons.js │ ├── templates/ │ │ ├── config.item.tmpl │ │ ├── config.tmpl │ │ ├── directives/ │ │ │ └── bs-switch.html │ │ ├── inline.template.tmpl │ │ ├── plugin.item.tmpl │ │ └── plugin.tmpl │ ├── test/ │ │ ├── .jshintrc │ │ ├── client/ │ │ │ └── e2e/ │ │ │ ├── bs-init.js │ │ │ ├── config.js │ │ │ ├── e2e.plugins.js │ │ │ ├── e2e.server-info.js │ │ │ ├── e2e.sync-options.js │ │ │ ├── test-utils.js │ │ │ └── tests/ │ │ │ ├── history.js │ │ │ ├── history.newtabs.js │ │ │ ├── home.js │ │ │ ├── network-throttle.auto.js │ │ │ ├── network-throttle.js │ │ │ ├── network-throttle.manual.js │ │ │ ├── network-throttle.remove.js │ │ │ ├── plugins.inline.js │ │ │ ├── plugins.js │ │ │ └── remote-debug.js │ │ ├── fixtures/ │ │ │ ├── content.html │ │ │ ├── css/ │ │ │ │ ├── blog.css │ │ │ │ └── bootstrap.css │ │ │ ├── forms.html │ │ │ ├── index.html │ │ │ ├── plugin/ │ │ │ │ ├── index.plugin.js │ │ │ │ ├── package.json │ │ │ │ └── ui/ │ │ │ │ ├── client.js │ │ │ │ ├── test.directive.html │ │ │ │ └── test.html │ │ │ ├── plugin-multi-templates/ │ │ │ │ ├── index.plugin.js │ │ │ │ ├── package.json │ │ │ │ └── ui/ │ │ │ │ ├── client.js │ │ │ │ ├── client2.js │ │ │ │ ├── test.directive.html │ │ │ │ ├── test.html │ │ │ │ └── test.list.html │ │ │ ├── plugin-noui/ │ │ │ │ ├── index.plugin.js │ │ │ │ └── package.json │ │ │ └── scrolling.html │ │ ├── opts.server.json │ │ ├── protractor.sh │ │ └── server/ │ │ ├── history/ │ │ │ └── history.js │ │ ├── init.js │ │ ├── plugins.js │ │ ├── plugins.templates.js │ │ └── remote-debug/ │ │ ├── client.files.js │ │ ├── latency.js │ │ ├── no-cache.js │ │ ├── throttle.https.js │ │ └── throttle.js │ └── webpack.config.js ├── playwright.config.ts └── tests/ ├── examples/ │ ├── basic/ │ │ └── basic.spec.ts │ ├── html-inject/ │ │ └── html-inject.spec.ts │ ├── snippet/ │ │ └── snippet.spec.ts │ └── tailwind/ │ └── tailwind.spec.ts └── utils.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.{css,js}] indent_size = 4 [*.md] trim_trailing_whitespace = false ================================================ FILE: .gitattributes ================================================ * text=auto ================================================ FILE: .github/workflows/main.yml ================================================ name: CI # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the master branch pull_request: branches: [ master ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest strategy: matrix: node-version: [16, 18, 20] # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - name: Setup Node.js environment uses: actions/setup-node@v2.5.0 with: node-version: ${{ matrix.node-version }} cache: npm cache-dependency-path: package-lock.json # Runs a single command using the runners shell - name: Install run: npm ci - name: Test run: npm test - name: Install Playwright Browsers run: npx playwright install --with-deps - name: Run Playwright tests run: npm run test:e2e - uses: actions/upload-artifact@v3 if: always() with: name: playwright-report path: playwright-report/ retention-days: 30 ================================================ FILE: .gitignore ================================================ node_modules .idea npm-debug.log .sass-cache test/fixtures/files/* test/fixtures/js/* example.server.js example.proxy.js example.snippet.js example.js .DS_store doc/ .coveralls.yml coverage/ /screenshots test/fixtures/multi/ before.json after.json bs-config.js /lodash.custom.min.js /dist /cypress/videos /cypress/screenshots/* client/dist/index.js client/dist/index.js.map client/dist/index.min.js client/dist/index.min.js.map node_modules/ /test-results/ /playwright-report/ /playwright/.cache/ ================================================ FILE: .travis.yml ================================================ git: depth: 2 language: node_js node_js: - "14" - "12" - "10" ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to Browsersync We'd love for you to contribute to Browsersync and help make it even better than it is today! Here are the guidelines we'd like you to follow: - [Question or Problem?](#question) - [Issues and Bugs](#issue) - [Tips for a creating a great issue report](#tips) - [Feature Requests](#feature) - [Pull Requests](#pull) - [Coding Rules](#rules) - [Thank you](#thanks) ## Got a Question or Problem? If you have questions about how to *use* Browsersync, or about your particular setup, please ask on [Stack Overflow](http://stackoverflow.com/). We're trying to keep the Issues thread for actual bugs with code & implementation. ## Found an Issue? On that note, if you think you *have* found a bug in Browsersync, please report it via [Github Issues](https://github.com/BrowserSync/browser-sync/issues). ## Tips for a creating a great issue report Whilst we do try to look at each and every issue as soon as possible, there are certain aspects about your report that will determine how quickly/deeply we'll delve into it. A great issue will contain at least the following: * Operating System + Version * Use case for Browsersync - are you using the built-in server, proxying your own server, or just using the snippet mode? * Example configuration - show us your full `gulpfile.js`, `Gruntfile.js`, `bs-config.js` or any other code related to how you're using Browsersync. If we have to respond to your very first issue report with "please provide information about how you're using Browsersync" then it's very likely to fall to the bottom of the heap. Help us out by providing as much detail as possible! * Provide a reduced test case. "Browsersync is not working with my app" is far less helpful than "Here's a example project showing the problem". An example project might contain a single `index.html` file with some JS/CSS from CDNs & a short description of the issue. If we can just pull a repo/gist and see the problem for ourselves, your issue will jump straight to the top of the stack. * Screencast or GIF - not always appropriate, but can be very helpful where possible. (non-issue related gifs are always welcome, we'll often respond with something from giphy :p) ## Want a Feature? You can request a new feature by submitting an issue to our [Github Issues](https://github.com/BrowserSync/browser-sync/issues) page. Prefix the title of your issue with "Feature Request:". ## Want a Doc Fix? Head over to the [Browsersync Website Repo](https://github.com/BrowserSync/browsersync.github.io) & submit issues there. ## Submitting a Pull Request Pull requests should always be branched off the main **Master** branch. (There's no guarantee that what lives on the develop branch will ever make it back to master, I do a **lot** of experimentation). **Never** commit directly to the master branch, instead create a new branch and submit a PR. This applies to users who have write access also. **Note:** If your first PR is merged, you'll get write access to all Browsersync repos. ## Coding Advice To ensure consistency throughout the source code, keep these rules in mind as you are working. * If you're not sure how to provide tests for a feature or bug fix, you should still submit it and we'll help you complete the PR in one of the following ways: * we can advise you how to go about it * we can write the test, and then explain them to you. * This project has a [.editorconfig](.editorconfig) file to help with code style; go to [EditorConfig.org](http://editorconfig.org) and download the plugin for your IDE. * Don't introduce any extra 3rd party libraries unless you're creating a brand new feature that requires it. * Try to keep your code simple and readable. * Improve my code! Browsersync has a lot of moving parts and I don't pretend to be skilled in any particular area. If *you* have particular experience though, then feel free to rip my code apart and tell me a better way to do something - I'll be extremely grateful (as will the growing number of users!). ## Thank you! If you contribute to Browsersync, or any other Open Source project, you're awesome! This project has been vastly improved by community input & contributions and we look forward to continuing that trend. ================================================ FILE: ISSUE_TEMPLATE.md ================================================ ### Issue details _Please provide issue details here_. ### Steps to reproduce/test case _Please provide necessary steps for reproduction of this issue, or better the reduced test case (without any external dependencies)_. ### Please specify which version of Browsersync, node and npm you're running - Browsersync [ ] - Node [ ] - Npm [ ] ### Affected platforms - [ ] linux - [ ] windows - [ ] OS X - [ ] freebsd - [ ] solaris - [ ] other _(please specify which)_ ### Browsersync use-case - [ ] API - [ ] Gulp - [ ] Grunt - [ ] CLI ### If CLI, please paste the entire command below {cli command here} ### for all other use-cases, (gulp, grunt etc), please show us exactly how you're using Browsersync {Browsersync init code here} ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2015] [Shane Osbourne] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================

Keep multiple browsers & devices in sync when building websites.

Follow @Browsersync on twitter for news & updates.

Ask questions on Discord

## Features Please visit [browsersync.io](https://browsersync.io) for a full run-down of features ## Requirements Browsersync works by injecting an asynchronous script tag (``) right after the `` tag during initial request. In order for this to work properly the `` tag must be present. Alternatively you can provide a custom rule for the snippet using [snippetOptions](https://www.browsersync.io/docs/options/#option-snippetOptions) ## Upgrading from 1.x to 2.x ? Providing you haven't accessed any internal properties, everything will just work as there are no breaking changes to the public API. Internally however, we now use an immutable data structure for storing/retrieving options. So whereas before you could access urls like this... ```js browserSync({server: true}, function(err, bs) { console.log(bs.options.urls.local); }); ``` ... you now access them in the following way: ```js browserSync({server: true}, function(err, bs) { console.log(bs.options.getIn(["urls", "local"])); }); ``` ## Install and trouble shooting [browsersync.io docs](https://browsersync.io) ## Integrations / recipes [Browsersync recipes](https://github.com/Browsersync/recipes) ## Support If you've found Browser-sync useful and would like to contribute to its continued development & support, please feel free to send a donation of any size - it would be greatly appreciated! [Support via PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=shakyshane%40gmail%2ecom&lc=US&item_name=browser%2dsync) ## Supported by Originally supported by [JH](https://www.wearejh.com) - they provided financial support as well as access to a professional designer to help with Branding. Apache 2 Copyright (c) 2021 Shane Osbourne ================================================ FILE: changelog.js ================================================ const {execSync} = require('child_process'); let [start, end] = process.argv.slice(2); if (!start || !end) { console.error('Must provide start and end tags'); console.error(' eg: v1.0 HEAD'); console.error(' eg: v1.0 v2.0'); process.exit(1); } const separator = `===END===`; const res = execSync(`git log -E --format=%H%n%s%b===END=== ${start}..${end}`); const sep = res.toString().split(separator); const output = sep .map((item, i) => { const [hash, ...body] = getParts(item, i); const bodyJoined = body.join('\n'); return [hash, bodyJoined]; }) // .filter(([, body]) => ) .map(([hash, bodyJoined]) => { const hasSection = /^[\w]+: [^ ]/.test(bodyJoined); if (hasSection) { const [section, body] = bodyJoined.split(/: /); return [hash, section, body]; } return [hash, 'misc', bodyJoined]; }) .reduce((acc, item) => { const [, section] = item; if (!acc[section]) { acc[section] = [item]; } else { acc[section].push(item); } return acc; }, {}); if (process.argv.indexOf('--json') > -1) { console.log(JSON.stringify(output, null, 2)); } else { Object.keys(output) .map(x => [x, output[x]]) .forEach(([section, items]) => { const header = `**${section}**`; console.log(header); items.forEach(([hash, section, body]) => { console.log(`- ${body} ${hash}`) }); console.log('') }); } function getParts(item, index) { const segs = item.split('\n'); if (index === 0) return segs; return segs.slice(1); } ================================================ FILE: examples/404.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will redirect all 404 requests to a * custom 404.html page * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init( { files: ["app/css/*.css"], server: { baseDir: "app" } }, function(err, bs) { bs.addMiddleware("*", function(req, res) { res.writeHead(302, { location: "404.html" }); res.end("Redirecting!"); }); } ); ================================================ FILE: examples/basic/run.js ================================================ const bs = require("../../packages/browser-sync/dist/index").create(); const path = require("path"); const serverDir = path.join(__dirname, "..", "..", "packages/browser-sync/test/fixtures"); bs.init( { server: serverDir, open: false, watch: true, online: false }, (err, bs) => { const message = { kind: "ready", urls: bs.options.get("urls").toJS(), cwd: serverDir }; if (process.send) { process.send(message); } else { console.log(message); } } ); ================================================ FILE: examples/callback.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example shows how you can access information about Browsersync when it's running * */ "use strict"; var browserSync = require("browser-sync").create(); var config = { proxy: "localhost:8000", files: ["app/css/*.css"] }; browserSync.init(config, function(err, bs) { // Full access to Browsersync object here console.log(bs.getOption("urls")); }); ================================================ FILE: examples/express.js ================================================ /** * * Install: * npm install browser-sync express * * Run: * node * * This example will create a server & use the `app` directory as the root * + use any custom routes you have registered with Express * */ "use strict"; var bs = require("browser-sync").create(); var express = require("express"); var router = express.Router(); var app = express(); /** * Catch a route like /user/2324 * and send a JSON response */ router.get("/user/:id", function(req, res) { res.send({ name: "shane", pets: ["cat", "hippo"], id: req.params.id }); }); /** * Register the route with Express */ app.use(router); /** * Start the Browsersync server and * load the express app as middleware */ bs.init({ server: "./app", middleware: [app] }); ================================================ FILE: examples/less.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will serve .less files * and allow them to be injected as a css file would be. * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ server: ["test/fixtures"], open: false, watch: true, injectFileTypes: ["css", "less"], middleware: [ (req, res, next) => { if (req.url.indexOf("bootstrap.less") > -1) { res.setHeader("content-type", "text/css"); } next(); } ] }); ================================================ FILE: examples/middleware.css.injection.js ================================================ /** * * Install: * npm install browser-sync less * * Run: * node * * This example will process less files on the file and auto-inject them into * all browsers. * * Instead of .css, use with the following * Configuration to enable a super-fast development workflow. * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ /** * Which files to watch for changes */ files: "src/*.less", /** * Base directory */ server: "app", /** * Add .less to the list of files that will cause injection (instead of reload) */ injectFileTypes: ["less"], /** * Catch all requests, if any are for .less files, recompile on the fly and * send back a CSS response */ middleware: function(req, res, next) { var parsed = require("url").parse(req.url); if (parsed.pathname.match(/\.less$/)) { return less(parsed.pathname).then(function(o) { res.setHeader("Content-Type", "text/css"); res.end(o.css); }); } next(); } }); function less(src) { var f = require("fs") .readFileSync("src/" + src) .toString(); return require("less").render(f); } ================================================ FILE: examples/notify-styles.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * */ "use strict"; var browserSync = require("../").create(); browserSync.init({ open: false, // Stop auto open browser notify: { styles: [ "display: none;", "padding: 6px 15px 3px;", "position: fixed;", "font-size: 40px;", "z-index: 9999;", "left: 0px;", "bottom: 0px;", "color: rgb(74, 74, 74);", "background-color: rgb(17, 17, 17);", "color: rgb(229, 229, 229);" ] }, server: { baseDir: "test/fixtures" } }); ================================================ FILE: examples/options.snippetOptions.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example shows how you can place the snippet anywhere. */ "use strict"; var path = require("path"); var browserSync = require("../packages/browser-sync").create(); var cwd = path.join(__dirname, ".."); var fixtures_dir = path.join(cwd, "packages/browser-sync/test/fixtures"); browserSync.init({ files: [path.join(fixtures_dir, "css/*.css")], server: fixtures_dir, snippetOptions: { rule: { match: /<\/head>/i, fn: function (snippet, match) { return snippet + match; }, }, }, }); ================================================ FILE: examples/proxy.gzip.js ================================================ /** * * Install: * npm install browser-sync compression * * Run: * node * * This example will proxy to your existing vhost * and serve gzipped responses * */ "use strict"; var browserSync = require("browser-sync").create(); var compression = require("compression"); browserSync.init({ files: ["app/css/*.css"], proxy: { target: "http://yourlocal.dev", middleware: compression() } }); ================================================ FILE: examples/proxy.headers.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example shows how to specify the proxy headers for each request * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], proxy: { target: "localhost:8000", reqHeaders: function(config) { /** * These are the default headers as a guide for you. * You can set whatever you want here. */ return { host: config.urlObj.host, "accept-encoding": "identity", agent: false }; } } }); ================================================ FILE: examples/proxy.localhost.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will wrap your existing server in a proxy url. * Use the new Proxy url to access your site. * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], proxy: "localhost:8000" }); ================================================ FILE: examples/proxy.middleware.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a proxy server and run middlewares * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], proxy: { target: "http://yourlocal.dev", middleware: function(req, res, next) { console.log(req.url); next(); } }, https: true }); ================================================ FILE: examples/proxy.middleware.multi.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a proxy server and run middlewares * */ "use strict"; var browserSync = require("browser-sync").create(); var fn1 = function(req, res, next) { console.log(req.url); next(); }; var fn2 = function(req, res, next) { console.log(req.headers); next(); }; browserSync.init({ files: ["app/css/*.css"], proxy: { target: "http://yourlocal.dev", middleware: [fn1, fn2] }, https: true }); ================================================ FILE: examples/proxy.proxyRes.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will proxy http://www.bbc.co.uk and * add headers to the response *after* it's returned from * the server. */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ proxy: { target: "http://www.bbc.co.uk", proxyRes: [ function(res) { res.headers["cache-control"] = "private"; } ] } }); ================================================ FILE: examples/proxy.rewriteRules.advanced.js ================================================ /** * * Install: * npm install browser-sync serve-static * * Run: * node * * This example will * 1. create a proxy server for a live magento website * 2. serve static assets from your local `assets` directory * 3. rewrite HTML on the fly to make the live site use your local assets * * eg: * becomes: * * eg: * becomes: * * 4. watch files in the assets directory and reload/inject when anything changes */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ proxy: "http://www.magento-site.com", files: ["assets"], middleware: require("serve-static")("."), rewriteRules: [ { match: new RegExp("skin/frontend/rwd/(.+?)(?=['\"])", "g"), replace: "assets/$1" } ] }); ================================================ FILE: examples/proxy.rewriteRules.simple.js ================================================ /** * * Install: * npm install browser-sync serve-static * * Run: * node * * This example will * 1. create a proxy server for a live magento website * 2. serve static assets from your local `assets` directory * 3. rewrite HTML on the fly to make the live site use your local assets/css/core.css file * * eg: * becomes: * * 4. watch files in the assets directory and reload/inject when anything changes */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ proxy: "http://www.magento-site.com", files: ["assets"], middleware: require("serve-static")("."), rewriteRules: [ { match: "skin/frontend/rwd/assets/css/core.min.css", replace: "assets/css/core.css" } ] }); ================================================ FILE: examples/proxy.secure.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a proxy server using https * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], proxy: "https://yourlocal.dev" }); ================================================ FILE: examples/proxy.vhost.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will wrap your existing server in a proxy url. * Use the new Proxy url to access your site. * */ var browserSync = require("browser-sync").create(); browserSync.init({ files: "app/css/*.css", proxy: "yourvhost.dev" }); ================================================ FILE: examples/server.basedir.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server & use the `app` directory as the root * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app" } }); ================================================ FILE: examples/server.basedir.mulitple.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server & use the `app` & `dist` directories for serving files * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: ["app", "dist"] } }); ================================================ FILE: examples/server.default.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server in the cwd. * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: true }); ================================================ FILE: examples/server.gzip.js ================================================ /** * * Install: * npm install browser-sync compression * * Run: * node * * This example will create a server with gzip enabled * */ "use strict"; var browserSync = require("browser-sync").create(); var compression = require("compression"); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app", middleware: compression() } }); ================================================ FILE: examples/server.http2.js ================================================ /** * * Install: * npm install browser-sync http2 * * Run: * node * * This example will create a server using http2 using the default information & use the `app` directory as the root * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app" }, https: true, httpModule: "http2" }); ================================================ FILE: examples/server.latency.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server & use the `app` directory as the root * - any requests beginning with /json will have fake latency applied * - for 3 seconds * */ "use strict"; var browserSync = require("browser-sync").create(); function fakeLatency(req, res, next) { if (req.url.match(/^\/json/)) { setTimeout(next, 3000); } else { next(); } } browserSync.init({ files: ["app/css/*.css"], server: "app", middleware: [fakeLatency] }); ================================================ FILE: examples/server.middleware.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server & use the `app` directory as the root * + use your custom middleware. Note: middleware will be added before * any Browsersync middlewares * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app", middleware: function(req, res, next) { console.log("hi from the middleware"); next(); } } }); ================================================ FILE: examples/server.middleware.multiple.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server & use the `app` directory as the root * + use your custom middleware. Note: middleware will be added before * any Browsersync middlewares * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app", middleware: [ function(req, res, next) { console.log("hi from the first middleware"); next(); }, function(req, res, next) { console.log("hi from the second middleware"); next(); } ] } }); ================================================ FILE: examples/server.proxy.js ================================================ /** * * Install: * npm install browser-sync express http-proxy-middleware * * Run: * node * * This example will create a server in the cwd whilst proxying requests * to /api to a backend * */ "use strict"; var browserSync = require("browser-sync").create(); var express = require('express'); var proxy = require('http-proxy-middleware'); var app = express(); app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true})); browserSync.init({ server: ".", watch: true, middleware: [app] }); ================================================ FILE: examples/server.secure.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server using https using the default information & use the `app` directory as the root * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app" }, https: true }); ================================================ FILE: examples/server.secure.pfx.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server using https using a PFX certificate & use the `app` directory as the root * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ files: ["app/css/*.css"], server: { baseDir: "app" }, https: { pfx: "certs/browsersync.pfx" } }); ================================================ FILE: examples/server.watch.js ================================================ /** * * Install: * npm install browser-sync * * Run: * node * * This example will create a server using https using the default information & use the `app` directory as the root * */ "use strict"; var browserSync = require("browser-sync").create(); browserSync.init({ server: "test/fixtures", watch: true }); ================================================ FILE: examples/snippet/index.html ================================================ Document

Hello world

================================================ FILE: examples/snippet/run.js ================================================ const bs = require("../../packages/browser-sync/dist/index").create(); bs.init( { server: ".", open: false, notify: false, watch: true, snippetOptions: { rule: { match: /<\/head>/i, fn: function(snippet, match) { return snippet + match; } } } }, (err, bs) => { const message = { kind: "ready", urls: bs.options.get("urls").toJS(), cwd: __dirname }; if (process.send) { process.send(message); } else { console.log(message); } } ); ================================================ FILE: lerna.json ================================================ { "packages": [ "packages/*" ], "version": "3.0.4" } ================================================ FILE: nx.json ================================================ { "tasksRunnerOptions": { "default": { "runner": "nx/tasks-runners/default", "options": { "cacheableOperations": [ "build" ] } } }, "targetDefaults": { "build": { "dependsOn": [ "^build" ] } } } ================================================ FILE: package.json ================================================ { "private": true, "name": "browser-sync-mono", "scripts": { "bootstrap": "lerna bootstrap", "postinstall": "npm run bootstrap", "test": "lerna run build && lerna run test --scope browser-sync", "test:e2e": "echo skipping cypress", "test:playwright": "playwright test" }, "devDependencies": { "lerna": "^6.1.0" }, "dependencies": { "@playwright/test": "^1.43.0", "rxjs": "^7.5.4", "zod": "^3.22.2" }, "nx": {} } ================================================ FILE: packages/browser-sync/.gitignore ================================================ /dist/* ================================================ FILE: packages/browser-sync/.prettierignore ================================================ ================================================ FILE: packages/browser-sync/certs/gen.sh ================================================ openssl genrsa -des3 -out server.key 2048 openssl req -new -key server.key -out server.csr openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt cp server.key server.key.copy openssl rsa -in server.key.copy -out server.key rm server.key.copy ================================================ FILE: packages/browser-sync/certs/server.crt ================================================ -----BEGIN CERTIFICATE----- MIIDBjCCAe4CCQCir/8eGDIE/jANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJH QjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 cyBQdHkgTHRkMB4XDTE3MDQxMDExNDcyNloXDTI3MDQwODExNDcyNlowRTELMAkG A1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AMRLR2crKB4X/9pM3gR641iDscZWW3aqo70nUDxzo5Bhk8uupqz0EfdRoCLCUeQi xVp3HJ1HqnilMW7dETGGkDHKdxJRjrkBrYHhE3Kw/LCC4tEb400F6Ikm6OudVPIB P+CuwfNAw70KHSx/CtIrbTz0HhDC6XN0azp39pDLRBnWWluz3iU+rFLMx7YT2Q8k 1nQAwcXkzLjeU7txAt2pYGQUgvBQETO5RI7QQ0CmwaV4gfHWGABBTX34WQun7g1Q YukrG3/4fVeNLzGW787FKCvL07BTymJTwXXbTTPXg4chw9p+YkLLPrr+AOVe/PF1 MJppDT3gKdKMHFo3vMycUf0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAEVmUYRrT fCQmBDox3evqj4n8dJVStjgdw/7BPkm49SmGtaxsST/eUSGwT7dTvZBLov6BK/OW +arhHZIvUY/DXlsV4NfCM4TK8KVefrwgd8ZsfQJW73L+FB0IOAY/6s+YKHm/wQGF ptSOycJvEltsqfIegtYcvvD6c6SkSOvqApaF+Ai10+yiLe20KyOvM3PefZLV7mFE 0zCNyglZ75HftvHHV0wh82T2Et/R+txH+6dTwh065Dd6rrDzljtcAd2HC7B26ERK dA2zJd9Y4eMz8osacmG/afVuR9rqtFGwdyZ1Kb5xQRzGWlrjvSmAFUx9W9iA4Ilv 3+56a5njSTFYKw== -----END CERTIFICATE----- ================================================ FILE: packages/browser-sync/certs/server.csr ================================================ -----BEGIN CERTIFICATE REQUEST----- MIICoTCCAYkCAQAwRTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUx ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMRLR2crKB4X/9pM3gR641iDscZWW3aqo70nUDxz o5Bhk8uupqz0EfdRoCLCUeQixVp3HJ1HqnilMW7dETGGkDHKdxJRjrkBrYHhE3Kw /LCC4tEb400F6Ikm6OudVPIBP+CuwfNAw70KHSx/CtIrbTz0HhDC6XN0azp39pDL RBnWWluz3iU+rFLMx7YT2Q8k1nQAwcXkzLjeU7txAt2pYGQUgvBQETO5RI7QQ0Cm waV4gfHWGABBTX34WQun7g1QYukrG3/4fVeNLzGW787FKCvL07BTymJTwXXbTTPX g4chw9p+YkLLPrr+AOVe/PF1MJppDT3gKdKMHFo3vMycUf0CAwEAAaAXMBUGCSqG SIb3DQEJBzEIDAYxMjM0NTYwDQYJKoZIhvcNAQELBQADggEBABlVUaWK/UUovgPZ +rqNG8/j6aggSCCye9CkauLB/WqhQFfLl9lWTYdUVmWweNU0SJwDU9lWF/TngipF RZs6501DkXKxaDT9/3JYg4lRz6zHLy+a77pavJOeN0+cFAPZZuGyxZvYHFYPVSVH EeJL6bO/nZ/ARgIp0YNkQblDarxq1ARj7YT1Z24D5KgO1kQ55+fCY/wtct8TLGk9 ujvWBbFEBSrJCDjRQeSctlP5qG8yfeJqZwZzo4PQMUwABhNLGUz0z0ceK8W1QnOm T+nCN5Fni04wO4dAZvYPp6wmU0Gpi2XBihbFl9CT3B5AmJmM8hQVpuQlmXeXT0FO pOZFpko= -----END CERTIFICATE REQUEST----- ================================================ FILE: packages/browser-sync/certs/server.key ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAxEtHZysoHhf/2kzeBHrjWIOxxlZbdqqjvSdQPHOjkGGTy66m rPQR91GgIsJR5CLFWnccnUeqeKUxbt0RMYaQMcp3ElGOuQGtgeETcrD8sILi0Rvj TQXoiSbo651U8gE/4K7B80DDvQodLH8K0ittPPQeEMLpc3RrOnf2kMtEGdZaW7Pe JT6sUszHthPZDyTWdADBxeTMuN5Tu3EC3algZBSC8FARM7lEjtBDQKbBpXiB8dYY AEFNffhZC6fuDVBi6Ssbf/h9V40vMZbvzsUoK8vTsFPKYlPBddtNM9eDhyHD2n5i Qss+uv4A5V788XUwmmkNPeAp0owcWje8zJxR/QIDAQABAoIBADbeT/wvnQwkazkL CXg5HXltfnDRTMmz0wcZiR0MueiuzdA+ZoqrwqXeJCPzK07YxU+PQelY0fbdPh8e HiM42O+CB5yQPZPLO0O1tWj2vftc6qfG4tdx0lkcDjlmBguLe96DGuWy8cPSousA K/cpemRyXEEVKopCPYLfa4V3u/Z4be2U/39KNjVkHFhSdSYQl6ferhEfUPwTPi7O 7l1/QUBabqN5FzNc2TeMVhhcJkXtYqF3RxGsaRfT0lK/j2hpbX7Bn2T0CfA/40jY 2OCERqFPfZWx/ShTT52b3fyX/FEua7Nukq/MZdYZou63dDIjCQQyTJSflX6lVojO SuUoumECgYEA6CSkLiKcRLlTfec3LkjqkWtXR5ibL33g/H1fsZEQKFOyMbIXpUkX Hybpku8NGeetjKynO3yRirp+NiBHGPn3cHc9WJ5GGG1ew9hRQ9QzyC3Tit15TDbu J8i50/MaQHZSiUCnPQ/ceIZCNz8STcsEz87o/7utRLJKOvIIAPj+/8kCgYEA2Hd/ v5oUroMRbtzPtMJDMHiGEQyNxEGDNqcuxgXSmiEEqPLfk2qR3yLffzA9UQOg4wkX /dSXsyomPriKWTvADXu1lNdkPGmW/1tk+onnHu6qgOalva30ZKhtteVjUqxEJEke mHhNHyIVuj6lExLw9LZhVvzoOi+aj4AD+DRS4pUCgYBEtuveOCJ3eUAMiY9c5PqB 9vsL11FAOouJUXcs8VqOBVA+w4+aPktYzkTfWGFRZLGLbWPHCPVv0gof7Wf+Laef o7wF6junaWBeqj5LzJlTTLVMaohIFg5iuli/Mzt3D08ZD4kxWuuQxXT+M24wlsKi 3IU9hYkhR4EPd6sE1q9seQKBgEpQRBAgModywbJgpgH1SyHBzqzdtXGx1/0USg97 gkCdoz7pGm4+gNOs4jOE+Rft+fbXcWAX8vh0OOsBaaWWyKkYVk9B3syKp2cFFlaY rzrETs6v4CiNJsDDvd5bYMzKDR6z54gKjNdqWTE2Pm+c6hHo5uP5MTSAkTxAg5xb QjU9AoGAaYPXlm3IKVO12FgNg/ffduooi0PKa1yRNJGnhpQKNvBQXs8eV+CQ83aK kQHUExuJDrOfsC2iwF/2ZywXhEfbhL7ar0aw5zrhV+r7qvYFWxu/YoLoNVMDByw5 wAN0oIbsGWYmtIIti8+b9IcacTbAZ79ctlTLb1HCyPMosHxDkv8= -----END RSA PRIVATE KEY----- ================================================ FILE: packages/browser-sync/cli-options/opts.init.json ================================================ {} ================================================ FILE: packages/browser-sync/cli-options/opts.recipe.json ================================================ { "output": { "alias": "o", "desc": "Specify an output directory" } } ================================================ FILE: packages/browser-sync/cli-options/opts.reload.json ================================================ { "files": { "desc": "File paths to reload", "type": "array", "alias": "f" }, "port": { "alias": "p", "type": "number", "desc": "Target a running instance by port number" }, "url": { "alias": "u", "desc": "Provide the full the url to the running Browsersync instance" } } ================================================ FILE: packages/browser-sync/cli-options/opts.start.json ================================================ { "server": { "alias": "s", "desc": "Run a Local server (uses your cwd as the web root)" }, "cwd": { "type": "string", "desc": "Working directory" }, "json": { "type": "boolean", "desc": "If true, certain logs will output as json only" }, "serveStatic": { "type": "array", "alias": "ss", "desc": "Directories to serve static files from" }, "port": { "type": "number", "desc": "Specify a port to use" }, "proxy": { "alias": "p", "desc": "Proxy an existing server", "example": "$0 shane is cool" }, "ws": { "type": "boolean", "desc": "Proxy mode only - enable websocket proxying" }, "browser": { "type": "array", "alias": "b", "desc": "Choose which browser should be auto-opened" }, "watch": { "type": "boolean", "alias": "w", "desc": "Watch files" }, "ignore": { "type": "array", "desc": "Ignore patterns for file watchers" }, "files": { "type": "array", "alias": "f", "desc": "File paths to watch" }, "index": { "type": "string", "desc": "Specify which file should be used as the index page" }, "plugins": { "type": "array", "desc": "Load Browsersync plugins" }, "extensions": { "type": "array", "desc": "Specify file extension fallbacks" }, "startPath": { "type": "string", "desc": "Specify the start path for the opened browser" }, "single": { "type": "boolean", "desc": "If true, the connect-history-api-fallback middleware will be added" }, "https": { "desc": "Enable SSL for local development" }, "directory": { "type": "boolean", "desc": "Show a directory listing for the server" }, "tunnel": { "desc": "Use a public URL" }, "open": { "type": "string", "desc": "Choose which URL is auto-opened (local, external or tunnel), or provide a url" }, "cors": { "type": "boolean", "desc": "Add Access Control headers to every request" }, "config": { "type": "string", "alias": "c", "desc": "Specify a path to a configuration file" }, "host": { "desc": "Specify a hostname to use" }, "listen": { "desc": "Specify a hostname bind to (this will prevent binding to all interfaces)" }, "logLevel": { "desc": "Set the logger output level (silent, info or debug)" }, "reload-delay": { "type": "number", "desc": "Time in milliseconds to delay the reload event following file changes" }, "reload-debounce": { "type": "number", "desc": "Restrict the frequency in which browser:reload events can be emitted to connected clients" }, "ui-port": { "type": "number", "desc": "Specify a port for the UI to use" }, "watchEvents": { "type": "array", "desc": "Specify which file events to respond to" }, "no-notify": { "desc": "Disable the notify element in browsers" }, "no-open": { "desc": "Don't open a new browser window" }, "no-snippet": { "desc": "Disable the snippet injection" }, "no-online": { "desc": "Force offline usage" }, "no-ui": { "desc": "Don't start the user interface" }, "no-ghost-mode": { "desc": "Disable Ghost Mode" }, "no-inject-changes": { "desc": "Reload on every file change" }, "no-reload-on-restart": { "desc": "Don't auto-reload all browsers following a restart" } } ================================================ FILE: packages/browser-sync/lib/args.js ================================================ "use strict"; /** * The purpose of this function is * to handle back-backwards compatibility * @param {Object} args * @returns {{config: {}, cb: *}} */ module.exports = function(args) { var config = {}; var cb; switch (args.length) { case 1: if (isFilesArg(args[0])) { config.files = args[0]; } else if (typeof args[0] === "function") { cb = args[0]; } else { config = args[0]; } break; case 2: // if second is a function, first MUST be config if (typeof args[1] === "function") { config = args[0] || {}; cb = args[1]; } else { if (args[1] === null || args[1] === undefined) { config = args[0]; } else { // finally, second arg could be a plain object for config config = args[1] || {}; if (!config.files) { config.files = args[0]; } } } break; case 3: config = args[1] || {}; if (!config.files) { config.files = args[0]; } cb = args[2]; } return { config: config, cb: cb }; }; /** * Files args were only ever strings or arrays * @param arg * @returns {*|boolean} */ function isFilesArg(arg) { return Array.isArray(arg) || typeof arg === "string"; } ================================================ FILE: packages/browser-sync/lib/async-tasks.js ================================================ var async = require("./async"); module.exports = [ { step: "Finding an empty port", fn: async.getEmptyPort }, { step: "Getting an extra port for Proxy", fn: async.getExtraPortForProxy }, { step: "Checking online status", fn: async.getOnlineStatus }, { step: "Resolve user plugins from options", fn: async.resolveInlineUserPlugins }, { step: "Set Urls and other options that rely on port/online status", fn: async.setOptions }, { step: "Setting Internal Events", fn: async.setInternalEvents }, { step: "Setting file watchers", fn: async.setFileWatchers }, { step: "Merging middlewares from core + plugins", fn: async.mergeMiddlewares }, { step: "Starting the Server", fn: async.startServer }, { step: "Starting the HTTPS Tunnel", fn: async.startTunnel }, { step: "Starting the web-socket server", fn: async.startSockets }, { step: "Starting the UI", fn: async.startUi }, { step: "Merge UI settings", fn: async.mergeUiSettings }, { step: "Init user plugins", fn: async.initUserPlugins } ]; ================================================ FILE: packages/browser-sync/lib/async.js ================================================ "use strict"; var _ = require("./lodash.custom"); var Immutable = require("immutable"); var utils = require("./utils"); var pluginUtils = require("./plugins"); var connectUtils = require("./connect-utils"); var chalk = require("chalk"); module.exports = { /** * BrowserSync needs at least 1 free port. * It will check the one provided in config * and keep incrementing until an available one is found. * @param {BrowserSync} bs * @param {Function} done */ getEmptyPort: function(bs, done) { utils.getPorts(bs.options, function(err, port) { if (err) { return utils.fail(true, err, bs.cb); } bs.debug("Found a free port: %s", chalk.magenta(port)); done(null, { options: { port: port } }); }); }, /** * If the running mode is proxy, we'll use a separate port * for the Browsersync web-socket server. This is to eliminate any issues * with trying to proxy web sockets through to the users server. * @param bs * @param done */ getExtraPortForProxy: function(bs, done) { /** * An extra port is not needed in snippet/server mode */ if (bs.options.get("mode") !== "proxy") { return done(); } /** * Web socket support is disabled by default */ if (!bs.options.getIn(["proxy", "ws"])) { return done(); } /** * Use 1 higher than server port by default... */ var socketPort = bs.options.get("port") + 1; /** * Or use the user-defined socket.port option instead */ if (bs.options.hasIn(["socket", "port"])) { socketPort = bs.options.getIn(["socket", "port"]); } utils.getPort( bs.options.get("listen", "localhost"), socketPort, null, function(err, port) { if (err) { return utils.fail(true, err, bs.cb); } done(null, { optionsIn: [ { path: ["socket", "port"], value: port } ] }); } ); }, /** * Some features require an internet connection. * If the user did not provide either `true` or `false` * for the online option, we will attempt to resolve www.google.com * as a way of determining network connectivity * @param {BrowserSync} bs * @param {Function} done */ getOnlineStatus: function(bs, done) { if ( _.isUndefined(bs.options.get("online")) && _.isUndefined(process.env.TESTING) ) { require("dns").resolve("www.google.com", function(err) { var online = false; if (err) { bs.debug( "Could not resolve www.google.com, setting %s", chalk.magenta("online: false") ); } else { bs.debug( "Resolved www.google.com, setting %s", chalk.magenta("online: true") ); online = true; } done(null, { options: { online: online } }); }); } else { done(); } }, /** * Try to load plugins that were given in options * @param {BrowserSync} bs * @param {Function} done */ resolveInlineUserPlugins: function(bs, done) { var plugins = bs.options .get("plugins") .map(pluginUtils.resolvePlugin) .map(pluginUtils.requirePlugin); plugins.forEach(function(plugin) { if (plugin.get("errors").size) { return logPluginError(plugin); } var jsPlugin = plugin.toJS(); jsPlugin.options = jsPlugin.options || {}; jsPlugin.options.moduleName = jsPlugin.moduleName; bs.registerPlugin(jsPlugin.module, jsPlugin.options); }); function logPluginError(plugin) { utils.fail(true, plugin.getIn(["errors", 0]), bs.cb); } done(); }, /** * * @param {BrowserSync} bs * @param {Function} done */ setOptions: function(bs, done) { done(null, { options: { urls: utils.getUrlOptions(bs.options), snippet: connectUtils.enabled(bs.options) ? connectUtils.scriptTags(bs.options) : false, scriptPaths: Immutable.fromJS( connectUtils.clientScript(bs.options, true) ), files: bs.pluginManager.hook( "files:watch", bs.options.get("files"), bs.pluginManager.pluginOptions ) } }); }, /** * @param {BrowserSync} bs * @param {Function} done */ setInternalEvents: function(bs, done) { require("./internal-events")(bs); done(); }, /** * @param {BrowserSync} bs * @param {Function} done */ setFileWatchers: function(bs, done) { done(null, { instance: { watchers: bs.pluginManager.get("file:watcher")(bs) } }); }, /** * @param {BrowserSync} bs * @param {Function} done */ mergeMiddlewares: function(bs, done) { done(null, { options: { middleware: bs.pluginManager.hook( "server:middleware", bs.options.get("middleware") ) } }); }, /** * @param {BrowserSync} bs * @param {Function} done */ startServer: function(bs, done) { var server = bs.pluginManager.get("server")(bs); done(null, { instance: { server: server.server, app: server.app } }); }, /** * @param {BrowserSync} bs * @param {Function} done */ startTunnel: function(bs, done) { if (bs.options.get("tunnel") && bs.options.get("online")) { var localTunnel = require("./tunnel"); localTunnel(bs, function(err, tunnel) { if (err) { if (err.code === "MODULE_NOT_FOUND") { return utils.fail(true, err, bs.cb); } return done(err); } else { return done(null, { optionsIn: [ { path: ["urls", "tunnel"], value: tunnel.url } ], instance: { tunnel: tunnel } }); } }); } else { done(); } }, /** * @param {BrowserSync} bs * @param {Function} done */ startSockets: function(bs, done) { var clientEvents = bs.pluginManager.hook( "client:events", bs.options.get("clientEvents").toJS() ); // Start the socket, needs an existing server. var io = bs.pluginManager.get("socket")(bs.server, clientEvents, bs); done(null, { instance: { io: io }, options: { clientEvents: Immutable.fromJS(clientEvents) } }); }, /** * * @param {BrowserSync} bs * @param {Function} done */ startUi: function(bs, done) { var PLUGIN_NAME = "UI"; var userPlugins = bs.getUserPlugins(); var ui = bs.pluginManager.get(PLUGIN_NAME); var uiOpts = bs.options.get("ui"); if (!uiOpts || uiOpts.get("enabled") === false) { return done(); } // if user provided a UI, use it instead if ( userPlugins.some(function(item) { return item.name === PLUGIN_NAME; }) ) { uiOpts = bs.options .get("ui") .mergeDeep( Immutable.fromJS( bs.pluginManager.pluginOptions[PLUGIN_NAME] ) ); } /** * Append the 'listen' option */ const opts = uiOpts.update(uiOpts => { const listen = bs.options.get("listen"); if (listen) { return uiOpts.set("listen", listen); } return uiOpts; }); return ui(opts.toJS(), bs, function(err, ui) { if (err) { return done(err); } done(null, { instance: { ui: ui } }); }); }, /** * @param {BrowserSync} bs * @param {Function} done */ mergeUiSettings: function(bs, done) { if (!bs.ui) { return done(); } done(null, { options: { urls: bs.options.get("urls").merge(bs.ui.options.get("urls")) } }); }, /** * @param {BrowserSync} bs * @param {Function} done */ initUserPlugins: function(bs, done) { bs.pluginManager.initUserPlugins(bs); done(null, { options: { userPlugins: bs.getUserPlugins() } }); } }; ================================================ FILE: packages/browser-sync/lib/bin.ts ================================================ #!/usr/bin/env node const startOpts = require("../cli-options/opts.start.json"); const reloadOpts = require("../cli-options/opts.reload.json"); const recipeOpts = require("../cli-options/opts.recipe.json"); const chalk = require("chalk"); const pkg = require("../package.json"); import * as utils from "./utils"; import { resolve } from "path"; import { existsSync } from "fs"; import { logger } from "./logger"; import { printErrors } from "./cli/cli-options"; export enum BsErrorLevels { Fatal = "Fatal" } export enum BsErrorTypes { PathNotFound = "PathNotFound", HostAndListenIncompatible = "HostAndListenIncompatible" } export type BsErrors = BsError[]; export interface BsError { type: BsErrorTypes; level: BsErrorLevels; errors: BsErrorItem[]; } export interface BsErrorItem { error: Error; meta?(...args): string[]; } /** * Handle cli input */ if (!module.parent) { runFromCli(); } function freshYargs() { return require("yargs")(process.argv.slice(2)); } function runFromCli() { const yargs = freshYargs() .command("start", "Start the server") .command("init", "Create a configuration file") .command("reload", "Send a reload event over HTTP protocol") .command("recipe", "Generate the files for a recipe") .version(pkg.version) .help(false) .epilogue( [ "For help running a certain command, type --help", " $0 start --help", "", "You can run a static server by providing a path(s) directly", " $0 app/src app/tmp", "", "If the directory contains a 'index.html' file, you can omit any input", " $0", "", "You can run the proxy in this manner too", " $0 https://example.com", "", "To run a proxy, whilst also serving static files", " $0 https://example.com htdocs/themes/example" ].join("\n") ); const argv = yargs.argv; const input = argv._; const command = input[0]; const valid = ["start", "init", "reload", "recipe"]; if (valid.indexOf(command) > -1) { return handleIncoming(command, freshYargs()); } if (input.length) { return handleNoCommand(argv, input, freshYargs()); } if (existsSync("index.html")) { return handleNoCommand(argv, ["."], freshYargs()); } yargs.showHelp(); } /** * Feature: If no command was specified, try to do the 'right thing' * * If paths were given, start the server * eg: browser-sync app/code app/design * is equal to: browser-sync start --server app/code app/design * * eg: browser-sync http://example.com * is equal to: browser-sync start --proxy http://example.com * * eg: browser-sync http://example.com themes/example * is equal to: browser-sync start --proxy http://example.com --ss themes/example * * @param argv * @param input * @returns {any} */ function handleNoCommand(argv, input, yargs) { const processed = processStart(yargs); const paths = input.map(path => { const resolved = resolve(path); const isUrl = /^https?:\/\//.test(path); return { isUrl, userInput: path, resolved, errors: isUrl ? [] : pathErrors(path, resolved) }; }); const withErrors = paths.filter(item => item.errors.length); const withoutErrors = paths.filter(item => item.errors.length === 0); if (withErrors.length) { withErrors.forEach(item => { logger.unprefixed("error", printErrors(item.errors)); }); return process.exit(1); } const serveStaticPaths = withoutErrors .filter(item => item.isUrl === false) .map(item => item.resolved); const urls = withoutErrors .filter(item => item.isUrl === true) .map(item => item.userInput); /** * If a URL was given, switch to proxy mode and use * any other paths as serveStatic options */ if (urls.length) { const proxy = urls[0]; const config = { ...processed, proxy, serveStatic: serveStaticPaths }; return handleCli({ cli: { flags: config, input: ["start"] } }); } /** * if NO urls were given switch directly to server mode * @type {{server: {baseDir: any}}} */ const config = { ...processed, server: { baseDir: serveStaticPaths } }; return handleCli({ cli: { flags: config, input: ["start"] } }); } /** * @param {{cli: object, [whitelist]: array, [cb]: function}} opts * @returns {*} */ function handleCli(opts) { opts.cb = opts.cb || utils.defaultCallback; const m = require(`./cli/command.${opts.cli.input[0]}`); if (m.default) { return m.default(opts); } return m(opts); } export default handleCli; function processStart(yargs) { return yargs .usage("Usage: $0 start [options]") .options(startOpts) .example("$0 start -s app", "- Use the App directory to serve files") .example("$0 start -p www.bbc.co.uk", "- Proxy an existing website") .default("cwd", () => process.cwd()) .argv; } /** * @param {string} command * @param {object} yargs * @param cwd */ function handleIncoming(command, yargs) { let out; if (command === "start") { out = processStart(yargs); } if (command === "init") { out = yargs .usage("Usage: $0 init") .example("$0 init") .default("cwd", () => process.cwd()) .help().argv; } if (command === "reload") { out = yargs .usage("Usage: $0 reload") .options(reloadOpts) .example("$0 reload") .example("$0 reload --port 4000") .default("cwd", () => process.cwd()) .argv; } if (command === "recipe") { out = yargs .usage("Usage: $0 recipe ") .option(recipeOpts) .example("$0 recipe ls", "list the recipes") .example("$0 recipe gulp.sass", "use the gulp.sass recipe") .default("cwd", () => process.cwd()) .argv; } if (out.help) { return yargs.showHelp(); } handleCli({ cli: { flags: out, input: out._ } }); } function pathErrors(input, resolved): BsErrors { if (!existsSync(resolved)) { return [ { type: BsErrorTypes.PathNotFound, level: BsErrorLevels.Fatal, errors: [ { error: new Error(`Path not found: ${input}`), meta() { return [ `Your Input: ${chalk.yellow(input)}`, `CWD: ${chalk.yellow(process.cwd())}`, `Resolved to: ${chalk.yellow(resolved)}` ]; } } ] } ]; } return []; } ================================================ FILE: packages/browser-sync/lib/browser-sync.js ================================================ "use strict"; var hooks = require("./hooks"); var asyncTasks = require("./async-tasks"); var config = require("./config"); var connectUtils = require("./connect-utils"); var utils = require("./utils"); var logger = require("./logger"); var chalk = require("chalk"); var eachSeries = utils.eachSeries; var _ = require("./lodash.custom"); var EE = require("easy-extender"); /** * Required internal plugins. * Any of these can be overridden by deliberately * causing a name-clash. */ var defaultPlugins = { logger: logger, socket: require("./sockets"), "file:watcher": require("./file-watcher"), server: require("./server"), tunnel: require("./tunnel"), "client:script": require("browser-sync-client"), UI: require("browser-sync-ui") }; /** * @constructor */ var BrowserSync = function(emitter) { var bs = this; bs.cwd = process.cwd(); bs.active = false; bs.paused = false; bs.config = config; bs.utils = utils; bs.events = bs.emitter = emitter; bs._userPlugins = []; bs._reloadQueue = []; bs._cleanupTasks = []; bs._browserReload = false; // Plugin management bs.pluginManager = new EE(defaultPlugins, hooks); }; /** * Call a user-options provided callback * @param name */ BrowserSync.prototype.callback = function(name) { var bs = this; var cb = bs.options.getIn(["callbacks", name]); if (_.isFunction(cb)) { cb.apply(bs.publicInstance, _.toArray(arguments).slice(1)); } }; /** * @param {Map} options * @param {Function} cb * @returns {BrowserSync} */ BrowserSync.prototype.init = function(options, cb) { /** * Safer access to `this` * @type {BrowserSync} */ var bs = this; /** * Set user-provided callback, or assign a noop * @type {Function} */ bs.cb = cb || utils.defaultCallback; /** * Verify provided config. * Some options are not compatible and will cause us to * end the process. */ if (!utils.verifyConfig(options, bs.cb)) { return; } /** * Save a reference to the original options * @type {Map} * @private */ bs._options = options; /** * Set additional options that depend on what the * user may of provided * @type {Map} */ bs.options = options; /** * Kick off default plugins. */ bs.pluginManager.init(); /** * Create a base logger & debugger. */ bs.logger = bs.pluginManager.get("logger")(bs.events, bs); bs.debugger = bs.logger.clone({ useLevelPrefixes: true }); bs.debug = bs.debugger.debug; /** * Run each setup task in sequence */ eachSeries(asyncTasks, taskRunner(bs), tasksComplete(bs)); return this; }; /** * Run 1 setup task. * Each task is a pure function. * They can return options or instance properties to set, * but they cannot set them directly. * @param {BrowserSync} bs * @returns {Function} */ function taskRunner(bs) { return function(item, cb) { bs.debug("-> %s", chalk.yellow("Starting Step: " + item.step)); /** * Execute the current task. */ item.fn(bs, executeTask); function executeTask(err, out) { /** * Exit early if any task returned an error. */ if (err) { return cb(err); } /** * Act on return values (such as options to be set, * or instance properties to be set */ if (out) { handleOut(bs, out); } bs.debug("+ %s", chalk.green("Step Complete: " + item.step)); cb(); } }; } /** * @param bs * @param out */ function handleOut(bs, out) { /** * Set a single/many option. */ if (out.options) { setOptions(bs, out.options); } /** * Any options returned that require path access? */ if (out.optionsIn) { out.optionsIn.forEach(function(item) { bs.setOptionIn(item.path, item.value); }); } /** * Any instance properties returned? */ if (out.instance) { Object.keys(out.instance).forEach(function(key) { bs[key] = out.instance[key]; }); } } /** * Update the options Map * @param bs * @param options */ function setOptions(bs, options) { /** * If multiple options were set, act on the immutable map * in an efficient way */ if (Object.keys(options).length > 1) { bs.setMany(function(item) { Object.keys(options).forEach(function(key) { item.set(key, options[key]); return item; }); }); } else { Object.keys(options).forEach(function(key) { bs.setOption(key, options[key]); }); } } /** * At this point, ALL async tasks have completed * @param {BrowserSync} bs * @returns {Function} */ function tasksComplete(bs) { return function(err) { if (err) { bs.logger.setOnce("useLevelPrefixes", true).error(err.message); } /** * Set active flag */ bs.active = true; /** * @deprecated */ bs.events.emit("init", bs); /** * This is no-longer needed as the Callback now only resolves * when everything (including slow things, like the tunnel) is ready. * It's here purely for backwards compatibility. * @deprecated */ bs.events.emit("service:running", { options: bs.options, baseDir: bs.options.getIn(["server", "baseDir"]), type: bs.options.get("mode"), port: bs.options.get("port"), url: bs.options.getIn(["urls", "local"]), urls: bs.options.get("urls").toJS(), tunnel: bs.options.getIn(["urls", "tunnel"]) }); /** * Call any option-provided callbacks */ bs.callback("ready", null, bs); /** * Finally, call the user-provided callback given as last arg */ bs.cb(null, bs); }; } /** * @param module * @param opts * @param cb */ BrowserSync.prototype.registerPlugin = function(module, opts, cb) { var bs = this; bs.pluginManager.registerPlugin(module, opts, cb); if (module["plugin:name"]) { bs._userPlugins.push(module); } }; /** * Get a plugin by name * @param name */ BrowserSync.prototype.getUserPlugin = function(name) { var bs = this; var items = bs.getUserPlugins(function(item) { return item["plugin:name"] === name; }); if (items && items.length) { return items[0]; } return false; }; /** * @param {Function} [filter] */ BrowserSync.prototype.getUserPlugins = function(filter) { var bs = this; filter = filter || function() { return true; }; /** * Transform Plugins option */ bs.userPlugins = bs._userPlugins.filter(filter).map(function(plugin) { return { name: plugin["plugin:name"], active: plugin._enabled, opts: bs.pluginManager.pluginOptions[plugin["plugin:name"]] }; }); return bs.userPlugins; }; /** * Get middleware * @returns {*} */ BrowserSync.prototype.getMiddleware = function(type) { var types = { connector: connectUtils.socketConnector(this.options) }; if (type in types) { return function(req, res) { res.setHeader("Content-Type", "text/javascript"); res.end(types[type]); }; } }; /** * Shortcut for pushing a file-serving middleware * onto the stack * @param {String} path * @param {{type: string, content: string}} props */ var _serveFileCount = 0; BrowserSync.prototype.serveFile = function(path, props) { var bs = this; var mode = bs.options.get("mode"); var entry = { handle: function(req, res) { res.setHeader("Content-Type", props.type); res.end(props.content); }, id: "Browsersync - " + _serveFileCount++, route: path }; bs._addMiddlewareToStack(entry); }; /** * Add middlewares on the fly */ BrowserSync.prototype._addMiddlewareToStack = function(entry) { var bs = this; /** * additional middlewares are always appended -1, * this is to allow the proxy middlewares to remain, * and the directory index to remain in serveStatic/snippet modes */ bs.app.stack.splice(bs.app.stack.length - 1, 0, entry); }; var _addMiddlewareCount = 0; BrowserSync.prototype.addMiddleware = function(route, handle, opts) { var bs = this; if (!bs.app) { return; } opts = opts || {}; if (!opts.id) { opts.id = "bs-mw-" + _addMiddlewareCount++; } if (route === "*") { route = ""; } var entry = { id: opts.id, route: route, handle: handle }; if (opts.override) { entry.override = true; } bs.options = bs.options.update("middleware", function(mw) { if (bs.options.get("mode") === "proxy") { return mw.insert(mw.size - 1, entry); } return mw.concat(entry); }); bs.resetMiddlewareStack(); }; /** * Remove middlewares on the fly * @param {String} id * @returns {Server} */ BrowserSync.prototype.removeMiddleware = function(id) { var bs = this; if (!bs.app) { return; } bs.options = bs.options.update("middleware", function(mw) { return mw.filter(function(mw) { return mw.id !== id; }); }); bs.resetMiddlewareStack(); }; /** * Middleware for socket connection (external usage) * @param opts * @returns {*} */ BrowserSync.prototype.getSocketConnector = function(opts) { var bs = this; return function(req, res) { res.setHeader("Content-Type", "text/javascript"); res.end(bs.getExternalSocketConnector(opts)); }; }; /** * Socket connector as a string * @param {Object} opts * @returns {*} */ BrowserSync.prototype.getExternalSocketConnector = function(opts) { var bs = this; return connectUtils.socketConnector( bs.options.withMutations(function(item) { item.set("socket", item.get("socket").merge(opts)); if (!bs.options.getIn(["proxy", "ws"])) { item.set("mode", "snippet"); } }) ); }; /** * Callback helper * @param name */ BrowserSync.prototype.getOption = function(name) { this.debug("Getting option: {magenta:%s", name); return this.options.get(name); }; /** * Callback helper * @param path */ BrowserSync.prototype.getOptionIn = function(path) { this.debug("Getting option via path: {magenta:%s", path); return this.options.getIn(path); }; /** * @returns {BrowserSync.options} */ BrowserSync.prototype.getOptions = function() { return this.options; }; /** * @returns {BrowserSync.options} */ BrowserSync.prototype.getLogger = logger.getLogger; /** * @param {String} name * @param {*} value * @returns {BrowserSync.options|*} */ BrowserSync.prototype.setOption = function(name, value, opts) { var bs = this; opts = opts || {}; bs.debug("Setting Option: {cyan:%s} - {magenta:%s", name, value.toString()); bs.options = bs.options.set(name, value); if (!opts.silent) { bs.events.emit("options:set", { path: name, value: value, options: bs.options }); } return this.options; }; /** * @param path * @param value * @param opts * @returns {Map|*|BrowserSync.options} */ BrowserSync.prototype.setOptionIn = function(path, value, opts) { var bs = this; opts = opts || {}; bs.debug( "Setting Option: {cyan:%s} - {magenta:%s", path.join("."), value.toString() ); bs.options = bs.options.setIn(path, value); if (!opts.silent) { bs.events.emit("options:set", { path: path, value: value, options: bs.options }); } return bs.options; }; /** * Set multiple options with mutations * @param fn * @param opts * @returns {Map|*} */ BrowserSync.prototype.setMany = function(fn, opts) { var bs = this; opts = opts || {}; bs.debug("Setting multiple Options"); bs.options = bs.options.withMutations(fn); if (!opts.silent) { bs.events.emit("options:set", { options: bs.options.toJS() }); } return this.options; }; BrowserSync.prototype.addRewriteRule = function(rule) { var bs = this; bs.options = bs.options.update("rewriteRules", function(rules) { return rules.concat(rule); }); bs.resetMiddlewareStack(); }; BrowserSync.prototype.removeRewriteRule = function(id) { var bs = this; bs.options = bs.options.update("rewriteRules", function(rules) { return rules.filter(function(rule) { return rule.id !== id; }); }); bs.resetMiddlewareStack(); }; BrowserSync.prototype.setRewriteRules = function(rules) { var bs = this; bs.options = bs.options.update("rewriteRules", function(_) { return rules; }); bs.resetMiddlewareStack(); }; /** * Add a new rewrite rule to the stack * @param {Object} rule */ BrowserSync.prototype.resetMiddlewareStack = function() { var bs = this; var middlewares = require("./server/utils").getMiddlewares(bs, bs.options); bs.app.stack = middlewares; }; /** * @param fn */ BrowserSync.prototype.registerCleanupTask = function(fn) { this._cleanupTasks.push(fn); }; /** * Instance Cleanup */ BrowserSync.prototype.cleanup = function(cb) { var bs = this; if (!bs.active) { return; } // Remove all event listeners if (bs.events) { bs.debug("Removing event listeners..."); bs.events.removeAllListeners(); } // Close any core file watchers if (bs.watchers) { Object.keys(bs.watchers).forEach(function(key) { bs.watchers[key].watchers.forEach(function(watcher) { watcher.close(); }); }); } // Run any additional clean up tasks bs._cleanupTasks.forEach(function(fn) { if (_.isFunction(fn)) { fn(bs); } }); // Reset the flag bs.debug("Setting {magenta:active: false"); bs.active = false; bs.paused = false; bs.pluginManager.plugins = {}; bs.pluginManager.pluginOptions = {}; bs.pluginManager.defaultPlugins = defaultPlugins; bs._userPlugins = []; bs.userPlugins = []; bs._reloadTimer = undefined; bs._reloadQueue = []; bs._cleanupTasks = []; if (_.isFunction(cb)) { cb(null, bs); } }; module.exports = BrowserSync; ================================================ FILE: packages/browser-sync/lib/cli/cli-info.js ================================================ "use strict"; var config = require("../config"); var logger = require("../logger").logger; var fs = require("fs"); var _ = require("../lodash.custom"); var path = require("path"); var chalk = require("chalk"); var info = { /** * Version info * @param {Object} pjson * @returns {String} */ getVersion: function(pjson) { console.log(pjson.version); return pjson.version; }, /** * Retrieve the config file * @returns {*} * @private * @param filePath */ getConfigFile: function(filePath) { return require(path.resolve(filePath)); }, /** * Generate an example Config file. */ makeConfig: function(cwd, cb) { var opts = require(path.join(__dirname, "..", config.configFile)); var userOpts = {}; var ignore = ["excludedFileTypes", "injectFileTypes", "snippetOptions"]; Object.keys(opts).forEach(function(key) { if (!_.includes(ignore, key)) { userOpts[key] = opts[key]; } }); var file = fs.readFileSync(config.template, "utf8"); file = file.replace("//OPTS", JSON.stringify(userOpts, null, 4)); fs.writeFile(path.resolve(cwd, config.userFile), file, function() { logger.info("Config file created %s", chalk.magenta(config.userFile)); logger.info( "To use it, in the same directory run: " + chalk.cyan("browser-sync start --config bs-config.js") ); cb(); }); } }; module.exports = info; ================================================ FILE: packages/browser-sync/lib/cli/cli-options.ts ================================================ import { Map, List, fromJS } from "immutable"; import { addToFilesOption } from "./transforms/addToFilesOption"; import { addDefaultIgnorePatterns } from "./transforms/addDefaultIgnorePatterns"; import { copyCLIIgnoreToWatchOptions } from "./transforms/copyCLIIgnoreToWatchOptions"; import { handleExtensionsOption } from "./transforms/handleExtensionsOption"; import { handleFilesOption } from "./transforms/handleFilesOption"; import { handleGhostModeOption } from "./transforms/handleGhostModeOption"; import { handlePortsOption } from "./transforms/handlePortsOption"; import { handleProxyOption } from "./transforms/handleProxyOption"; import { handleServerOption } from "./transforms/handleServerOption"; import { appendServerIndexOption } from "./transforms/appendServerIndexOption"; import { appendServerDirectoryOption } from "./transforms/appendServerDirectoryOption"; import { addCwdToWatchOptions } from "./transforms/addCwdToWatchOptions"; import { setMode, setScheme, setStartPath, setProxyWs, setServerOpts, liftExtensionsOptionFromCli, setNamespace, fixSnippetIgnorePaths, fixSnippetIncludePaths, fixRewriteRules, setMiddleware, setOpen, setUiPort } from "../options"; import { BsErrors } from "../bin"; import { handleHostOption } from "./transforms/handleHostOption"; const _ = require("../lodash.custom"); const defaultConfig = require("../default-config"); const immDefs = fromJS(defaultConfig); /** * @param {Object} input * @returns {Map} */ export type BsTempOptions = Map; export type TransformResult = [BsTempOptions, BsErrors]; export type TransformFn = (subject: BsTempOptions) => TransformResult; export function merge(input) { const merged = immDefs.mergeDeep(input); const transforms: TransformFn[] = [ addToFilesOption, addCwdToWatchOptions, addDefaultIgnorePatterns, copyCLIIgnoreToWatchOptions, handleServerOption, appendServerIndexOption, appendServerDirectoryOption, handleProxyOption, handlePortsOption, handleHostOption, handleGhostModeOption, handleFilesOption, handleExtensionsOption, setMode, setScheme, setStartPath, setProxyWs, setServerOpts, liftExtensionsOptionFromCli, setNamespace, fixSnippetIgnorePaths, fixSnippetIncludePaths, fixRewriteRules, setMiddleware, setOpen, setUiPort ]; const output = transforms.reduce( (acc: TransformResult, item: TransformFn) => { const [current, currentErrors] = acc; const [result, errors] = item.call(null, current); return [result, [...currentErrors, ...errors]]; }, [merged, []] as TransformResult ); return output; } /** * @param string */ export function explodeFilesArg(string): string { return string.split(",").map(item => item.trim()); } /** * @param value * @returns {{globs: Array, objs: Array}} */ export function makeFilesArg(value) { let globs = []; let objs = []; if (_.isString(value)) { globs = globs.concat(explodeFilesArg(value)); } if (List.isList(value) && value.size) { value.forEach(function(value) { if (_.isString(value)) { globs.push(value); } else { if (Map.isMap(value)) { objs.push(value); } } }); } return { globs: globs, objs: objs }; } export function printErrors(errors: BsErrors) { return errors .map(error => [ `Error Type: ${error.type}`, `Error Level: ${error.level}`, error.errors.map(item => [ `Error Message: ${item.error.message}`, item.meta ? item.meta().join("\n") : "" ] .filter(Boolean) .join("\n") ) ].join("\n") ) .join("\n\n"); } ================================================ FILE: packages/browser-sync/lib/cli/command.init.js ================================================ "use strict"; var info = require("./cli-info"); /** * $ browser-sync init * * This command will generate a configuration * file in the current directory * * @param opts */ module.exports = function(opts) { info.makeConfig(process.cwd(), opts.cb); }; ================================================ FILE: packages/browser-sync/lib/cli/command.recipe.js ================================================ "use strict"; var logger = require("../logger").logger; var chalk = require("chalk"); /** * $ browser-sync recipe * * This command will copy a recipe into either the current directory * or one given with the --output flag * * @param opts * @returns {Function} */ module.exports = function(opts) { var path = require("path"); var fs = require("fs-extra"); var input = opts.cli.input.slice(1); var resolved = require.resolve("bs-recipes"); var dir = path.dirname(resolved); var logRecipes = function() { var dirs = fs.readdirSync(path.join(dir, "recipes")); logger.info( "Install one of the following with %s\n", chalk.cyan('browser-sync recipe ') ); dirs.forEach(function(name) { console.log(" " + name); }); }; if (!input.length) { logger.info("No recipe name provided!"); logRecipes(); return opts.cb(); } if (opts.cli.input[1] === "ls") { logRecipes(); return opts.cb(); } input = input[0]; var flags = opts.cli.flags; var output = flags.output ? path.resolve(flags.output) : path.join(process.cwd(), input); var targetDir = path.join(dir, "recipes", input); if (fs.existsSync(output)) { return opts.cb( new Error("Target folder exists remove it first and then try again") ); } if (fs.existsSync(targetDir)) { fs.copy(targetDir, output, function(err) { if (err) { opts.cb(err); } else { logger.info("Recipe copied into %s", chalk.cyan(output)); logger.info( "Next, inside that folder, run %s", chalk.cyan("npm i && npm start") ); opts.cb(null); } }); } else { logger.info( "Recipe %s not found. The following are available though", chalk.cyan(input) ); logRecipes(); opts.cb(); } }; ================================================ FILE: packages/browser-sync/lib/cli/command.reload.js ================================================ "use strict"; /** * $ browser-sync reload * * This commands starts the Browsersync servers * & Optionally UI. * * @param opts * @returns {Function} */ module.exports = function(opts) { var flags = opts.cli.flags; if (!flags.url) { flags.url = "http://localhost:" + (flags.port || 3000); } var proto = require("../http-protocol"); var scheme = flags.url.match(/^https/) ? "https" : "http"; var args = { method: "reload" }; if (flags.files) { args.args = flags.files; } var url = proto.getUrl(args, flags.url); if (scheme === "https") { process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; } require(scheme) .get(url, function(res) { res.on("data", function() { if (res.statusCode === 200) { opts.cb(null, res); } }); }) .on("error", function(err) { if (err.code === "ECONNREFUSED") { err.message = "Browsersync not running at " + flags.url; } return opts.cb(err); }); }; ================================================ FILE: packages/browser-sync/lib/cli/command.start.ts ================================================ import * as path from "path"; import { existsSync } from "fs"; import { fromJS } from "immutable"; import * as utils from "../utils"; import { explodeFilesArg } from "./cli-options"; const _ = require("../lodash.custom"); /** * $ browser-sync start * * This commands starts the Browsersync servers * & Optionally UI. * * @param opts * @returns {Function} */ export default function(opts) { const flags = preprocessFlags(opts.cli.flags); const cwd = flags.cwd || process.cwd(); const maybepkg = path.resolve(cwd, "package.json"); let input = flags; if (flags.config) { const maybeconf = path.resolve(cwd, flags.config); if (existsSync(maybeconf)) { const conf = require(maybeconf); input = _.merge({}, conf, flags); } else { utils.fail( true, new Error(`Configuration file '${flags.config}' not found`), opts.cb ); } } else { if (existsSync(maybepkg)) { const pkg = require(maybepkg); if (pkg["browser-sync"]) { console.log("> Configuration obtained from package.json"); input = _.merge({}, pkg["browser-sync"], flags); } } } return require("../") .create("cli") .init(input, opts.cb); } /** * @param flags * @returns {*} */ function preprocessFlags(flags) { return [ stripUndefined, legacyFilesArgs, removeWatchBooleanWhenFalse ].reduce((flags, fn) => fn.call(null, flags), flags); } /** * Incoming undefined values are problematic as * they interfere with Immutable.Map.mergeDeep * @param subject * @returns {*} */ function stripUndefined(subject) { return Object.keys(subject).reduce((acc, key) => { const value = subject[key]; if (typeof value === "undefined") { return acc; } acc[key] = value; return acc; }, {}); } /** * @param flags * @returns {*} */ function legacyFilesArgs(flags) { if (flags.files && flags.files.length) { flags.files = flags.files.reduce( (acc, item) => acc.concat(explodeFilesArg(item)), [] ); } return flags; } /** * `watch` is a CLI boolean so should be removed if false to * allow config to set watch: true * @param flags * @returns {any} */ function removeWatchBooleanWhenFalse(flags) { if (flags.watch === false) { return fromJS(flags) .delete("watch") .toJS(); } return flags; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/addCwdToWatchOptions.ts ================================================ import { BsTempOptions, TransformResult } from "../cli-options"; export function addCwdToWatchOptions(incoming: BsTempOptions): TransformResult { const output = incoming.updateIn(["watchOptions", "cwd"], watchCwd => { return watchCwd || incoming.get("cwd"); }); return [output, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/addDefaultIgnorePatterns.ts ================================================ import { List } from "immutable"; import { BsTempOptions, TransformResult } from "../cli-options"; const defaultIgnorePatterns = [ /node_modules/, /bower_components/, ".sass-cache", ".vscode", ".git", ".idea" ]; export function addDefaultIgnorePatterns( incoming: BsTempOptions ): TransformResult { if (!incoming.get("watch")) { return [incoming, []]; } const output = incoming.update("watchOptions", watchOptions => { const userIgnored = List([]) .concat(watchOptions.get("ignored")) .filter(Boolean) .toSet(); const merged = userIgnored.merge(defaultIgnorePatterns); return watchOptions.merge({ ignored: merged.toList() }); }); return [output, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/addToFilesOption.ts ================================================ import { List, Map } from "immutable"; import { BsTempOptions, TransformResult } from "../cli-options"; export function addToFilesOption(incoming: BsTempOptions): TransformResult { if (!incoming.get("watch")) { return [incoming, []]; } let serverPaths = []; const fromServeStatic = incoming.get("serveStatic", List([])).toArray(); const ssPaths = fromServeStatic.reduce((acc, ss) => { if (typeof ss === "string") { return acc.concat(ss); } if (ss.dir && typeof ss.dir === "string") { return acc.concat(ss); } return acc; }, []); ssPaths.forEach(p => serverPaths.push(p)); const server = incoming.get("server"); if (server) { if (server === true) { serverPaths.push("."); } if (typeof server === "string") { serverPaths.push(server); } if (List.isList(server) && server.every(x => typeof x === "string")) { server.forEach(s => serverPaths.push(s)); } if (Map.isMap(server)) { const baseDirProp = server.get("baseDir"); const baseDirs = List([]) .concat(baseDirProp) .filter(Boolean); baseDirs.forEach(s => serverPaths.push(s)); } } const output = incoming.update("files", files => { return List([]) .concat(files, serverPaths) .filter(Boolean); }); return [output, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/appendServerDirectoryOption.ts ================================================ import { BsTempOptions, TransformResult } from "../cli-options"; export function appendServerDirectoryOption( incoming: BsTempOptions ): TransformResult { if (!incoming.get("server")) return [incoming, []]; if (incoming.get("directory")) { return [ incoming.setIn(["server", "directory"], incoming.has("directory")), [] ]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/appendServerIndexOption.ts ================================================ import { BsTempOptions, TransformResult } from "../cli-options"; export function appendServerIndexOption( incoming: BsTempOptions ): TransformResult { if (!incoming.get("server")) return [incoming, []]; const value = incoming.get("index"); if (value) { return [incoming.setIn(["server", "index"], value), []]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/copyCLIIgnoreToWatchOptions.ts ================================================ import { List } from "immutable"; import { BsTempOptions, TransformResult } from "../cli-options"; export function copyCLIIgnoreToWatchOptions( incoming: BsTempOptions ): TransformResult { if (!incoming.get("ignore")) { return [incoming, []]; } const output = incoming.updateIn( ["watchOptions", "ignored"], List([]), ignored => { return List([]).concat(ignored, incoming.get("ignore")); } ); return [output, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleExtensionsOption.ts ================================================ import { List } from "immutable"; import { BsTempOptions, explodeFilesArg, TransformResult } from "../cli-options"; const _ = require("../../lodash.custom"); export function handleExtensionsOption( incoming: BsTempOptions ): TransformResult { const value = incoming.get("extensions"); if (_.isString(value)) { const split = explodeFilesArg(value); if (split.length) { return [incoming.set("extensions", List(split)), []]; } } if (List.isList(value)) { return [incoming.set("extensions", value), []]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleFilesOption.ts ================================================ import { fromJS } from "immutable"; import { BsTempOptions, makeFilesArg, TransformResult } from "../cli-options"; import { FilesNamespaces } from "../../types"; export function handleFilesOption(incoming: BsTempOptions): TransformResult { const value = incoming.get("files"); const namespaces: FilesNamespaces = { core: { globs: [], objs: [] } }; const processed = makeFilesArg(value); if (processed.globs.length) { namespaces.core.globs = processed.globs; } if (processed.objs.length) { namespaces.core.objs = processed.objs; } return [incoming.set("files", fromJS(namespaces)), []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleGhostModeOption.ts ================================================ import { fromJS } from "immutable"; import { BsTempOptions, TransformResult } from "../cli-options"; export function handleGhostModeOption( incoming: BsTempOptions ): TransformResult { const value = incoming.get("ghostMode"); var trueAll = { clicks: true, scroll: true, forms: { submit: true, inputs: true, toggles: true } }; var falseAll = { clicks: false, scroll: false, forms: { submit: false, inputs: false, toggles: false } }; if (value === false || value === "false") { return [incoming.set("ghostMode", fromJS(falseAll)), []]; } if (value === true || value === "true") { return [incoming.set("ghostMode", fromJS(trueAll)), []]; } if (value.get("forms") === false) { return [ incoming.set( "ghostMode", value.withMutations(function(map) { map.set( "forms", fromJS({ submit: false, inputs: false, toggles: false }) ); }) ), [] ]; } if (value.get("forms") === true) { return [ incoming.set( "ghostMode", value.withMutations(function(map) { map.set( "forms", fromJS({ submit: true, inputs: true, toggles: true }) ); }) ), [] ]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleHostOption.ts ================================================ import { BsTempOptions, TransformResult } from "../cli-options"; import { BsErrorLevels, BsErrorTypes } from "../../bin"; export function handleHostOption(incoming: BsTempOptions): TransformResult { const host: string | null = incoming.get("host"); const listen: string | null = incoming.get("listen"); if (host && listen) { if (host !== listen) { return [ incoming, [ { errors: [ { error: new Error( "Cannot specify both `host` and `listen` options" ), meta() { return [ "", "Tip: Use just the `listen` option *only* if you want to bind only to a particular host." ]; } } ], level: BsErrorLevels.Fatal, type: BsErrorTypes.HostAndListenIncompatible } ] ]; } // whenever we have have both `host` + `listen` options, // we remove the 'host' to prevent complication further down the line return [incoming.delete("host"), []]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handlePortsOption.ts ================================================ import { Map } from "immutable"; import { PortsOption } from "../../types"; import { BsTempOptions, TransformResult } from "../cli-options"; export function handlePortsOption(incoming: BsTempOptions): TransformResult { const value = incoming.get("ports"); if (!value) return [incoming, []]; const obj: PortsOption = { min: null, max: null }; if (typeof value === "string") { if (~value.indexOf(",")) { const segs = value.split(","); obj.min = parseInt(segs[0], 10); obj.max = parseInt(segs[1], 10); } else { obj.min = parseInt(value, 10); obj.max = null; } } else { obj.min = value.get("min"); obj.max = value.get("max") || null; } return [incoming.set("ports", Map(obj)), []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleProxyOption.ts ================================================ import * as url from "url"; import { Map } from "immutable"; import { BrowsersyncProxy } from "../../types"; import { BsTempOptions, TransformResult } from "../cli-options"; export function handleProxyOption(incoming: BsTempOptions): TransformResult { let value = incoming.get("proxy"); let mw; let target; if (!value || value === true) { return [incoming, []]; } if (typeof value !== "string") { target = value.get("target"); mw = value.get("middleware"); } else { target = value; value = Map({}); } if (!target.match(/^(https?):\/\//)) { target = "http://" + target; } const parsedUrl = url.parse(target); if (!parsedUrl.port) { parsedUrl.port = "80"; } const out: BrowsersyncProxy = { target: parsedUrl.protocol + "//" + parsedUrl.host, url: Map(parsedUrl) }; if (mw) { out.middleware = mw; } const proxyOutput = value.mergeDeep(out); return [incoming.set("proxy", proxyOutput), []]; } ================================================ FILE: packages/browser-sync/lib/cli/transforms/handleServerOption.ts ================================================ import { IServerOption } from "../../types"; import { fromJS, List, Map } from "immutable"; import { BsTempOptions, TransformResult } from "../cli-options"; export function handleServerOption(incoming: BsTempOptions): TransformResult { const value = incoming.get("server"); if (value === false) { return [incoming, []]; } // server: true if (value === true) { const obj: IServerOption = { baseDir: ["./"] }; return [incoming.set("server", fromJS(obj)), []]; } // server: "./app" if (typeof value === "string") { const obj: IServerOption = { baseDir: [value] }; return [incoming.set("server", fromJS(obj)), []]; } if (List.isList(value)) { const obj: IServerOption = { baseDir: value }; return [incoming.set("server", fromJS(obj)), []]; } if (Map.isMap(value)) { const dirs = List([]) .concat(value.get("baseDir", "./")) .filter(Boolean); const merged = value.merge({ baseDir: dirs }); return [incoming.set("server", merged), []]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/config.js ================================================ "use strict"; var path = require("path"); /** * @type {{controlPanel: {jsFile: string, baseDir: *}, socketIoScript: string, configFile: string, client: {shims: string}}} */ module.exports = { controlPanel: { jsFile: "/js/app.js", baseDir: path.join(__dirname, "control-panel") }, templates: { scriptTag: path.join(__dirname, "..", "templates/script-tags.html"), scriptTagSimple: path.join( __dirname, "..", "templates/script-tags-simple.html" ), connector: path.join(__dirname, "..", "templates/connector.tmpl") }, socketIoScript: "/public/socket.io.min.1.6.0.js", configFile: "default-config.js", userFile: "bs-config.js", template: path.join(__dirname, "..", "templates/cli-template.js"), httpProtocol: { path: "/__browser_sync__" }, client: { shims: "/client/client-shims.js" }, errors: { "server+proxy": "Invalid config. You cannot specify both server & proxy options.", "proxy+https": "Invalid config. You set https: true, but your proxy target doesn't reflect this." } }; ================================================ FILE: packages/browser-sync/lib/connect-utils.js ================================================ "use strict"; var _ = require("./lodash.custom"); var fs = require("fs"); var config = require("./config"); function getPath(options, relative, port) { if (options.get("mode") === "snippet") { return options.get("scheme") + "://HOST:" + port + relative; } else { return "//HOST:" + port + relative; } } var connectUtils = { /** * Allow users to disable the Browsersync snippet * @param {Immutable.Map} options * @returns {Boolean} */ enabled: function(options) { const userValue = options.get("snippet"); if (typeof userValue === "boolean") { return userValue } return true }, /** * @param {Immutable.Map} options * @returns {String} */ scriptTags: function(options) { var scriptPath = this.clientScript(options); var async = options.getIn(["snippetOptions", "async"]); var scriptDomain = options.getIn(["script", "domain"]); /** * Generate the [src] attribute based on user options */ var scriptSrc = (function() { if (options.get("localOnly")) { return [ options.get("scheme"), "://localhost:", options.get("port"), scriptPath ].join(""); } /** * First, was "scriptPath" set? if so the user wanted full control over the * script tag output * */ if (_.isFunction(options.get("scriptPath"))) { return options .get("scriptPath") .apply(null, getScriptArgs(options, scriptPath)); } /** * Next, if "script.domain" was given, allow that + the path to the JS file * eg: * script.domain=localhost:3000 * -> localhost:3000/browser-sync/browser-sync-client.js */ if (scriptDomain) { if (_.isFunction(scriptDomain)) { return scriptDomain.call(null, options) + scriptPath; } if (scriptDomain.match(/\{port\}/)) { return ( scriptDomain.replace("{port}", options.get("port")) + scriptPath ); } return scriptDomain + scriptPath; } /** * Now if server or proxy, use dynamic script * eg: * browser-sync start --server * -> * "HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname) */ if (options.get("server") || options.get("proxy")) { return scriptPath; } /** * Final use case is snippet mode * -> "http://HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname) * -> "//HOST:3000/browser-sync/browser-sync-client.js".replace("HOST", location.hostname)" */ return getPath(options, scriptPath, options.get("port")); })(); /** * Decide which template shall be used to generate the script tags */ var template = (function() { if (scriptDomain || options.get("localOnly")) { return config.templates.scriptTagSimple; } return config.templates.scriptTag; })(); /** * Finally read the template file from disk and replace * the dynamic values. */ return fs .readFileSync(template, "utf8") .replace("%script%", scriptSrc) .replace("%async%", async ? "async" : ""); }, /** * @param {Map} options * @returns {String} */ socketConnector: function(options) { var socket = options.get("socket"); var template = fs.readFileSync(config.templates.connector, "utf-8"); var url = connectUtils.getConnectionUrl(options); /** * ***Backwards compatibility***. While `socket.path` is technically a * socketIoClientConfig property, it's been documented previously * as a top-level option, so must stay. */ var clientConfig = socket.get("socketIoClientConfig").merge({ path: socket.get("path") }); template = template .replace("%config%", JSON.stringify(clientConfig.toJS())) .replace("%options%", JSON.stringify(options)) .replace("%url%", url); return template; }, /** * @param {Object} socketOpts * @param {Map} options * @returns {String|Function} */ getNamespace: function(socketOpts, options) { var namespace = socketOpts.namespace; if (typeof namespace === "function") { return namespace(options); } if (!namespace.match(/^\//)) { namespace = "/" + namespace; } return namespace; }, /** * @param {Map} options * @returns {string} */ getConnectionUrl: function(options) { var socketOpts = options.get("socket").toJS(); var namespace = connectUtils.getNamespace(socketOpts, options); var protocol = ""; var withHostnamePort = "'{protocol}' + location.hostname + ':{port}{ns}'"; var withHost = "'{protocol}' + location.host + '{ns}'"; var withDomain = "'{domain}{ns}'"; var port = options.get("port"); // default use-case is server/proxy var string = withHost; if (options.get("mode") !== "server") { protocol = options.get("scheme") + "://"; string = withHostnamePort; } if (options.get("mode") === "proxy" && options.getIn(["proxy", "ws"])) { port = options.getIn(["socket", "port"]); } /** * Ensure socket.domain is always a string (for noop replacements later) */ socketOpts.domain = (function() { if (options.get("localOnly")) { string = withDomain; return [ options.get("scheme"), "://localhost:", options.get("port") ].join(""); } if (socketOpts.domain) { string = withDomain; /** * User provided a function */ if (_.isFunction(socketOpts.domain)) { return socketOpts.domain.call(null, options); } /** * User provided a string */ if (_.isString(socketOpts.domain)) { return socketOpts.domain; } } return ""; })(); return string .replace("{protocol}", protocol) .replace("{port}", port) .replace("{domain}", socketOpts.domain.replace("{port}", port)) .replace("{ns}", namespace); }, /** * @param {Object} [options] * @param {Boolean} [both] */ clientScript: function(options, both) { var prefix = options.getIn(["socket", "clientPath"]); var script = prefix + "/browser-sync-client.js"; var versioned = prefix + "/browser-sync-client.js?v=" + options.get("version"); if (both) { return { path: script, versioned: versioned }; } return versioned; } }; /** * @param options * @returns {*[]} */ function getScriptArgs(options, scriptPath) { var abspath = options.get("scheme") + "://HOST:" + options.get("port") + scriptPath; return [scriptPath, options.get("port"), options.set("absolute", abspath)]; } module.exports = connectUtils; ================================================ FILE: packages/browser-sync/lib/default-config.js ================================================ /** * @module BrowserSync.options */ module.exports = { /** * Browsersync includes a user-interface that is accessed via a separate port. * The UI allows to controls all devices, push sync updates and much more. * @property ui * @type Object * @param {Number} [port=3001] * @since 2.0.0 * @default false */ ui: { port: 3001 }, /** * Browsersync can watch your files as you work. Changes you make will either * be injected into the page (CSS & images) or will cause all browsers to do * a full-page refresh. * @property files * @type Array|String * @default false */ files: false, /** * Specify which file events to respond to. * Available events: `add`, `change`, `unlink`, `addDir`, `unlinkDir` * @property watchEvents * @type Array * @default ["change"] * @since 2.18.8 */ watchEvents: ["change"], /** * Watch files automatically - this should be used as an * alternative to the `files` option. When this option is used, some directories * will be ignored automatically such as `node_modules` `bower_components` `.sass-cache` * `.vscode` `.git` `.idea` * * @property watch * @type Boolean * @default false * @since 2.23.0 */ watch: false, /** * Patterns for any watchers to ignore. Anything provided here * will end up inside `watchOptions.ignored` * @property ignore * @type Array * @default [] * @since 2.23.0 */ ignore: [], /** * Serve an index.html file for all non-asset routes. Useful * when using client-routers * @property single * @type Boolean * @default false * @since 2.23.0 */ single: false, /** * File watching options that get passed along to [Chokidar](https://github.com/paulmillr/chokidar). * Check their docs for available options * @property watchOptions * @type Object * @default undefined * @since 2.6.0 */ watchOptions: { ignoreInitial: true /* persistent: true, ignored: '*.txt', followSymlinks: true, cwd: '.', usePolling: true, alwaysStat: false, depth: undefined, interval: 100, ignorePermissionErrors: false, atomic: true */ }, /** * Use the built-in static server for basic HTML/JS/CSS websites. * @property server * @type Object|Boolean * @default false */ server: false, /** * Proxy an EXISTING vhost. Browsersync will wrap your vhost with a proxy URL to view your site. * @property proxy * @type String|Object|Boolean * @param {String} [target] * @param {Boolean} [ws] - Enable websocket proxying * @param {Function|Array} [middleware] * @param {Function} [reqHeaders] * @param {Array} [proxyReq] * @param {Array} [proxyRes] * @default false */ proxy: false, /** * @property port * @type Number * @default 3000 */ port: 3000, /** * @property middleware * @type Function|Array * @default false */ middleware: false, /** * Add additional directories from which static * files should be served. Should only be used in `proxy` or `snippet` * mode. * @property serveStatic * @type Array * @default [] * @since 2.8.0 */ serveStatic: [], /** * Options that are passed to the serve-static middleware * when you use the string[] syntax: eg: `serveStatic: ['./app']`. Please see * [serve-static](https://github.com/expressjs/serve-static) for details * * @property serveStaticOptions * @type Object * @since 2.17.0 */ /** * Enable https for localhost development. **Note** - this is not needed for proxy * option as it will be inferred from your target url. * @property https * @type Boolean * @default undefined * @since 1.3.0 */ /** * Override http module to allow using 3rd party server modules (such as http2) * *Note*: these modules are not included in the Browsersync package - you need * to 'npm install' any that you'd like to use. * @property httpModule * @type string * @default undefined * @since 2.18.0 */ /** * Current working directory * @property cwd * @type String * @since 2.23.0 */ /** * Register callbacks via a regular option - this can be used * to get access the Browsersync instance in situations where you * cannot provide a callback via the normal API (for example, in a Gruntfile) * * **Note**: Only the `ready` callback is currently supported here. * * @property callbacks * @type Object * @param {Function} ready */ /** * Clicks, Scrolls & Form inputs on any device will be mirrored to all others. * @property ghostMode * @param {Boolean} [clicks=true] * @param {Boolean} [scroll=true] * @param {Boolean} [location=true] * @param {Boolean} [forms=true] * @param {Boolean} [forms.submit=true] * @param {Boolean} [forms.inputs=true] * @param {Boolean} [forms.toggles=true] * @type Object */ ghostMode: { clicks: true, scroll: true, location: true, forms: { submit: true, inputs: true, toggles: true } }, /** * Can be either "info", "debug", "warn", or "silent" * @property logLevel * @type String * @default info */ logLevel: "info", /** * Change the console logging prefix. Useful if you're creating your * own project based on Browsersync * @property logPrefix * @type String * @default Browsersync * @since 1.5.1 */ logPrefix: "Browsersync", /** * @property logConnections * @type Boolean * @default false */ logConnections: false, /** * @property logFileChanges * @type Boolean * @default true */ logFileChanges: true, /** * Log the snippet to the console when you're in snippet mode (no proxy/server) * @property logSnippet * @type: Boolean * @default true * @since 1.5.2 */ logSnippet: true, /** * You can prevent Browsersync from injecting the connection snippet * by passing `snippet: false`. * @property snippet * @type Boolean * @default undefined */ /** * You can control how the snippet is injected * onto each page via a custom regex + function. * You can also provide patterns for certain urls * that should be ignored from the snippet injection. * @property snippetOptions * @since 2.0.0 * @param {Boolean} [async] - should the script tags have the async attribute? * @param {Array} [blacklist] * @param {Array} [whitelist] * @param {RegExp} [rule.match=/$/] * @param {Function} [rule.fn=Function] * @type Object */ snippetOptions: { async: true, whitelist: [], blacklist: [], rule: { match: /]*>/i, fn: function(snippet, match) { return match + snippet; } } }, /** * Add additional HTML rewriting rules. * @property rewriteRules * @since 2.4.0 * @type Array * @default false */ rewriteRules: [], /** * @property tunnel * @type String|Boolean * @default null */ /** * Decide which URL to open automatically when Browsersync starts. Defaults to "local" if none set. * Can be `true`, `local`, `external`, `ui`, `ui-external`, `tunnel` or `false` * @property open * @type Boolean|String * @default true */ open: "local", /** * @property browser * @type String|Array * @default default */ browser: "default", /** * Add HTTP access control (CORS) headers to assets served by Browsersync. * @property cors * @type boolean * @default false * @since 2.16.0 */ cors: false, hostnameSuffix: false, /** * Reload each browser when Browsersync is restarted. * @property reloadOnRestart * @type Boolean * @default false */ reloadOnRestart: false, /** * The small pop-over notifications in the browser are not always needed/wanted. * @property notify * @type Boolean * @default true */ notify: true, /** * @property scrollProportionally * @type Boolean * @default true */ scrollProportionally: true, /** * @property scrollThrottle * @type Number * @default 0 */ scrollThrottle: 0, /** * Decide which technique should be used to restore * scroll position following a reload. * Can be `window.name` or `cookie` * @property scrollRestoreTechnique * @type String * @default 'window.name' */ scrollRestoreTechnique: "window.name", /** * Sync the scroll position of any element * on the page. Add any amount of CSS selectors * @property scrollElements * @type Array * @default [] * @since 2.9.0 */ scrollElements: [], /** * Sync the scroll position of any element * on the page - where any scrolled element * will cause all others to match scroll position. * This is helpful when a breakpoint alters which element * is actually scrolling * @property scrollElementMapping * @type Array * @default [] * @since 2.9.0 */ scrollElementMapping: [], /** * Time, in milliseconds, to wait before * instructing the browser to reload/inject following a * file change event * @property reloadDelay * @type Number * @default 0 */ reloadDelay: 0, /** * Wait for a specified window of event-silence before * sending any reload events. * @property reloadDebounce * @type Number * @default 0 * @since 2.6.0 */ reloadDebounce: 500, /** * Emit only the first event during sequential time windows * of a specified duration. * @property reloadThrottle * @type Number * @default 0 * @since 2.13.0 */ reloadThrottle: 0, /** * User provided plugins * @property plugins * @type Array * @default [] * @since 2.6.0 */ plugins: [], /** * @property injectChanges * @type Boolean * @default true */ injectChanges: true, /** * @property startPath * @type String|Null * @default null */ startPath: null, /** * Whether to minify client script, or not. * @property minify * @type Boolean * @default true */ minify: true, /** * @property host * @type String * @default null */ host: null, /** * Specify a host to listen on. Use this if you want to * prevent binding to all interfaces. * * Note: When you specify this option, it overrides the 'host' option * @property listen * @type String * @default undefined */ /** * Support environments where dynamic hostnames are not required * (ie: electron) * @property localOnly * @type Boolean * @default false * @since 2.14.0 */ localOnly: false, /** * @property codeSync * @type Boolean * @default true */ codeSync: true, /** * @property timestamps * @type Boolean * @default true */ timestamps: true, clientEvents: [ "scroll", "scroll:element", "input:text", "input:toggles", "form:submit", "form:reset", "click" ], /** * Alter the script path for complete control over where the Browsersync * Javascript is served from. Whatever you return from this function * will be used as the script path. * @property scriptPath * @default undefined * @since 1.5.0 * @type Function */ /** * Configure the Socket.IO path and namespace & domain to avoid collisions. * @property socket * @param {String} [path="/browser-sync/socket.io"] * @param {String} [clientPath="/browser-sync"] * @param {String|Function} [namespace="/browser-sync"] * @param {String|Function} [domain=undefined] * @param {String|Function} [port=undefined] * @param {Object} [clients.heartbeatTimeout=5000] * @since 1.6.2 * @type Object */ socket: { socketIoOptions: { log: false }, socketIoClientConfig: { reconnectionAttempts: 50 }, path: "/browser-sync/socket.io", clientPath: "/browser-sync", namespace: "/browser-sync", clients: { heartbeatTimeout: 5000 } }, /** * Configure the script domain * @property script * @param {String|Function} [domain=undefined] * @since 2.14.0 * @type Object */ tagNames: { less: "link", scss: "link", css: "link", jpg: "img", jpeg: "img", png: "img", svg: "img", gif: "img", js: "script" }, injectFileTypes: ["css", "png", "jpg", "jpeg", "svg", "gif", "webp", "map"], injectNotification: false, // console | overlay excludedFileTypes: [ "js", "css", "pdf", "map", "svg", "ico", "woff", "json", "eot", "ttf", "png", "jpg", "jpeg", "webp", "gif", "mp4", "mp3", "3gp", "ogg", "ogv", "webm", "m4a", "flv", "wmv", "avi", "swf", "scss" ] }; ================================================ FILE: packages/browser-sync/lib/file-event-handler.js ================================================ var utils = require("./utils"); /** * Apply the operators that apply to the 'file:changed' event * @param {Rx.Observable} subject * @param options * @return {Rx.Observable<{type: string, files: Array}>} */ function fileChanges(subject, options) { const operators = [ { option: "reloadThrottle", fnName: "throttle" }, { option: "reloadDelay", fnName: "delay" } ]; const scheduler = options.getIn(["debug", "scheduler"]); /** * Create a stream buffered/debounced stream of events */ const initial = getAggregatedDebouncedStream(subject, options, scheduler); return applyOperators(operators, initial, options, scheduler).map(function( items ) { const paths = items.map(x => x.path); if ( utils.willCauseReload(paths, options.get("injectFileTypes").toJS()) ) { return { type: "reload", files: items }; } return { type: "inject", files: items }; }); } module.exports.fileChanges = fileChanges; /** * Apply the operators that apply to the 'browser:reload' event * @param {Rx.Observable} subject * @param options * @returns {Rx.Observable} */ function applyReloadOperators(subject, options) { var operators = [ { option: "reloadDebounce", fnName: "debounce" }, { option: "reloadThrottle", fnName: "throttle" }, { option: "reloadDelay", fnName: "delay" } ]; return applyOperators( operators, subject, options, options.getIn(["debug", "scheduler"]) ); } module.exports.applyReloadOperators = applyReloadOperators; /** * @param items * @param subject * @param options * @param scheduler */ function applyOperators(items, subject, options, scheduler) { return items.reduce(function(subject, item) { var value = options.get(item.option); if (value > 0) { return subject[item.fnName].call(subject, value, scheduler); } return subject; }, subject); } /** * @param subject * @param options * @param scheduler */ function getAggregatedDebouncedStream(subject, options, scheduler) { return subject .filter(function(x) { return options.get("watchEvents").indexOf(x.event) > -1; }) .buffer(subject.debounce(options.get("reloadDebounce"), scheduler)); } ================================================ FILE: packages/browser-sync/lib/file-utils.js ================================================ "use strict"; var _ = require("./lodash.custom"); var fileUtils = { /** * React to file-change events that occur on "core" namespace only * @param bs * @param data */ changedFile: function(bs, data) { /** * If the event property is undefined, infer that it's a 'change' * event due the fact this handler is for emitter.emit("file:changed") */ if (_.isUndefined(data.event)) { data.event = "change"; } /** * Chokidar always sends an 'event' property - which could be * `add` `unlink` etc etc so we need to check for that and only * respond to 'change', for now. */ if (bs.options.get("watchEvents").indexOf(data.event) > -1) { if (!bs.paused && data.namespace === "core") { bs.events.emit( "file:reload", fileUtils.getFileInfo(data, bs.options) ); } } }, /** * @param data * @param options * @returns {{assetFileName: *, fileExtension: String}} */ getFileInfo: function(data, options) { data.ext = require("path") .extname(data.path) .slice(1); data.basename = require("path").basename(data.path); var obj = { ext: data.ext, path: data.path, basename: data.basename, event: data.event, type: "inject" }; // RELOAD page if (!_.includes(options.get("injectFileTypes").toJS(), obj.ext)) { obj.url = obj.path; obj.type = "reload"; } obj.path = data.path; obj.log = data.log; return obj; } }; module.exports = fileUtils; ================================================ FILE: packages/browser-sync/lib/file-watcher.js ================================================ "use strict"; var _ = require("./lodash.custom"); var utils = require("./utils"); var Rx = require("rx"); /** * Plugin interface * @returns {*|function(this:exports)} */ module.exports.plugin = function(bs) { var options = bs.options; var emitter = bs.emitter; var defaultWatchOptions = options.get("watchOptions").toJS(); return options.get("files").reduce(function(map, glob, namespace) { /** * Default CB when not given * @param event * @param path */ var fn = function(event, path) { emitter.emit("file:changed", { event: event, path: path, namespace: namespace }); }; var jsItem = glob.toJS(); if (jsItem.globs.length) { var watcher = watch(jsItem.globs, defaultWatchOptions, fn); map[namespace] = { watchers: [watcher] }; } if (jsItem.objs.length) { jsItem.objs.forEach(function(item) { if (!_.isFunction(item.fn)) { item.fn = fn; } var watcher = watch( item.match, item.options || defaultWatchOptions, item.fn.bind(bs.publicInstance) ); if (!map[namespace]) { map[namespace] = { watchers: [watcher] }; } else { map[namespace].watchers.push(watcher); } }); } return map; }, {}); }; /** * @param patterns * @param opts * @param cb * @returns {*} */ function watch(patterns, opts, cb) { if (typeof opts === "function") { cb = opts; opts = {}; } var watcher = require("chokidar").watch(patterns, opts); if (_.isFunction(cb)) { watcher.on("all", cb); } // watcher.on('ready', () => { // console.log(watcher.getWatched()); // }); return watcher; } module.exports.watch = watch; ================================================ FILE: packages/browser-sync/lib/hooks.js ================================================ "use strict"; var _ = require("./lodash.custom"); var Immutable = require("immutable"); var snippetUtils = require("./snippet").utils; module.exports = { /** * * @this {BrowserSync} * @returns {String} */ "client:js": function(hooks, data) { var js = snippetUtils.getClientJs(data.port, data.options); return hooks.reduce( function(acc, hook) { if (typeof hook === "function") { return acc.concat(hook); } return acc.concat(String(hook)); }, [js] ); }, /** * @this {BrowserSync} * @returns {Array} */ "client:events": function(hooks, clientEvents) { hooks.forEach(function(hook) { var result = hook(this); if (Array.isArray(result)) { clientEvents = _.union(clientEvents, result); } else { clientEvents.push(result); } }, this); return clientEvents; }, /** * @returns {Array} */ "server:middleware": function(hooks, initial) { initial = initial || []; _.each( hooks, function(hook) { var result = hook(this); if (Array.isArray(result)) { result.forEach(function(res) { if (_.isFunction(res)) { initial = initial.push(res); } }); } else { if (_.isFunction(result)) { initial = initial.push(result); } } }, this ); return initial; }, /** * @param {Array} hooks * @param {Map|List} initial * @param pluginOptions * @returns {any} */ "files:watch": function(hooks, initial, pluginOptions) { var opts; if (pluginOptions) { opts = Immutable.fromJS(pluginOptions); opts.forEach(function(value, key) { if (!value) { return; } var files = value.get("files"); if (files) { var fileArg = require("./cli/cli-options").makeFilesArg( files ); if (fileArg) { initial = initial.set(key, Immutable.fromJS(fileArg)); } } }); } return initial; } }; ================================================ FILE: packages/browser-sync/lib/http-protocol.js ================================================ "use strict"; var proto = exports; var instanceMethods = ["exit", "notify", "pause", "resume"]; var getBody = require("raw-body"); const { parseParams, serializeParams } = require("./utils"); const permittedSocketEvents = [ "file:reload", "browser:reload", "browser:notify", "browser:location", "options:set" ]; /** * Does the requested method expect an instance of BrowserSync * or raw access to the emitter? * @param method * @returns {boolean} */ function methodRequiresInstance(method) { return instanceMethods.indexOf(method) > -1; } /** * Use BrowserSync options + querystring to create a * full HTTP/HTTTPS url. * * Eg. http://localhost:3000/__browser_sync__?method=reload * Eg. http://localhost:3000/__browser_sync__?method=reload&args=core.css * Eg. http://localhost:3000/__browser_sync__?method=reload&args=core.css&args=core.min * * @param args * @param url * @returns {string} */ proto.getUrl = function(args, url) { return [ url, require("./config").httpProtocol.path, "?", serializeParams(args).toString() ].join(""); }; /** * Return a middleware for handling the requests * @param {BrowserSync} bs * @returns {Function} */ proto.middleware = function(bs) { return function(req, res) { if (req.method === "POST") { return getBody(req, function(err, body) { if (err) { const output = ["Error: could not parse JSON."]; res.writeHead(500, { "Content-Type": "text/plain" }); return res.end(output.join("\n")); } try { const [name, payload] = JSON.parse(body.toString()); bs.io.sockets.emit(name, payload); return res.end( `Browsersync HTTP Protocol received: ${name} ${JSON.stringify( payload )}` ); } catch (e) { const output = [`Error: ${e.message}`]; res.writeHead(500, { "Content-Type": "text/plain" }); return res.end(output.join("\n")); } }); } var split = req.url.split("?"); var params = parseParams(split[1]); var output; if (!Object.keys(params).length) { output = [ "Error: No Parameters were provided.", "Example: http://localhost:3000/__browser_sync__?method=reload&args=core.css" ]; res.writeHead(500, { "Content-Type": "text/plain" }); res.end(output.join("\n")); return; } try { var bsOrEmitter = methodRequiresInstance(params.method) ? bs : bs.events; require("./public/" + params.method)(bsOrEmitter).apply(null, [ params.args ]); output = [ "Called public API method `.%s()`".replace("%s", params.method), "With args: " + JSON.stringify(params.args) ]; res.end(output.join("\n")); } catch (e) { res.writeHead(404, { "Content-Type": "text/plain" }); res.write("Public API method `" + params.method + "` not found."); res.end(); return; } }; }; ================================================ FILE: packages/browser-sync/lib/index.js ================================================ #! /usr/bin/env node "use strict"; /** * @module BrowserSync */ var pjson = require("../package.json"); var BrowserSync = require("./browser-sync"); var publicUtils = require("./public/public-utils"); var events = require("events"); var chalk = require("chalk"); var PassThrough = require("stream").PassThrough; var logger = require("eazy-logger").Logger({ useLevelPrefixes: true }); var singleton = false; var singletonPlugins = []; var instances = []; /** * @type {boolean|EventEmitter} */ var singletonEmitter = false; module.exports = initSingleton; /** * Create a Browsersync instance * @method create * @param {String} name an identifier that can used for retrieval later */ /** * Get a single instance by name. This is useful if you have your * build scripts in separate files * @method get * @param {String} name * @returns {Object|Boolean} */ module.exports.get = function(name) { var instance = getSingle(name); if (instance) { return instance; } throw new Error( "An instance with the name `%s` was not found.".replace("%s", name) ); }; /** * Check if an instance has been created. * @method has * @param {String} name * @returns {Boolean} */ module.exports.has = function(name) { var instance = getSingle(name); if (instance) { return true; } return false; }; /** * Start the Browsersync service. This will launch a server, proxy or start the snippet * mode depending on your use-case. * @method init * @param {Object} [config] This is the main configuration for your Browsersync instance and can contain any of the [available options]({{site.links.options}}) * If you do not pass a config an argument for configuration, Browsersync will still run; but it will be in the `snippet` mode * @param {Function} [cb] If you pass a callback function, it will be called when Browsersync has completed all setup tasks and is ready to use. This * is useful when you need to wait for information (for example: urls, port etc) or perform other tasks synchronously. * @returns {BrowserSync} */ module.exports.init = initSingleton; /** * Register a plugin. Must implement at least a 'plugin' method that returns a * callable function. * * @method use * @param {String} name The name of the plugin * @param {Object} module The object to be `required`. * @param {Function} [cb] A callback function that will return any errors. */ module.exports.use = function() { var args = Array.prototype.slice.call(arguments); singletonPlugins.push({ args: args }); }; /** * The `reload` method will inform all browsers about changed files and will either cause the browser to refresh, or inject the files where possible. * * @method reload * @param {String|Array|Object} [arg] The file or files to be reloaded. * @returns {*} */ module.exports.reload = noop("reload"); /** * The `stream` method returns a transform stream and can act once or on many files. * * @method stream * @param {Object} [opts] Configuration for the stream method * @param {Object} [opts.match] Resulting files to reload. The path is from the * root of the site (not the root of your project). You can use '**' to recurse * directories. * @param {Object} [opts.once] Only reload on the first changed file in the stream. * @since 2.6.0 * @returns {*} */ module.exports.stream = noop("stream"); /** * Helper method for browser notifications * * @method notify * @param {String|HTML} msg Can be a simple message such as 'Connected' or HTML * @param {Number} [timeout] How long the message will remain in the browser. @since 1.3.0 */ module.exports.notify = noop("notify"); /** * This method will close any running server, stop file watching & exit the current process. * * @method exit */ module.exports.exit = noop("exit"); /** * Stand alone file-watcher. Use this along with Browsersync to create your own, minimal build system * @method watch * @param {string} patterns Glob patterns for files to watch * @param {object} [opts] Options to be passed to Chokidar - check what's available in [their docs](https://github.com/paulmillr/chokidar#getting-started) * @param {function} [fn] Callback function for each event. * @since 2.6.0 */ module.exports.watch = noop("watch"); /** * Method to pause file change events * * @method pause */ module.exports.pause = noop("pause"); /** * Method to resume paused watchers * * @method resume */ module.exports.resume = noop("resume"); /** * Add properties fo */ Object.defineProperties(module.exports, { /** * The internal Event Emitter used by the running Browsersync instance (if there is one). * You can use this to emit your own events, such as changed files, logging etc. * * @property emitter */ emitter: { get: function() { if (!singletonEmitter) { singletonEmitter = newEmitter(); return singletonEmitter; } return singletonEmitter; } }, /** * A simple true/false flag that you can use to determine if there's a currently-running Browsersync instance. * * @property active */ active: { get: getSingletonValue.bind(null, "active") }, /** * A simple true/false flag to determine if the current instance is paused * * @property paused */ paused: { get: getSingletonValue.bind(null, "paused") } }); /** * Event emitter factory * @returns {EventEmitter} */ function newEmitter() { var emitter = new events.EventEmitter(); emitter.setMaxListeners(20); return emitter; } /** * Get the singleton's emitter, or a new one. * @returns {EventEmitter} */ function getSingletonEmitter() { if (singletonEmitter) { return singletonEmitter; } singletonEmitter = newEmitter(); return singletonEmitter; } /** * Helper to allow methods to be called on the module export * before there's a running instance * @param {String} name * @returns {Function} */ function noop(name) { return function() { var args = Array.prototype.slice.call(arguments); if (singleton) { return singleton[name].apply(singleton, args); } else { if (publicUtils.isStreamArg(name, args)) { return new PassThrough({ objectMode: true }); } } }; } /** * Create a single instance when module export is used directly via browserSync({}); * This is mostly for back-compatibility, for also for the nicer api. * This will never be removed to ensure we never break user-land, but * we should discourage it's use. * @returns {*} */ function initSingleton() { var instance; if (instances.length) { instance = instances.filter(function(item) { return item.name === "singleton"; }); if (instance.length) { logger.error( chalk.yellow("You tried to start Browsersync twice!"), "To create multiple instances, use", chalk.cyan("browserSync.create().init()") ); return instance; } } var args = Array.prototype.slice.call(arguments); singleton = create("singleton", getSingletonEmitter()); if (singletonPlugins.length) { singletonPlugins.forEach(function(obj) { singleton.instance.registerPlugin.apply( singleton.instance, obj.args ); }); } singleton.init.apply(null, args); return singleton; } /** * @param {String} prop * @returns {Object|Boolean} */ function getSingletonValue(prop) { var single = getSingle("singleton"); if (single) { return single[prop]; } return false; } /** * Get a single instance by name * @param {String} name * @returns {Object|Boolean} */ function getSingle(name) { if (instances.length) { var match = instances.filter(function(item) { return item.name === name; }); if (match.length) { return match[0]; } } return false; } /** * Create an instance of Browsersync * @param {String} [name] * @param {EventEmitter} [emitter] * @returns {{init: *, exit: (exit|exports), notify: *, reload: *, cleanup: *, emitter: (Browsersync.events|*), use: *}} */ /** * Reset the state of the module. * (should only be needed for test environments) */ module.exports.reset = function() { instances.forEach(function(item) { item.cleanup(); }); instances = []; singletonPlugins = []; singletonEmitter = false; singleton = false; }; /** * @type {Array} */ module.exports.instances = instances; /** * Create an instance of Browsersync * @param {String} [name] * @param {EventEmitter} [emitter] * @returns {{init: *, exit: (exit|exports), notify: *, reload: *, cleanup: *, emitter: (Browsersync.events|*), use: *}} */ module.exports.create = create; function create(name, emitter) { name = name || new Date().getTime(); emitter = emitter || newEmitter(); var browserSync = new BrowserSync(emitter); var instance = { name: name, instance: browserSync, exit: require("./public/exit")(browserSync), notify: require("./public/notify")(browserSync), pause: require("./public/pause")(browserSync), resume: require("./public/resume")(browserSync), reload: require("./public/reload")(emitter), stream: require("./public/stream")(emitter), cleanup: browserSync.cleanup.bind(browserSync), use: browserSync.registerPlugin.bind(browserSync), getOption: browserSync.getOption.bind(browserSync), emitter: browserSync.events, watch: require("./file-watcher").watch }; browserSync.publicInstance = instance; instance.init = require("./public/init")(browserSync, name, pjson); Object.defineProperty(instance, "active", { get: function() { return browserSync.active; } }); Object.defineProperty(instance, "paused", { get: function() { return browserSync.paused; } }); /** * Access to client-side socket for emitting events * * @property sockets */ Object.defineProperty(instance, "sockets", { get: function() { if (!browserSync.active) { return { emit: function() {}, on: function() {} }; } else { return browserSync.io.sockets; } } }); instances.push(instance); return instance; } ================================================ FILE: packages/browser-sync/lib/internal-events.js ================================================ "use strict"; var utils = require("./utils"); var fileUtils = require("./file-utils"); var Rx = require("rx"); var fromEvent = Rx.Observable.fromEvent; var fileHandler = require("./file-event-handler"); module.exports = function(bs) { var events = { /** * File reloads * @param data */ "file:reload": function(data) { bs.io.sockets.emit("file:reload", data); }, /** * Browser Reloads */ "browser:reload": function() { bs.io.sockets.emit("browser:reload"); }, /** * Browser Notify * @param data */ "browser:notify": function(data) { bs.io.sockets.emit("browser:notify", data); }, /** * Things that happened after the service is running * @param data */ "service:running": function(data) { var mode = bs.options.get("mode"); var open = bs.options.get("open"); if ( mode === "proxy" || mode === "server" || open === "ui" || open === "ui-external" ) { utils.openBrowser(data.url, bs.options, bs); } // log about any file watching if (bs.watchers) { bs.events.emit("file:watching", bs.watchers); } }, /** * Option setting * @param data */ "options:set": function(data) { if (bs.io) { bs.io.sockets.emit("options:set", data); } }, /** * Plugin configuration setting * @param data */ "plugins:configure": function(data) { if (data.active) { bs.pluginManager.enablePlugin(data.name); } else { bs.pluginManager.disablePlugin(data.name); } bs.setOption("userPlugins", bs.getUserPlugins()); }, "plugins:opts": function(data) { if (bs.pluginManager.pluginOptions[data.name]) { bs.pluginManager.pluginOptions[data.name] = data.opts; bs.setOption("userPlugins", bs.getUserPlugins()); } } }; Object.keys(events).forEach(function(event) { bs.events.on(event, events[event]); }); var reloader = fileHandler .applyReloadOperators( fromEvent(bs.events, "_browser:reload"), bs.options ) .subscribe(function() { bs.events.emit("browser:reload"); }); var coreNamespacedWatchers = fromEvent(bs.events, "file:changed") .filter(function() { return bs.options.get("codeSync"); }) .filter(function(x) { return x.namespace === "core"; }); var handler = fileHandler .fileChanges(coreNamespacedWatchers, bs.options) .subscribe(function(x) { if (x.type === "reload") { bs.events.emit("browser:reload", x); } if (x.type === "inject") { x.files.forEach(function(data) { if (!bs.paused && data.namespace === "core") { bs.events.emit( "file:reload", fileUtils.getFileInfo(data, bs.options) ); } }); } }); bs.registerCleanupTask(function() { handler.dispose(); reloader.dispose(); }); }; ================================================ FILE: packages/browser-sync/lib/lodash.custom.js ================================================ /** * @license * Lodash (Custom Build) * Build: `lodash include="isUndefined,isFunction,toArray,includes,union,each,isString,merge,isObject,set" exports="node"` * Copyright JS Foundation and other contributors * Released under MIT license * Based on Underscore.js 1.8.3 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ (function() { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; /** Used as the semantic version number. */ var VERSION = "4.17.4"; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Error message constants. */ var FUNC_ERROR_TEXT = "Expected a function"; /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = "__lodash_hash_undefined__"; /** Used as the maximum memoize cache size. */ var MAX_MEMOIZE_SIZE = 500; /** Used to compose bitmasks for cloning. */ var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4; /** Used to compose bitmasks for value comparisons. */ var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2; /** Used to detect hot functions by number of calls within a span of milliseconds. */ var HOT_COUNT = 800, HOT_SPAN = 16; /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 1.7976931348623157e308, NAN = 0 / 0; /** `Object#toString` result references. */ var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]"; var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, reLeadingDot = /^\./, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; /** * Used to match `RegExp` * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; /** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; /** Used to detect binary string values. */ var reIsBinary = /^0b[01]+$/i; /** Used to detect host constructors (Safari). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect octal string values. */ var reIsOctal = /^0o[0-7]+$/i; /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; /** Used to compose unicode character classes. */ var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsVarRange = "\\ufe0e\\ufe0f"; /** Used to compose unicode capture groups. */ var rsAstral = "[" + rsAstralRange + "]", rsCombo = "[" + rsComboRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsZWJ = "\\u200d"; /** Used to compose unicode regexes. */ var reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsSymbol = "(?:" + [ rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral ].join("|") + ")"; /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ var reUnicode = RegExp( rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g" ); /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ var reHasUnicode = RegExp( "[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]" ); /** Used to identify `toStringTag` values of typed arrays. */ var typedArrayTags = {}; typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[ int8Tag ] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[ uint8Tag ] = typedArrayTags[uint8ClampedTag] = typedArrayTags[ uint16Tag ] = typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[ arrayBufferTag ] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[ dateTag ] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[ mapTag ] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[ regexpTag ] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[ weakMapTag ] = false; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[ arrayBufferTag ] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[ dateTag ] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[ int8Tag ] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[ mapTag ] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[ regexpTag ] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[ symbolTag ] = cloneableTags[uint8Tag] = cloneableTags[ uint8ClampedTag ] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[ weakMapTag ] = false; /** Built-in method references without a dependency on `root`. */ var freeParseInt = parseInt; /** Detect free variable `global` from Node.js. */ var freeGlobal = typeof global == "object" && global && global.Object === Object && global; /** Detect free variable `self`. */ var freeSelf = typeof self == "object" && self && self.Object === Object && self; /** Used as a reference to the global object. */ var root = freeGlobal || freeSelf || Function("return this")(); /** Detect free variable `exports`. */ var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; /** Detect free variable `module`. */ var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = freeModule && freeModule.exports === freeExports; /** Detect free variable `process` from Node.js. */ var freeProcess = moduleExports && freeGlobal.process; /** Used to access faster Node.js helpers. */ var nodeUtil = (function() { try { return ( freeProcess && freeProcess.binding && freeProcess.binding("util") ); } catch (e) {} })(); /* Node.js helper references. */ var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; /*--------------------------------------------------------------------------*/ /** * Adds the key-value `pair` to `map`. * * @private * @param {Object} map The map to modify. * @param {Array} pair The key-value pair to add. * @returns {Object} Returns `map`. */ function addMapEntry(map, pair) { // Don't return `map.set` because it's not chainable in IE 11. map.set(pair[0], pair[1]); return map; } /** * Adds `value` to `set`. * * @private * @param {Object} set The set to modify. * @param {*} value The value to add. * @returns {Object} Returns `set`. */ function addSetEntry(set, value) { // Don't return `set.add` because it's not chainable in IE 11. set.add(value); return set; } /** * A faster alternative to `Function#apply`, this function invokes `func` * with the `this` binding of `thisArg` and the arguments of `args`. * * @private * @param {Function} func The function to invoke. * @param {*} thisArg The `this` binding of `func`. * @param {Array} args The arguments to invoke `func` with. * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { switch (args.length) { case 0: return func.call(thisArg); case 1: return func.call(thisArg, args[0]); case 2: return func.call(thisArg, args[0], args[1]); case 3: return func.call(thisArg, args[0], args[1], args[2]); } return func.apply(thisArg, args); } /** * A specialized version of `_.forEach` for arrays without support for * iteratee shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array == null ? 0 : array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { break; } } return array; } /** * A specialized version of `_.filter` for arrays without support for * iteratee shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result[resIndex++] = value; } } return result; } /** * A specialized version of `_.includes` for arrays without support for * specifying an index to search from. * * @private * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludes(array, value) { var length = array == null ? 0 : array.length; return !!length && baseIndexOf(array, value, 0) > -1; } /** * This function is like `arrayIncludes` except that it accepts a comparator. * * @private * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @param {Function} comparator The comparator invoked per element. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludesWith(array, value, comparator) { var index = -1, length = array == null ? 0 : array.length; while (++index < length) { if (comparator(value, array[index])) { return true; } } return false; } /** * A specialized version of `_.map` for arrays without support for iteratee * shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { var index = -1, length = array == null ? 0 : array.length, result = Array(length); while (++index < length) { result[index] = iteratee(array[index], index, array); } return result; } /** * Appends the elements of `values` to `array`. * * @private * @param {Array} array The array to modify. * @param {Array} values The values to append. * @returns {Array} Returns `array`. */ function arrayPush(array, values) { var index = -1, length = values.length, offset = array.length; while (++index < length) { array[offset + index] = values[index]; } return array; } /** * A specialized version of `_.reduce` for arrays without support for * iteratee shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initAccum] Specify using the first element of `array` as * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, length = array == null ? 0 : array.length; if (initAccum && length) { accumulator = array[++index]; } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } /** * A specialized version of `_.some` for arrays without support for iteratee * shorthands. * * @private * @param {Array} [array] The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function arraySome(array, predicate) { var index = -1, length = array == null ? 0 : array.length; while (++index < length) { if (predicate(array[index], index, array)) { return true; } } return false; } /** * Converts an ASCII `string` to an array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the converted array. */ function asciiToArray(string) { return string.split(""); } /** * The base implementation of `_.findIndex` and `_.findLastIndex` without * support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Function} predicate The function invoked per iteration. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseFindIndex(array, predicate, fromIndex, fromRight) { var length = array.length, index = fromIndex + (fromRight ? 1 : -1); while (fromRight ? index-- : ++index < length) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex); } /** * The base implementation of `_.isNaN` without support for number objects. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. */ function baseIsNaN(value) { return value !== value; } /** * The base implementation of `_.property` without support for deep paths. * * @private * @param {string} key The key of the property to get. * @returns {Function} Returns the new accessor function. */ function baseProperty(key) { return function(object) { return object == null ? undefined : object[key]; }; } /** * The base implementation of `_.times` without support for iteratee shorthands * or max array length checks. * * @private * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the array of results. */ function baseTimes(n, iteratee) { var index = -1, result = Array(n); while (++index < n) { result[index] = iteratee(index); } return result; } /** * The base implementation of `_.unary` without support for storing metadata. * * @private * @param {Function} func The function to cap arguments for. * @returns {Function} Returns the new capped function. */ function baseUnary(func) { return function(value) { return func(value); }; } /** * The base implementation of `_.values` and `_.valuesIn` which creates an * array of `object` property values corresponding to the property names * of `props`. * * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. * @returns {Object} Returns the array of property values. */ function baseValues(object, props) { return arrayMap(props, function(key) { return object[key]; }); } /** * Checks if a `cache` value for `key` exists. * * @private * @param {Object} cache The cache to query. * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function cacheHas(cache, key) { return cache.has(key); } /** * Gets the value at `key` of `object`. * * @private * @param {Object} [object] The object to query. * @param {string} key The key of the property to get. * @returns {*} Returns the property value. */ function getValue(object, key) { return object == null ? undefined : object[key]; } /** * Checks if `string` contains Unicode symbols. * * @private * @param {string} string The string to inspect. * @returns {boolean} Returns `true` if a symbol is found, else `false`. */ function hasUnicode(string) { return reHasUnicode.test(string); } /** * Converts `iterator` to an array. * * @private * @param {Object} iterator The iterator to convert. * @returns {Array} Returns the converted array. */ function iteratorToArray(iterator) { var data, result = []; while (!(data = iterator.next()).done) { result.push(data.value); } return result; } /** * Converts `map` to its key-value pairs. * * @private * @param {Object} map The map to convert. * @returns {Array} Returns the key-value pairs. */ function mapToArray(map) { var index = -1, result = Array(map.size); map.forEach(function(value, key) { result[++index] = [key, value]; }); return result; } /** * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. * @param {Function} transform The argument transform. * @returns {Function} Returns the new function. */ function overArg(func, transform) { return function(arg) { return func(transform(arg)); }; } /** * Converts `set` to an array of its values. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the values. */ function setToArray(set) { var index = -1, result = Array(set.size); set.forEach(function(value) { result[++index] = value; }); return result; } /** * A specialized version of `_.indexOf` which performs strict equality * comparisons of values, i.e. `===`. * * @private * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function strictIndexOf(array, value, fromIndex) { var index = fromIndex - 1, length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * Converts `string` to an array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the converted array. */ function stringToArray(string) { return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string); } /** * Converts a Unicode `string` to an array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the converted array. */ function unicodeToArray(string) { return string.match(reUnicode) || []; } /*--------------------------------------------------------------------------*/ /** Used for built-in method references. */ var arrayProto = Array.prototype, funcProto = Function.prototype, objectProto = Object.prototype; /** Used to detect overreaching core-js shims. */ var coreJsData = root["__core-js_shared__"]; /** Used to resolve the decompiled source of functions. */ var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to detect methods masquerading as native. */ var maskSrcKey = (function() { var uid = /[^.]+$/.exec( (coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO) || "" ); return uid ? "Symbol(src)_1." + uid : ""; })(); /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var nativeObjectToString = objectProto.toString; /** Used to infer the `Object` constructor. */ var objectCtorString = funcToString.call(Object); /** Used to detect if a method is native. */ var reIsNative = RegExp( "^" + funcToString .call(hasOwnProperty) .replace(reRegExpChar, "\\$&") .replace( /hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?" ) + "$" ); /** Built-in value references. */ var Buffer = moduleExports ? root.Buffer : undefined, Symbol = root.Symbol, Uint8Array = root.Uint8Array, allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, getPrototype = overArg(Object.getPrototypeOf, Object), objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, symIterator = Symbol ? Symbol.iterator : undefined, symToStringTag = Symbol ? Symbol.toStringTag : undefined; var defineProperty = (function() { try { var func = getNative(Object, "defineProperty"); func({}, "", {}); return func; } catch (e) {} })(); /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeGetSymbols = Object.getOwnPropertySymbols, nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeNow = Date.now; /* Built-in method references that are verified to be native. */ var DataView = getNative(root, "DataView"), Map = getNative(root, "Map"), Promise = getNative(root, "Promise"), Set = getNative(root, "Set"), WeakMap = getNative(root, "WeakMap"), nativeCreate = getNative(Object, "create"); /** Used to lookup unminified function names. */ var realNames = {}; /** Used to detect maps, sets, and weakmaps. */ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap); /** Used to convert symbols to primitives and strings. */ var symbolProto = Symbol ? Symbol.prototype : undefined, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, symbolToString = symbolProto ? symbolProto.toString : undefined; /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps `value` to enable implicit method * chain sequences. Methods that operate on and return arrays, collections, * and functions can be chained together. Methods that retrieve a single value * or may return a primitive value will automatically end the chain sequence * and return the unwrapped value. Otherwise, the value must be unwrapped * with `_#value`. * * Explicit chain sequences, which must be unwrapped with `_#value`, may be * enabled using `_.chain`. * * The execution of chained methods is lazy, that is, it's deferred until * `_#value` is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. * Shortcut fusion is an optimization to merge iteratee calls; this avoids * the creation of intermediate arrays and can greatly reduce the number of * iteratee executions. Sections of a chain sequence qualify for shortcut * fusion if the section is applied to an array and iteratees accept only * one argument. The heuristic for whether a section qualifies for shortcut * fusion is subject to change. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. * * In addition to lodash methods, wrappers have `Array` and `String` methods. * * The wrapper `Array` methods are: * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` * * The wrapper `String` methods are: * `replace` and `split` * * The wrapper methods that support shortcut fusion are: * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` * * The chainable wrapper methods are: * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, * `zipObject`, `zipObjectDeep`, and `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, * `upperFirst`, `value`, and `words` * * @name _ * @constructor * @category Seq * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * function square(n) { * return n * n; * } * * var wrapped = _([1, 2, 3]); * * // Returns an unwrapped value. * wrapped.reduce(_.add); * // => 6 * * // Returns a wrapped value. * var squares = wrapped.map(square); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash() { // No operation performed. } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} proto The object to inherit from. * @returns {Object} Returns the new object. */ var baseCreate = (function() { function object() {} return function(proto) { if (!isObject(proto)) { return {}; } if (objectCreate) { return objectCreate(proto); } object.prototype = proto; var result = new object(); object.prototype = undefined; return result; }; })(); /*------------------------------------------------------------------------*/ /** * Creates a hash object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Hash(entries) { var index = -1, length = entries == null ? 0 : entries.length; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the hash. * * @private * @name clear * @memberOf Hash */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; this.size = 0; } /** * Removes `key` and its value from the hash. * * @private * @name delete * @memberOf Hash * @param {Object} hash The hash to modify. * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { var result = this.has(key) && delete this.__data__[key]; this.size -= result ? 1 : 0; return result; } /** * Gets the hash value for `key`. * * @private * @name get * @memberOf Hash * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function hashGet(key) { var data = this.__data__; if (nativeCreate) { var result = data[key]; return result === HASH_UNDEFINED ? undefined : result; } return hasOwnProperty.call(data, key) ? data[key] : undefined; } /** * Checks if a hash value for `key` exists. * * @private * @name has * @memberOf Hash * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function hashHas(key) { var data = this.__data__; return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); } /** * Sets the hash `key` to `value`. * * @private * @name set * @memberOf Hash * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the hash instance. */ function hashSet(key, value) { var data = this.__data__; this.size += this.has(key) ? 0 : 1; data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value; return this; } // Add methods to `Hash`. Hash.prototype.clear = hashClear; Hash.prototype["delete"] = hashDelete; Hash.prototype.get = hashGet; Hash.prototype.has = hashHas; Hash.prototype.set = hashSet; /*------------------------------------------------------------------------*/ /** * Creates an list cache object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function ListCache(entries) { var index = -1, length = entries == null ? 0 : entries.length; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the list cache. * * @private * @name clear * @memberOf ListCache */ function listCacheClear() { this.__data__ = []; this.size = 0; } /** * Removes `key` and its value from the list cache. * * @private * @name delete * @memberOf ListCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function listCacheDelete(key) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) { return false; } var lastIndex = data.length - 1; if (index == lastIndex) { data.pop(); } else { splice.call(data, index, 1); } --this.size; return true; } /** * Gets the list cache value for `key`. * * @private * @name get * @memberOf ListCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function listCacheGet(key) { var data = this.__data__, index = assocIndexOf(data, key); return index < 0 ? undefined : data[index][1]; } /** * Checks if a list cache value for `key` exists. * * @private * @name has * @memberOf ListCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function listCacheHas(key) { return assocIndexOf(this.__data__, key) > -1; } /** * Sets the list cache `key` to `value`. * * @private * @name set * @memberOf ListCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the list cache instance. */ function listCacheSet(key, value) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) { ++this.size; data.push([key, value]); } else { data[index][1] = value; } return this; } // Add methods to `ListCache`. ListCache.prototype.clear = listCacheClear; ListCache.prototype["delete"] = listCacheDelete; ListCache.prototype.get = listCacheGet; ListCache.prototype.has = listCacheHas; ListCache.prototype.set = listCacheSet; /*------------------------------------------------------------------------*/ /** * Creates a map cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function MapCache(entries) { var index = -1, length = entries == null ? 0 : entries.length; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the map. * * @private * @name clear * @memberOf MapCache */ function mapCacheClear() { this.size = 0; this.__data__ = { hash: new Hash(), map: new (Map || ListCache)(), string: new Hash() }; } /** * Removes `key` and its value from the map. * * @private * @name delete * @memberOf MapCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { var result = getMapData(this, key)["delete"](key); this.size -= result ? 1 : 0; return result; } /** * Gets the map value for `key`. * * @private * @name get * @memberOf MapCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function mapCacheGet(key) { return getMapData(this, key).get(key); } /** * Checks if a map value for `key` exists. * * @private * @name has * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapCacheHas(key) { return getMapData(this, key).has(key); } /** * Sets the map `key` to `value`. * * @private * @name set * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { var data = getMapData(this, key), size = data.size; data.set(key, value); this.size += data.size == size ? 0 : 1; return this; } // Add methods to `MapCache`. MapCache.prototype.clear = mapCacheClear; MapCache.prototype["delete"] = mapCacheDelete; MapCache.prototype.get = mapCacheGet; MapCache.prototype.has = mapCacheHas; MapCache.prototype.set = mapCacheSet; /*------------------------------------------------------------------------*/ /** * * Creates an array cache object to store unique values. * * @private * @constructor * @param {Array} [values] The values to cache. */ function SetCache(values) { var index = -1, length = values == null ? 0 : values.length; this.__data__ = new MapCache(); while (++index < length) { this.add(values[index]); } } /** * Adds `value` to the array cache. * * @private * @name add * @memberOf SetCache * @alias push * @param {*} value The value to cache. * @returns {Object} Returns the cache instance. */ function setCacheAdd(value) { this.__data__.set(value, HASH_UNDEFINED); return this; } /** * Checks if `value` is in the array cache. * * @private * @name has * @memberOf SetCache * @param {*} value The value to search for. * @returns {number} Returns `true` if `value` is found, else `false`. */ function setCacheHas(value) { return this.__data__.has(value); } // Add methods to `SetCache`. SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; SetCache.prototype.has = setCacheHas; /*------------------------------------------------------------------------*/ /** * Creates a stack cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { var data = (this.__data__ = new ListCache(entries)); this.size = data.size; } /** * Removes all key-value entries from the stack. * * @private * @name clear * @memberOf Stack */ function stackClear() { this.__data__ = new ListCache(); this.size = 0; } /** * Removes `key` and its value from the stack. * * @private * @name delete * @memberOf Stack * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { var data = this.__data__, result = data["delete"](key); this.size = data.size; return result; } /** * Gets the stack value for `key`. * * @private * @name get * @memberOf Stack * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function stackGet(key) { return this.__data__.get(key); } /** * Checks if a stack value for `key` exists. * * @private * @name has * @memberOf Stack * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function stackHas(key) { return this.__data__.has(key); } /** * Sets the stack `key` to `value`. * * @private * @name set * @memberOf Stack * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { var data = this.__data__; if (data instanceof ListCache) { var pairs = data.__data__; if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) { pairs.push([key, value]); this.size = ++data.size; return this; } data = this.__data__ = new MapCache(pairs); } data.set(key, value); this.size = data.size; return this; } // Add methods to `Stack`. Stack.prototype.clear = stackClear; Stack.prototype["delete"] = stackDelete; Stack.prototype.get = stackGet; Stack.prototype.has = stackHas; Stack.prototype.set = stackSet; /*------------------------------------------------------------------------*/ /** * Creates an array of the enumerable property names of the array-like `value`. * * @private * @param {*} value The value to query. * @param {boolean} inherited Specify returning inherited property names. * @returns {Array} Returns the array of property names. */ function arrayLikeKeys(value, inherited) { var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes(value.length, String) : [], length = result.length; for (var key in value) { if ( (inherited || hasOwnProperty.call(value, key)) && !( skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode. (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers. (isBuff && (key == "offset" || key == "parent")) || // PhantomJS 2 has enumerable non-index properties on typed arrays. (isType && (key == "buffer" || key == "byteLength" || key == "byteOffset")) || // Skip index properties. isIndex(key, length)) ) ) { result.push(key); } } return result; } /** * This function is like `assignValue` except that it doesn't assign * `undefined` values. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignMergeValue(object, key, value) { if ( (value !== undefined && !eq(object[key], value)) || (value === undefined && !(key in object)) ) { baseAssignValue(object, key, value); } } /** * Assigns `value` to `key` of `object` if the existing value is not equivalent * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignValue(object, key, value) { var objValue = object[key]; if ( !(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object)) ) { baseAssignValue(object, key, value); } } /** * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private * @param {Array} array The array to inspect. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ function assocIndexOf(array, key) { var length = array.length; while (length--) { if (eq(array[length][0], key)) { return length; } } return -1; } /** * The base implementation of `_.assign` without support for multiple sources * or `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssign(object, source) { return object && copyObject(source, keys(source), object); } /** * The base implementation of `_.assignIn` without support for multiple sources * or `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssignIn(object, source) { return object && copyObject(source, keysIn(source), object); } /** * The base implementation of `assignValue` and `assignMergeValue` without * value checks. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function baseAssignValue(object, key, value) { if (key == "__proto__" && defineProperty) { defineProperty(object, key, { configurable: true, enumerable: true, value: value, writable: true }); } else { object[key] = value; } } /** * The base implementation of `_.clone` and `_.cloneDeep` which tracks * traversed objects. * * @private * @param {*} value The value to clone. * @param {boolean} bitmask The bitmask flags. * 1 - Deep clone * 2 - Flatten inherited properties * 4 - Clone symbols * @param {Function} [customizer] The function to customize cloning. * @param {string} [key] The key of `value`. * @param {Object} [object] The parent object of `value`. * @param {Object} [stack] Tracks traversed objects and their clone counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, bitmask, customizer, key, object, stack) { var result, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG; if (customizer) { result = object ? customizer(value, key, object, stack) : customizer(value); } if (result !== undefined) { return result; } if (!isObject(value)) { return value; } var isArr = isArray(value); if (isArr) { result = initCloneArray(value); if (!isDeep) { return copyArray(value, result); } } else { var tag = getTag(value), isFunc = tag == funcTag || tag == genTag; if (isBuffer(value)) { return cloneBuffer(value, isDeep); } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { result = isFlat || isFunc ? {} : initCloneObject(value); if (!isDeep) { return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value)); } } else { if (!cloneableTags[tag]) { return object ? value : {}; } result = initCloneByTag(value, tag, baseClone, isDeep); } } // Check for circular references and return its corresponding clone. stack || (stack = new Stack()); var stacked = stack.get(value); if (stacked) { return stacked; } stack.set(value, result); var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys; var props = isArr ? undefined : keysFunc(value); arrayEach(props || value, function(subValue, key) { if (props) { key = subValue; subValue = value[key]; } // Recursively populate clone (susceptible to call stack limits). assignValue( result, key, baseClone(subValue, bitmask, customizer, key, value, stack) ); }); return result; } /** * The base implementation of `_.forEach` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object} Returns `collection`. */ var baseEach = createBaseEach(baseForOwn); /** * The base implementation of `_.flatten` with support for restricting flattening. * * @private * @param {Array} array The array to flatten. * @param {number} depth The maximum recursion depth. * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, depth, predicate, isStrict, result) { var index = -1, length = array.length; predicate || (predicate = isFlattenable); result || (result = []); while (++index < length) { var value = array[index]; if (depth > 0 && predicate(value)) { if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result); } else { arrayPush(result, value); } } else if (!isStrict) { result[result.length] = value; } } return result; } /** * The base implementation of `baseForOwn` which iterates over `object` * properties returned by `keysFunc` and invokes `iteratee` for each property. * Iteratee functions may exit iteration early by explicitly returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ var baseFor = createBaseFor(); /** * The base implementation of `_.forOwn` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return object && baseFor(object, iteratee, keys); } /** * The base implementation of `_.get` without support for default values. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @returns {*} Returns the resolved value. */ function baseGet(object, path) { path = castPath(path, object); var index = 0, length = path.length; while (object != null && index < length) { object = object[toKey(path[index++])]; } return index && index == length ? object : undefined; } /** * The base implementation of `getAllKeys` and `getAllKeysIn` which uses * `keysFunc` and `symbolsFunc` to get the enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @param {Function} keysFunc The function to get the keys of `object`. * @param {Function} symbolsFunc The function to get the symbols of `object`. * @returns {Array} Returns the array of property names and symbols. */ function baseGetAllKeys(object, keysFunc, symbolsFunc) { var result = keysFunc(object); return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); } /** * The base implementation of `getTag` without fallbacks for buggy environments. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function baseGetTag(value) { if (value == null) { return value === undefined ? undefinedTag : nullTag; } return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value); } /** * The base implementation of `_.hasIn` without support for deep paths. * * @private * @param {Object} [object] The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHasIn(object, key) { return object != null && key in Object(object); } /** * The base implementation of `_.isArguments`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an `arguments` object, */ function baseIsArguments(value) { return isObjectLike(value) && baseGetTag(value) == argsTag; } /** * The base implementation of `_.isEqual` which supports partial comparisons * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {boolean} bitmask The bitmask flags. * 1 - Unordered comparison * 2 - Partial comparison * @param {Function} [customizer] The function to customize comparisons. * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, bitmask, customizer, stack) { if (value === other) { return true; } if ( value == null || other == null || (!isObjectLike(value) && !isObjectLike(other)) ) { return value !== value && other !== other; } return baseIsEqualDeep( value, other, bitmask, customizer, baseIsEqual, stack ); } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep( object, other, bitmask, customizer, equalFunc, stack ) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other); objTag = objTag == argsTag ? objectTag : objTag; othTag = othTag == argsTag ? objectTag : othTag; var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; if (isSameTag && isBuffer(object)) { if (!isBuffer(other)) { return false; } objIsArr = true; objIsObj = false; } if (isSameTag && !objIsObj) { stack || (stack = new Stack()); return objIsArr || isTypedArray(object) ? equalArrays( object, other, bitmask, customizer, equalFunc, stack ) : equalByTag( object, other, objTag, bitmask, customizer, equalFunc, stack ); } if (!(bitmask & COMPARE_PARTIAL_FLAG)) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); if (objIsWrapped || othIsWrapped) { var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other; stack || (stack = new Stack()); return equalFunc( objUnwrapped, othUnwrapped, bitmask, customizer, stack ); } } if (!isSameTag) { return false; } stack || (stack = new Stack()); return equalObjects( object, other, bitmask, customizer, equalFunc, stack ); } /** * The base implementation of `_.isMatch` without support for iteratee shorthands. * * @private * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Array} matchData The property names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, source, matchData, customizer) { var index = matchData.length, length = index, noCustomizer = !customizer; if (object == null) { return !length; } object = Object(object); while (index--) { var data = matchData[index]; if ( noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object) ) { return false; } } while (++index < length) { data = matchData[index]; var key = data[0], objValue = object[key], srcValue = data[1]; if (noCustomizer && data[2]) { if (objValue === undefined && !(key in object)) { return false; } } else { var stack = new Stack(); if (customizer) { var result = customizer( objValue, srcValue, key, object, source, stack ); } if ( !(result === undefined ? baseIsEqual( srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack ) : result) ) { return false; } } } return true; } /** * The base implementation of `_.isNative` without bad shim checks. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, * else `false`. */ function baseIsNative(value) { if (!isObject(value) || isMasked(value)) { return false; } var pattern = isFunction(value) ? reIsNative : reIsHostCtor; return pattern.test(toSource(value)); } /** * The base implementation of `_.isTypedArray` without Node.js optimizations. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. */ function baseIsTypedArray(value) { return ( isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)] ); } /** * The base implementation of `_.iteratee`. * * @private * @param {*} [value=_.identity] The value to convert to an iteratee. * @returns {Function} Returns the iteratee. */ function baseIteratee(value) { // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. if (typeof value == "function") { return value; } if (value == null) { return identity; } if (typeof value == "object") { return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); } return property(value); } /** * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { if (!isPrototype(object)) { return nativeKeys(object); } var result = []; for (var key in Object(object)) { if (hasOwnProperty.call(object, key) && key != "constructor") { result.push(key); } } return result; } /** * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { if (!isObject(object)) { return nativeKeysIn(object); } var isProto = isPrototype(object), result = []; for (var key in object) { if ( !( key == "constructor" && (isProto || !hasOwnProperty.call(object, key)) ) ) { result.push(key); } } return result; } /** * The base implementation of `_.matches` which doesn't clone `source`. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new spec function. */ function baseMatches(source) { var matchData = getMatchData(source); if (matchData.length == 1 && matchData[0][2]) { return matchesStrictComparable(matchData[0][0], matchData[0][1]); } return function(object) { return object === source || baseIsMatch(object, source, matchData); }; } /** * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. * * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function baseMatchesProperty(path, srcValue) { if (isKey(path) && isStrictComparable(srcValue)) { return matchesStrictComparable(toKey(path), srcValue); } return function(object) { var objValue = get(object, path); return objValue === undefined && objValue === srcValue ? hasIn(object, path) : baseIsEqual( srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG ); }; } /** * The base implementation of `_.merge` without support for multiple sources. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {number} srcIndex The index of `source`. * @param {Function} [customizer] The function to customize merged values. * @param {Object} [stack] Tracks traversed source values and their merged * counterparts. */ function baseMerge(object, source, srcIndex, customizer, stack) { if (object === source) { return; } baseFor( source, function(srcValue, key) { if (isObject(srcValue)) { stack || (stack = new Stack()); baseMergeDeep( object, source, key, srcIndex, baseMerge, customizer, stack ); } else { var newValue = customizer ? customizer( object[key], srcValue, key + "", object, source, stack ) : undefined; if (newValue === undefined) { newValue = srcValue; } assignMergeValue(object, key, newValue); } }, keysIn ); } /** * A specialized version of `baseMerge` for arrays and objects which performs * deep merges and tracks traversed objects enabling objects with circular * references to be merged. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {number} srcIndex The index of `source`. * @param {Function} mergeFunc The function to merge values. * @param {Function} [customizer] The function to customize assigned values. * @param {Object} [stack] Tracks traversed source values and their merged * counterparts. */ function baseMergeDeep( object, source, key, srcIndex, mergeFunc, customizer, stack ) { var objValue = object[key], srcValue = source[key], stacked = stack.get(srcValue); if (stacked) { assignMergeValue(object, key, stacked); return; } var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined; var isCommon = newValue === undefined; if (isCommon) { var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue); newValue = srcValue; if (isArr || isBuff || isTyped) { if (isArray(objValue)) { newValue = objValue; } else if (isArrayLikeObject(objValue)) { newValue = copyArray(objValue); } else if (isBuff) { isCommon = false; newValue = cloneBuffer(srcValue, true); } else if (isTyped) { isCommon = false; newValue = cloneTypedArray(srcValue, true); } else { newValue = []; } } else if (isPlainObject(srcValue) || isArguments(srcValue)) { newValue = objValue; if (isArguments(objValue)) { newValue = toPlainObject(objValue); } else if ( !isObject(objValue) || (srcIndex && isFunction(objValue)) ) { newValue = initCloneObject(srcValue); } } else { isCommon = false; } } if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). stack.set(srcValue, newValue); mergeFunc(newValue, srcValue, srcIndex, customizer, stack); stack["delete"](srcValue); } assignMergeValue(object, key, newValue); } /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new accessor function. */ function basePropertyDeep(path) { return function(object) { return baseGet(object, path); }; } /** * The base implementation of `_.rest` which doesn't validate or coerce arguments. * * @private * @param {Function} func The function to apply a rest parameter to. * @param {number} [start=func.length-1] The start position of the rest parameter. * @returns {Function} Returns the new function. */ function baseRest(func, start) { return setToString(overRest(func, start, identity), func + ""); } /** * The base implementation of `_.set`. * * @private * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { if (!isObject(object)) { return object; } path = castPath(path, object); var index = -1, length = path.length, lastIndex = length - 1, nested = object; while (nested != null && ++index < length) { var key = toKey(path[index]), newValue = value; if (index != lastIndex) { var objValue = nested[key]; newValue = customizer ? customizer(objValue, key, nested) : undefined; if (newValue === undefined) { newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {}; } } assignValue(nested, key, newValue); nested = nested[key]; } return object; } /** * The base implementation of `setToString` without support for hot loop shorting. * * @private * @param {Function} func The function to modify. * @param {Function} string The `toString` result. * @returns {Function} Returns `func`. */ var baseSetToString = !defineProperty ? identity : function(func, string) { return defineProperty(func, "toString", { configurable: true, enumerable: false, value: constant(string), writable: true }); }; /** * The base implementation of `_.toString` which doesn't convert nullish * values to empty strings. * * @private * @param {*} value The value to process. * @returns {string} Returns the string. */ function baseToString(value) { // Exit early for strings to avoid a performance hit in some environments. if (typeof value == "string") { return value; } if (isArray(value)) { // Recursively convert values (susceptible to call stack limits). return arrayMap(value, baseToString) + ""; } if (isSymbol(value)) { return symbolToString ? symbolToString.call(value) : ""; } var result = value + ""; return result == "0" && 1 / value == -INFINITY ? "-0" : result; } /** * The base implementation of `_.uniqBy` without support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new duplicate free array. */ function baseUniq(array, iteratee, comparator) { var index = -1, includes = arrayIncludes, length = array.length, isCommon = true, result = [], seen = result; if (comparator) { isCommon = false; includes = arrayIncludesWith; } else if (length >= LARGE_ARRAY_SIZE) { var set = iteratee ? null : createSet(array); if (set) { return setToArray(set); } isCommon = false; includes = cacheHas; seen = new SetCache(); } else { seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value) : value; value = comparator || value !== 0 ? value : 0; if (isCommon && computed === computed) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } if (iteratee) { seen.push(computed); } result.push(value); } else if (!includes(seen, computed, comparator)) { if (seen !== result) { seen.push(computed); } result.push(value); } } return result; } /** * Casts `value` to a path array if it's not one. * * @private * @param {*} value The value to inspect. * @param {Object} [object] The object to query keys on. * @returns {Array} Returns the cast property path array. */ function castPath(value, object) { if (isArray(value)) { return value; } return isKey(value, object) ? [value] : stringToPath(toString(value)); } /** * Creates a clone of `buffer`. * * @private * @param {Buffer} buffer The buffer to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Buffer} Returns the cloned buffer. */ function cloneBuffer(buffer, isDeep) { if (isDeep) { return buffer.slice(); } var length = buffer.length, result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); buffer.copy(result); return result; } /** * Creates a clone of `arrayBuffer`. * * @private * @param {ArrayBuffer} arrayBuffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function cloneArrayBuffer(arrayBuffer) { var result = new arrayBuffer.constructor(arrayBuffer.byteLength); new Uint8Array(result).set(new Uint8Array(arrayBuffer)); return result; } /** * Creates a clone of `dataView`. * * @private * @param {Object} dataView The data view to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned data view. */ function cloneDataView(dataView, isDeep) { var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; return new dataView.constructor( buffer, dataView.byteOffset, dataView.byteLength ); } /** * Creates a clone of `map`. * * @private * @param {Object} map The map to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned map. */ function cloneMap(map, isDeep, cloneFunc) { var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map); return arrayReduce(array, addMapEntry, new map.constructor()); } /** * Creates a clone of `regexp`. * * @private * @param {Object} regexp The regexp to clone. * @returns {Object} Returns the cloned regexp. */ function cloneRegExp(regexp) { var result = new regexp.constructor( regexp.source, reFlags.exec(regexp) ); result.lastIndex = regexp.lastIndex; return result; } /** * Creates a clone of `set`. * * @private * @param {Object} set The set to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned set. */ function cloneSet(set, isDeep, cloneFunc) { var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set); return arrayReduce(array, addSetEntry, new set.constructor()); } /** * Creates a clone of the `symbol` object. * * @private * @param {Object} symbol The symbol object to clone. * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; } /** * Creates a clone of `typedArray`. * * @private * @param {Object} typedArray The typed array to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned typed array. */ function cloneTypedArray(typedArray, isDeep) { var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; return new typedArray.constructor( buffer, typedArray.byteOffset, typedArray.length ); } /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function copyArray(source, array) { var index = -1, length = source.length; array || (array = Array(length)); while (++index < length) { array[index] = source[index]; } return array; } /** * Copies properties of `source` to `object`. * * @private * @param {Object} source The object to copy properties from. * @param {Array} props The property identifiers to copy. * @param {Object} [object={}] The object to copy properties to. * @param {Function} [customizer] The function to customize copied values. * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { var isNew = !object; object || (object = {}); var index = -1, length = props.length; while (++index < length) { var key = props[index]; var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined; if (newValue === undefined) { newValue = source[key]; } if (isNew) { baseAssignValue(object, key, newValue); } else { assignValue(object, key, newValue); } } return object; } /** * Copies own symbols of `source` to `object`. * * @private * @param {Object} source The object to copy symbols from. * @param {Object} [object={}] The object to copy symbols to. * @returns {Object} Returns `object`. */ function copySymbols(source, object) { return copyObject(source, getSymbols(source), object); } /** * Copies own and inherited symbols of `source` to `object`. * * @private * @param {Object} source The object to copy symbols from. * @param {Object} [object={}] The object to copy symbols to. * @returns {Object} Returns `object`. */ function copySymbolsIn(source, object) { return copyObject(source, getSymbolsIn(source), object); } /** * Creates a function like `_.assign`. * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { return baseRest(function(object, sources) { var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined, guard = length > 2 ? sources[2] : undefined; customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : undefined; if (guard && isIterateeCall(sources[0], sources[1], guard)) { customizer = length < 3 ? undefined : customizer; length = 1; } object = Object(object); while (++index < length) { var source = sources[index]; if (source) { assigner(object, source, index, customizer); } } return object; }); } /** * Creates a `baseEach` or `baseEachRight` function. * * @private * @param {Function} eachFunc The function to iterate over a collection. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseEach(eachFunc, fromRight) { return function(collection, iteratee) { if (collection == null) { return collection; } if (!isArrayLike(collection)) { return eachFunc(collection, iteratee); } var length = collection.length, index = fromRight ? length : -1, iterable = Object(collection); while (fromRight ? index-- : ++index < length) { if (iteratee(iterable[index], index, iterable) === false) { break; } } return collection; }; } /** * Creates a base function for methods like `_.forIn` and `_.forOwn`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseFor(fromRight) { return function(object, iteratee, keysFunc) { var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length; while (length--) { var key = props[fromRight ? length : ++index]; if (iteratee(iterable[key], key, iterable) === false) { break; } } return object; }; } /** * Creates a set object of `values`. * * @private * @param {Array} values The values to add to the set. * @returns {Object} Returns the new set. */ var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function(values) { return new Set(values); }; /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Object} stack Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; if (arrLength != othLength && !(isPartial && othLength > arrLength)) { return false; } // Assume cyclic values are equal. var stacked = stack.get(array); if (stacked && stack.get(other)) { return stacked == other; } var index = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined; stack.set(array, other); stack.set(other, array); // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], othValue = other[index]; if (customizer) { var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer( arrValue, othValue, index, array, other, stack ); } if (compared !== undefined) { if (compared) { continue; } result = false; break; } // Recursively compare arrays (susceptible to call stack limits). if (seen) { if ( !arraySome(other, function(othValue, othIndex) { if ( !cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc( arrValue, othValue, bitmask, customizer, stack )) ) { return seen.push(othIndex); } }) ) { result = false; break; } } else if ( !( arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack) ) ) { result = false; break; } } stack["delete"](array); stack["delete"](other); return result; } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag( object, other, tag, bitmask, customizer, equalFunc, stack ) { switch (tag) { case dataViewTag: if ( object.byteLength != other.byteLength || object.byteOffset != other.byteOffset ) { return false; } object = object.buffer; other = other.buffer; case arrayBufferTag: if ( object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other)) ) { return false; } return true; case boolTag: case dateTag: case numberTag: // Coerce booleans to `1` or `0` and dates to milliseconds. // Invalid dates are coerced to `NaN`. return eq(+object, +other); case errorTag: return ( object.name == other.name && object.message == other.message ); case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring // for more details. return object == other + ""; case mapTag: var convert = mapToArray; case setTag: var isPartial = bitmask & COMPARE_PARTIAL_FLAG; convert || (convert = setToArray); if (object.size != other.size && !isPartial) { return false; } // Assume cyclic values are equal. var stacked = stack.get(object); if (stacked) { return stacked == other; } bitmask |= COMPARE_UNORDERED_FLAG; // Recursively compare objects (susceptible to call stack limits). stack.set(object, other); var result = equalArrays( convert(object), convert(other), bitmask, customizer, equalFunc, stack ); stack["delete"](object); return result; case symbolTag: if (symbolValueOf) { return ( symbolValueOf.call(object) == symbolValueOf.call(other) ); } } return false; } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. * @param {Function} customizer The function to customize comparisons. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects( object, other, bitmask, customizer, equalFunc, stack ) { var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length; if (objLength != othLength && !isPartial) { return false; } var index = objLength; while (index--) { var key = objProps[index]; if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false; } } // Assume cyclic values are equal. var stacked = stack.get(object); if (stacked && stack.get(other)) { return stacked == other; } var result = true; stack.set(object, other); stack.set(other, object); var skipCtor = isPartial; while (++index < objLength) { key = objProps[index]; var objValue = object[key], othValue = other[key]; if (customizer) { var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); } // Recursively compare objects (susceptible to call stack limits). if ( !(compared === undefined ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared) ) { result = false; break; } skipCtor || (skipCtor = key == "constructor"); } if (result && !skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal. if ( objCtor != othCtor && ("constructor" in object && "constructor" in other) && !( typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor ) ) { result = false; } } stack["delete"](object); stack["delete"](other); return result; } /** * Creates an array of own enumerable property names and symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeys(object) { return baseGetAllKeys(object, keys, getSymbols); } /** * Creates an array of own and inherited enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeysIn(object) { return baseGetAllKeys(object, keysIn, getSymbolsIn); } /** * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, * this function returns the custom method, otherwise it returns `baseIteratee`. * If arguments are provided, the chosen function is invoked with them and * its result is returned. * * @private * @param {*} [value] The value to convert to an iteratee. * @param {number} [arity] The arity of the created iteratee. * @returns {Function} Returns the chosen function or its result. */ function getIteratee() { var result = lodash.iteratee || iteratee; result = result === iteratee ? baseIteratee : result; return arguments.length ? result(arguments[0], arguments[1]) : result; } /** * Gets the data for `map`. * * @private * @param {Object} map The map to query. * @param {string} key The reference key. * @returns {*} Returns the map data. */ function getMapData(map, key) { var data = map.__data__; return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; } /** * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { var result = keys(object), length = result.length; while (length--) { var key = result[length], value = object[key]; result[length] = [key, value, isStrictComparable(value)]; } return result; } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = getValue(object, key); return baseIsNative(value) ? value : undefined; } /** * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. * * @private * @param {*} value The value to query. * @returns {string} Returns the raw `toStringTag`. */ function getRawTag(value) { var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; try { value[symToStringTag] = undefined; var unmasked = true; } catch (e) {} var result = nativeObjectToString.call(value); if (unmasked) { if (isOwn) { value[symToStringTag] = tag; } else { delete value[symToStringTag]; } } return result; } /** * Creates an array of the own enumerable symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ var getSymbols = !nativeGetSymbols ? stubArray : function(object) { if (object == null) { return []; } object = Object(object); return arrayFilter(nativeGetSymbols(object), function(symbol) { return propertyIsEnumerable.call(object, symbol); }); }; /** * Creates an array of the own and inherited enumerable symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { var result = []; while (object) { arrayPush(result, getSymbols(object)); object = getPrototype(object); } return result; }; /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. if ( (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map()) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || (Set && getTag(new Set()) != setTag) || (WeakMap && getTag(new WeakMap()) != weakMapTag) ) { getTag = function(value) { var result = baseGetTag(value), Ctor = result == objectTag ? value.constructor : undefined, ctorString = Ctor ? toSource(Ctor) : ""; if (ctorString) { switch (ctorString) { case dataViewCtorString: return dataViewTag; case mapCtorString: return mapTag; case promiseCtorString: return promiseTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } } return result; }; } /** * Checks if `path` exists on `object`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @param {Function} hasFunc The function to check properties. * @returns {boolean} Returns `true` if `path` exists, else `false`. */ function hasPath(object, path, hasFunc) { path = castPath(path, object); var index = -1, length = path.length, result = false; while (++index < length) { var key = toKey(path[index]); if (!(result = object != null && hasFunc(object, key))) { break; } object = object[key]; } if (result || ++index != length) { return result; } length = object == null ? 0 : object.length; return ( !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)) ); } /** * Initializes an array clone. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the initialized clone. */ function initCloneArray(array) { var length = array.length, result = array.constructor(length); // Add properties assigned by `RegExp#exec`. if ( length && typeof array[0] == "string" && hasOwnProperty.call(array, "index") ) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {Object} object The object to clone. * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {}; } /** * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to clone. * @param {string} tag The `toStringTag` of the object to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the initialized clone. */ function initCloneByTag(object, tag, cloneFunc, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: return cloneArrayBuffer(object); case boolTag: case dateTag: return new Ctor(+object); case dataViewTag: return cloneDataView(object, isDeep); case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: return cloneTypedArray(object, isDeep); case mapTag: return cloneMap(object, isDeep, cloneFunc); case numberTag: case stringTag: return new Ctor(object); case regexpTag: return cloneRegExp(object); case setTag: return cloneSet(object, isDeep, cloneFunc); case symbolTag: return cloneSymbol(object); } } /** * Checks if `value` is a flattenable `arguments` object or array. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ function isFlattenable(value) { return ( isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]) ); } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { length = length == null ? MAX_SAFE_INTEGER : length; return ( !!length && (typeof value == "number" || reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length) ); } /** * Checks if the given arguments are from an iteratee call. * * @private * @param {*} value The potential iteratee value argument. * @param {*} index The potential iteratee index or key argument. * @param {*} object The potential iteratee object argument. * @returns {boolean} Returns `true` if the arguments are from an iteratee call, * else `false`. */ function isIterateeCall(value, index, object) { if (!isObject(object)) { return false; } var type = typeof index; if ( type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object ) { return eq(object[index], value); } return false; } /** * Checks if `value` is a property name and not a property path. * * @private * @param {*} value The value to check. * @param {Object} [object] The object to query keys on. * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { if (isArray(value)) { return false; } var type = typeof value; if ( type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value) ) { return true; } return ( reIsPlainProp.test(value) || !reIsDeepProp.test(value) || (object != null && value in Object(object)) ); } /** * Checks if `value` is suitable for use as unique object key. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is suitable, else `false`. */ function isKeyable(value) { var type = typeof value; return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; } /** * Checks if `func` has its source masked. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` is masked, else `false`. */ function isMasked(func) { return !!maskSrcKey && maskSrcKey in func; } /** * Checks if `value` is likely a prototype object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ function isPrototype(value) { var Ctor = value && value.constructor, proto = (typeof Ctor == "function" && Ctor.prototype) || objectProto; return value === proto; } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && !isObject(value); } /** * A specialized version of `matchesProperty` for source values suitable * for strict equality comparisons, i.e. `===`. * * @private * @param {string} key The key of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function matchesStrictComparable(key, srcValue) { return function(object) { if (object == null) { return false; } return ( object[key] === srcValue && (srcValue !== undefined || key in Object(object)) ); }; } /** * A specialized version of `_.memoize` which clears the memoized function's * cache when it exceeds `MAX_MEMOIZE_SIZE`. * * @private * @param {Function} func The function to have its output memoized. * @returns {Function} Returns the new memoized function. */ function memoizeCapped(func) { var result = memoize(func, function(key) { if (cache.size === MAX_MEMOIZE_SIZE) { cache.clear(); } return key; }); var cache = result.cache; return result; } /** * This function is like * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * except that it includes inherited enumerable properties. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function nativeKeysIn(object) { var result = []; if (object != null) { for (var key in Object(object)) { result.push(key); } } return result; } /** * Converts `value` to a string using `Object.prototype.toString`. * * @private * @param {*} value The value to convert. * @returns {string} Returns the converted string. */ function objectToString(value) { return nativeObjectToString.call(value); } /** * A specialized version of `baseRest` which transforms the rest array. * * @private * @param {Function} func The function to apply a rest parameter to. * @param {number} [start=func.length-1] The start position of the rest parameter. * @param {Function} transform The rest array transform. * @returns {Function} Returns the new function. */ function overRest(func, start, transform) { start = nativeMax(start === undefined ? func.length - 1 : start, 0); return function() { var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array(length); while (++index < length) { array[index] = args[start + index]; } index = -1; var otherArgs = Array(start + 1); while (++index < start) { otherArgs[index] = args[index]; } otherArgs[start] = transform(array); return apply(func, this, otherArgs); }; } /** * Sets the `toString` method of `func` to return `string`. * * @private * @param {Function} func The function to modify. * @param {Function} string The `toString` result. * @returns {Function} Returns `func`. */ var setToString = shortOut(baseSetToString); /** * Creates a function that'll short out and invoke `identity` instead * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` * milliseconds. * * @private * @param {Function} func The function to restrict. * @returns {Function} Returns the new shortable function. */ function shortOut(func) { var count = 0, lastCalled = 0; return function() { var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { return arguments[0]; } } else { count = 0; } return func.apply(undefined, arguments); }; } /** * Converts `string` to a property path array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ var stringToPath = memoizeCapped(function(string) { var result = []; if (reLeadingDot.test(string)) { result.push(""); } string.replace(rePropName, function(match, number, quote, string) { result.push( quote ? string.replace(reEscapeChar, "$1") : number || match ); }); return result; }); /** * Converts `value` to a string key if it's not a string or symbol. * * @private * @param {*} value The value to inspect. * @returns {string|symbol} Returns the key. */ function toKey(value) { if (typeof value == "string" || isSymbol(value)) { return value; } var result = value + ""; return result == "0" && 1 / value == -INFINITY ? "-0" : result; } /** * Converts `func` to its source code. * * @private * @param {Function} func The function to convert. * @returns {string} Returns the source code. */ function toSource(func) { if (func != null) { try { return funcToString.call(func); } catch (e) {} try { return func + ""; } catch (e) {} } return ""; } /*------------------------------------------------------------------------*/ /** * Creates an array of unique values, in order, from all given arrays using * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of combined values. * @example * * _.union([2], [1, 2]); * // => [2, 1] */ var union = baseRest(function(arrays) { return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); }); /*------------------------------------------------------------------------*/ /** * Iterates over elements of `collection` and invokes `iteratee` for each element. * The iteratee is invoked with three arguments: (value, index|key, collection). * Iteratee functions may exit iteration early by explicitly returning `false`. * * **Note:** As with other "Collections" methods, objects with a "length" * property are iterated like arrays. To avoid this behavior use `_.forIn` * or `_.forOwn` for object iteration. * * @static * @memberOf _ * @since 0.1.0 * @alias each * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array|Object} Returns `collection`. * @see _.forEachRight * @example * * _.forEach([1, 2], function(value) { * console.log(value); * }); * // => Logs `1` then `2`. * * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { * console.log(key); * }); * // => Logs 'a' then 'b' (iteration order is not guaranteed). */ function forEach(collection, iteratee) { var func = isArray(collection) ? arrayEach : baseEach; return func(collection, getIteratee(iteratee, 3)); } /** * Checks if `value` is in `collection`. If `collection` is a string, it's * checked for a substring of `value`, otherwise * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * is used for equality comparisons. If `fromIndex` is negative, it's used as * the offset from the end of `collection`. * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object|string} collection The collection to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. * @returns {boolean} Returns `true` if `value` is found, else `false`. * @example * * _.includes([1, 2, 3], 1); * // => true * * _.includes([1, 2, 3], 1, 2); * // => false * * _.includes({ 'a': 1, 'b': 2 }, 1); * // => true * * _.includes('abcd', 'bc'); * // => true */ function includes(collection, value, fromIndex, guard) { collection = isArrayLike(collection) ? collection : values(collection); fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0; var length = collection.length; if (fromIndex < 0) { fromIndex = nativeMax(length + fromIndex, 0); } return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1; } /*------------------------------------------------------------------------*/ /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided, it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the map cache key. The `func` * is invoked with the `this` binding of the memoized function. * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) * method interface of `clear`, `delete`, `get`, `has`, and `set`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoized function. * @example * * var object = { 'a': 1, 'b': 2 }; * var other = { 'c': 3, 'd': 4 }; * * var values = _.memoize(_.values); * values(object); * // => [1, 2] * * values(other); * // => [3, 4] * * object.a = 2; * values(object); * // => [1, 2] * * // Modify the result cache. * values.cache.set(object, ['a', 'b']); * values(object); * // => ['a', 'b'] * * // Replace `_.memoize.Cache`. * _.memoize.Cache = WeakMap; */ function memoize(func, resolver) { if ( typeof func != "function" || (resolver != null && typeof resolver != "function") ) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; if (cache.has(key)) { return cache.get(key); } var result = func.apply(this, args); memoized.cache = cache.set(key, result) || cache; return result; }; memoized.cache = new (memoize.Cache || MapCache)(); return memoized; } // Expose `MapCache`. memoize.Cache = MapCache; /*------------------------------------------------------------------------*/ /** * Performs a * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'a': 1 }; * var other = { 'a': 1 }; * * _.eq(object, object); * // => true * * _.eq(object, other); * // => false * * _.eq('a', 'a'); * // => true * * _.eq('a', Object('a')); * // => false * * _.eq(NaN, NaN); * // => true */ function eq(value, other) { return value === other || (value !== value && other !== other); } /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an `arguments` object, * else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ var isArguments = baseIsArguments( (function() { return arguments; })() ) ? baseIsArguments : function(value) { return ( isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee") ); }; /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(document.body.children); * // => false * * _.isArray('abc'); * // => false * * _.isArray(_.noop); * // => false */ var isArray = Array.isArray; /** * Checks if `value` is array-like. A value is considered array-like if it's * not a function and has a `value.length` that's an integer greater than or * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. * @example * * _.isArrayLike([1, 2, 3]); * // => true * * _.isArrayLike(document.body.children); * // => true * * _.isArrayLike('abc'); * // => true * * _.isArrayLike(_.noop); * // => false */ function isArrayLike(value) { return value != null && isLength(value.length) && !isFunction(value); } /** * This method is like `_.isArrayLike` except that it also checks if `value` * is an object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, * else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); * // => true * * _.isArrayLikeObject(document.body.children); * // => true * * _.isArrayLikeObject('abc'); * // => false * * _.isArrayLikeObject(_.noop); * // => false */ function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value); } /** * Checks if `value` is a buffer. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. * @example * * _.isBuffer(new Buffer(2)); * // => true * * _.isBuffer(new Uint8Array(2)); * // => false */ var isBuffer = nativeIsBuffer || stubFalse; /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a function, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { if (!isObject(value)) { return false; } // The use of `Object#toString` avoids issues with the `typeof` operator // in Safari 9 which returns 'object' for typed arrays and other constructors. var tag = baseGetTag(value); return ( tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag ); } /** * Checks if `value` is a valid array-like length. * * **Note:** This method is loosely based on * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); * // => true * * _.isLength(Number.MIN_VALUE); * // => false * * _.isLength(Infinity); * // => false * * _.isLength('3'); * // => false */ function isLength(value) { return ( typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER ); } /** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(_.noop); * // => true * * _.isObject(null); * // => false */ function isObject(value) { var type = typeof value; return value != null && (type == "object" || type == "function"); } /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * * _.isObjectLike({}); * // => true * * _.isObjectLike([1, 2, 3]); * // => true * * _.isObjectLike(_.noop); * // => false * * _.isObjectLike(null); * // => false */ function isObjectLike(value) { return value != null && typeof value == "object"; } /** * Checks if `value` is a plain object, that is, an object created by the * `Object` constructor or one with a `[[Prototype]]` of `null`. * * @static * @memberOf _ * @since 0.8.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Foo() { * this.a = 1; * } * * _.isPlainObject(new Foo); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true * * _.isPlainObject(Object.create(null)); * // => true */ function isPlainObject(value) { if (!isObjectLike(value) || baseGetTag(value) != objectTag) { return false; } var proto = getPrototype(value); if (proto === null) { return true; } var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor; return ( typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString ); } /** * Checks if `value` is classified as a `String` primitive or object. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a string, else `false`. * @example * * _.isString('abc'); * // => true * * _.isString(1); * // => false */ function isString(value) { return ( typeof value == "string" || (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag) ); } /** * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. * @example * * _.isSymbol(Symbol.iterator); * // => true * * _.isSymbol('abc'); * // => false */ function isSymbol(value) { return ( typeof value == "symbol" || (isObjectLike(value) && baseGetTag(value) == symbolTag) ); } /** * Checks if `value` is classified as a typed array. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. * @example * * _.isTypedArray(new Uint8Array); * // => true * * _.isTypedArray([]); * // => false */ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; /** * Checks if `value` is `undefined`. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true * * _.isUndefined(null); * // => false */ function isUndefined(value) { return value === undefined; } /** * Converts `value` to an array. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to convert. * @returns {Array} Returns the converted array. * @example * * _.toArray({ 'a': 1, 'b': 2 }); * // => [1, 2] * * _.toArray('abc'); * // => ['a', 'b', 'c'] * * _.toArray(1); * // => [] * * _.toArray(null); * // => [] */ function toArray(value) { if (!value) { return []; } if (isArrayLike(value)) { return isString(value) ? stringToArray(value) : copyArray(value); } if (symIterator && value[symIterator]) { return iteratorToArray(value[symIterator]()); } var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values; return func(value); } /** * Converts `value` to a finite number. * * @static * @memberOf _ * @since 4.12.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted number. * @example * * _.toFinite(3.2); * // => 3.2 * * _.toFinite(Number.MIN_VALUE); * // => 5e-324 * * _.toFinite(Infinity); * // => 1.7976931348623157e+308 * * _.toFinite('3.2'); * // => 3.2 */ function toFinite(value) { if (!value) { return value === 0 ? value : 0; } value = toNumber(value); if (value === INFINITY || value === -INFINITY) { var sign = value < 0 ? -1 : 1; return sign * MAX_INTEGER; } return value === value ? value : 0; } /** * Converts `value` to an integer. * * **Note:** This method is loosely based on * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * * _.toInteger(3.2); * // => 3 * * _.toInteger(Number.MIN_VALUE); * // => 0 * * _.toInteger(Infinity); * // => 1.7976931348623157e+308 * * _.toInteger('3.2'); * // => 3 */ function toInteger(value) { var result = toFinite(value), remainder = result % 1; return result === result ? remainder ? result - remainder : result : 0; } /** * Converts `value` to a number. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * * _.toNumber(3.2); * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 * * _.toNumber(Infinity); * // => Infinity * * _.toNumber('3.2'); * // => 3.2 */ function toNumber(value) { if (typeof value == "number") { return value; } if (isSymbol(value)) { return NAN; } if (isObject(value)) { var other = typeof value.valueOf == "function" ? value.valueOf() : value; value = isObject(other) ? other + "" : other; } if (typeof value != "string") { return value === 0 ? value : +value; } value = value.replace(reTrim, ""); var isBinary = reIsBinary.test(value); return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; } /** * Converts `value` to a plain object flattening inherited enumerable string * keyed properties of `value` to own properties of the plain object. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to convert. * @returns {Object} Returns the converted plain object. * @example * * function Foo() { * this.b = 2; * } * * Foo.prototype.c = 3; * * _.assign({ 'a': 1 }, new Foo); * // => { 'a': 1, 'b': 2 } * * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); * // => { 'a': 1, 'b': 2, 'c': 3 } */ function toPlainObject(value) { return copyObject(value, keysIn(value)); } /** * Converts `value` to a string. An empty string is returned for `null` * and `undefined` values. The sign of `-0` is preserved. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {string} Returns the converted string. * @example * * _.toString(null); * // => '' * * _.toString(-0); * // => '-0' * * _.toString([1, 2, 3]); * // => '1,2,3' */ function toString(value) { return value == null ? "" : baseToString(value); } /*------------------------------------------------------------------------*/ /** * Gets the value at `path` of `object`. If the resolved value is * `undefined`, the `defaultValue` is returned in its place. * * @static * @memberOf _ * @since 3.7.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @param {*} [defaultValue] The value returned for `undefined` resolved values. * @returns {*} Returns the resolved value. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.get(object, 'a[0].b.c'); * // => 3 * * _.get(object, ['a', '0', 'b', 'c']); * // => 3 * * _.get(object, 'a.b.c', 'default'); * // => 'default' */ function get(object, path, defaultValue) { var result = object == null ? undefined : baseGet(object, path); return result === undefined ? defaultValue : result; } /** * Checks if `path` is a direct or inherited property of `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * * var object = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.hasIn(object, 'a'); * // => true * * _.hasIn(object, 'a.b'); * // => true * * _.hasIn(object, ['a', 'b']); * // => true * * _.hasIn(object, 'b'); * // => false */ function hasIn(object, path) { return object != null && hasPath(object, path, baseHasIn); } /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keys(new Foo); * // => ['a', 'b'] (iteration order is not guaranteed) * * _.keys('hi'); * // => ['0', '1'] */ function keys(object) { return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); } /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } /** * This method is like `_.assign` except that it recursively merges own and * inherited enumerable string keyed properties of source objects into the * destination object. Source properties that resolve to `undefined` are * skipped if a destination value exists. Array and plain object properties * are merged recursively. Other objects and value types are overridden by * assignment. Source objects are applied from left to right. Subsequent * sources overwrite property assignments of previous sources. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 0.5.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @example * * var object = { * 'a': [{ 'b': 2 }, { 'd': 4 }] * }; * * var other = { * 'a': [{ 'c': 3 }, { 'e': 5 }] * }; * * _.merge(object, other); * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } */ var merge = createAssigner(function(object, source, srcIndex) { baseMerge(object, source, srcIndex); }); /** * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, * it's created. Arrays are created for missing index properties while objects * are created for all other missing properties. Use `_.setWith` to customize * `path` creation. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 3.7.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @returns {Object} Returns `object`. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.set(object, 'a[0].b.c', 4); * console.log(object.a[0].b.c); * // => 4 * * _.set(object, ['x', '0', 'y', 'z'], 5); * console.log(object.x[0].y.z); * // => 5 */ function set(object, path, value) { return object == null ? object : baseSet(object, path, value); } /** * Creates an array of the own enumerable string keyed property values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.values(new Foo); * // => [1, 2] (iteration order is not guaranteed) * * _.values('hi'); * // => ['h', 'i'] */ function values(object) { return object == null ? [] : baseValues(object, keys(object)); } /*------------------------------------------------------------------------*/ /** * Creates a function that returns `value`. * * @static * @memberOf _ * @since 2.4.0 * @category Util * @param {*} value The value to return from the new function. * @returns {Function} Returns the new constant function. * @example * * var objects = _.times(2, _.constant({ 'a': 1 })); * * console.log(objects); * // => [{ 'a': 1 }, { 'a': 1 }] * * console.log(objects[0] === objects[1]); * // => true */ function constant(value) { return function() { return value; }; } /** * This method returns the first argument it receives. * * @static * @since 0.1.0 * @memberOf _ * @category Util * @param {*} value Any value. * @returns {*} Returns `value`. * @example * * var object = { 'a': 1 }; * * console.log(_.identity(object) === object); * // => true */ function identity(value) { return value; } /** * Creates a function that invokes `func` with the arguments of the created * function. If `func` is a property name, the created function returns the * property value for a given element. If `func` is an array or object, the * created function returns `true` for elements that contain the equivalent * source properties, otherwise it returns `false`. * * @static * @since 4.0.0 * @memberOf _ * @category Util * @param {*} [func=_.identity] The value to convert to a callback. * @returns {Function} Returns the callback. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false } * ]; * * // The `_.matches` iteratee shorthand. * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); * // => [{ 'user': 'barney', 'age': 36, 'active': true }] * * // The `_.matchesProperty` iteratee shorthand. * _.filter(users, _.iteratee(['user', 'fred'])); * // => [{ 'user': 'fred', 'age': 40 }] * * // The `_.property` iteratee shorthand. * _.map(users, _.iteratee('user')); * // => ['barney', 'fred'] * * // Create custom iteratee shorthands. * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { * return !_.isRegExp(func) ? iteratee(func) : function(string) { * return func.test(string); * }; * }); * * _.filter(['abc', 'def'], /ef/); * // => ['def'] */ function iteratee(func) { return baseIteratee( typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG) ); } /** * This method returns `undefined`. * * @static * @memberOf _ * @since 2.3.0 * @category Util * @example * * _.times(2, _.noop); * // => [undefined, undefined] */ function noop() { // No operation performed. } /** * Creates a function that returns the value at `path` of a given object. * * @static * @memberOf _ * @since 2.4.0 * @category Util * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new accessor function. * @example * * var objects = [ * { 'a': { 'b': 2 } }, * { 'a': { 'b': 1 } } * ]; * * _.map(objects, _.property('a.b')); * // => [2, 1] * * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); * // => [1, 2] */ function property(path) { return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); } /** * This method returns a new empty array. * * @static * @memberOf _ * @since 4.13.0 * @category Util * @returns {Array} Returns the new empty array. * @example * * var arrays = _.times(2, _.stubArray); * * console.log(arrays); * // => [[], []] * * console.log(arrays[0] === arrays[1]); * // => false */ function stubArray() { return []; } /** * This method returns `false`. * * @static * @memberOf _ * @since 4.13.0 * @category Util * @returns {boolean} Returns `false`. * @example * * _.times(2, _.stubFalse); * // => [false, false] */ function stubFalse() { return false; } /*------------------------------------------------------------------------*/ // Add methods that return wrapped values in chain sequences. lodash.constant = constant; lodash.iteratee = iteratee; lodash.keys = keys; lodash.keysIn = keysIn; lodash.memoize = memoize; lodash.merge = merge; lodash.property = property; lodash.set = set; lodash.toArray = toArray; lodash.toPlainObject = toPlainObject; lodash.union = union; lodash.values = values; /*------------------------------------------------------------------------*/ // Add methods that return unwrapped values in chain sequences. lodash.eq = eq; lodash.forEach = forEach; lodash.get = get; lodash.hasIn = hasIn; lodash.identity = identity; lodash.includes = includes; lodash.isArguments = isArguments; lodash.isArray = isArray; lodash.isArrayLike = isArrayLike; lodash.isArrayLikeObject = isArrayLikeObject; lodash.isBuffer = isBuffer; lodash.isFunction = isFunction; lodash.isLength = isLength; lodash.isObject = isObject; lodash.isObjectLike = isObjectLike; lodash.isPlainObject = isPlainObject; lodash.isString = isString; lodash.isSymbol = isSymbol; lodash.isTypedArray = isTypedArray; lodash.isUndefined = isUndefined; lodash.stubArray = stubArray; lodash.stubFalse = stubFalse; lodash.noop = noop; lodash.toFinite = toFinite; lodash.toInteger = toInteger; lodash.toNumber = toNumber; lodash.toString = toString; // Add aliases. lodash.each = forEach; /*------------------------------------------------------------------------*/ /** * The semantic version number. * * @static * @memberOf _ * @type {string} */ lodash.VERSION = VERSION; /*--------------------------------------------------------------------------*/ if (freeModule) { // Export for Node.js. (freeModule.exports = lodash)._ = lodash; // Export for CommonJS support. freeExports._ = lodash; } }.call(this)); ================================================ FILE: packages/browser-sync/lib/logger.js ================================================ "use strict"; var messages = require("./connect-utils"); var utils = require("./utils"); var _ = require("./lodash.custom"); var chalk = require("chalk"); var template = (prefix) => "[" + chalk.blue(prefix) + "] " var logger = require("eazy-logger").Logger({ useLevelPrefixes: false }); module.exports.logger = logger; /** * @param name * @returns {*} */ module.exports.getLogger = function(name) { return logger.clone(function(config) { config.prefix = config.prefix + template(name) return config; }); }; /** * Logging Callbacks */ module.exports.callbacks = { /** * Log when file-watching has started * @param {BrowserSync} bs * @param data */ "file:watching": function(bs, data) { if (Object.keys(data).length) { logger.info("Watching files..."); } }, /** * Log when a file changes * @param {BrowserSync} bs * @param data */ "file:reload": function(bs, data) { if (canLogFileChange(bs, data)) { if (data.path[0] === "*") { return logger.info( chalk.cyan("Reloading files that match: %s"), chalk.magenta(data.path) ); } logger.info( chalk.cyan("File event [%s] : %s"), data.event, chalk.magenta(data.path), ); } }, /** * */ "service:exit": function() { logger.debug("Exiting..."); }, /** * */ "browser:reload": function(bs, data = {}) { if (canLogFileChange(bs)) { if (data.files && data.files.length > 1) { return logger.info( chalk.cyan(`Reloading Browsers... (buffered %s events)`), data.files.length ); } logger.info(chalk.cyan("Reloading Browsers...")); } }, /** * */ "browser:error": function() { logger.error( "Couldn't open browser (if you are using BrowserSync in a " + "headless environment, you might want to set the %s option to %s)", chalk.cyan("open"), chalk.cyan("false"), ); }, /** * @param {BrowserSync} bs * @param data */ "stream:changed": function(bs, data) { if (canLogFileChange(bs)) { var changed = data.changed; logger.info( chalk.cyan("%s %s changed (%s)"), changed.length, changed.length > 1 ? "files" : "file", chalk.magenta(changed.join(", ")) ); } }, /** * Client connected logging * @param {BrowserSync} bs * @param data */ "client:connected": function(bs, data) { var uaString = utils.getUaString(data.ua); var msg = chalk.cyan("Browser Connected: %s, version: %s"); var method = "info"; if (!bs.options.get("logConnections")) { method = "debug"; } logger.log(method, msg, chalk.magenta(uaString.name), chalk.magenta(uaString.version)); }, /** * Main logging when the service is running * @param {BrowserSync} bs * @param data */ "service:running": function(bs, data) { const type = data.type; if (bs.options.get("json")) { return console.log( JSON.stringify({ "service:running": { options: bs.options.toJS() } }) ); } if (type === "server") { var baseDir = bs.options.getIn(["server", "baseDir"]); logUrls(bs.options.get("urls").toJS()); if (baseDir) { if (utils.isList(baseDir)) { baseDir.forEach(serveFiles); } else { serveFiles(baseDir); } } } if (type === "proxy") { logger.info( "Proxying: %s", chalk.cyan(bs.options.getIn(["proxy", "target"])) ); logUrls(bs.options.get("urls").toJS()); } if (type === "snippet") { if (bs.options.get("logSnippet")) { logger.info( chalk.bold(`Copy the following snippet into your website, just before the closing ${chalk.cyan('')} tag`) ); logger.unprefixed("info", messages.scriptTags(bs.options)); } logUrls( bs.options .get("urls") .filter(function(value, key) { return key.slice(0, 2) === "ui"; }) .toJS() ); } function serveFiles(base) { logger.info("Serving files from: %s", chalk.magenta(base)); } } }; /** * Plugin interface for BrowserSync * @param {EventEmitter} emitter * @param {BrowserSync} bs * @returns {Object} */ module.exports.plugin = function(emitter, bs) { var logPrefix = bs.options.get("logPrefix"); var logLevel = bs.options.get("logLevel"); // Should set logger level here! logger.setLevel(logLevel); if (logPrefix) { if (_.isFunction(logPrefix)) { logger.setPrefix(logPrefix); } else { logger.setPrefix(template(logPrefix)); } } _.each(exports.callbacks, function(func, event) { emitter.on(event, func.bind(this, bs)); }); return logger; }; /** * * @param urls */ function logUrls(urls) { var keys = Object.keys(urls); var longestName = 0; var longesturl = 0; var offset = 2; if (!keys.length) { return; } var names = keys.map(function(key) { if (key.length > longestName) { longestName = key.length; } if (urls[key].length > longesturl) { longesturl = urls[key].length; } return key; }); var underline = getChars(longestName + offset + longesturl + 1, "-"); var underlined = false; logger.info(chalk.bold("Access URLs:")); logger.unprefixed("info", " %s", chalk.grey(underline)); keys.forEach(function(key, i) { var keyname = getKeyName(key); logger.unprefixed( "info", " %s: %s", getPadding(key.length, longestName + offset) + keyname, chalk.magenta(urls[key]) ); if (!underlined && names[i + 1] && names[i + 1].indexOf("ui") > -1) { underlined = true; logger.unprefixed("info", " %s", chalk.grey(underline)); } }); logger.unprefixed("info", " %s", chalk.grey(underline)); } /** * @param {Number} len * @param {Number} max * @returns {string} */ function getPadding(len, max) { return new Array(max - (len + 1)).join(" "); } /** * @param {Number} len * @param {String} char * @returns {string} */ function getChars(len, char) { return new Array(len).join(char); } /** * Transform url-key names into something more presentable * @param key * @returns {string} */ function getKeyName(key) { if (key.indexOf("ui") > -1) { if (key === "ui") { return "UI"; } if (key === "ui-external") { return "UI External"; } } return key.substr(0, 1).toUpperCase() + key.substring(1); } /** * Determine if file changes should be logged * @param bs * @param data * @returns {boolean} */ function canLogFileChange(bs, data) { if (data && data.log === false) { return false; } return bs.options.get("logFileChanges"); } ================================================ FILE: packages/browser-sync/lib/options.ts ================================================ import { BsTempOptions, TransformResult } from "./cli/cli-options"; const _ = require("./lodash.custom"); import * as Immutable from "immutable"; import * as defaultConfig from "./default-config"; /** * Move top-level ws options to proxy.ws * This is to allow it to be set from the CLI * @param incoming */ export function setProxyWs(incoming: BsTempOptions): TransformResult { if (incoming.get("ws") && incoming.get("mode") === "proxy") { return [incoming.setIn(["proxy", "ws"], true), []]; } return [incoming, []]; } /** * @param incoming */ export function setOpen(incoming: BsTempOptions): TransformResult { return [ incoming.update("open", function(open) { if (incoming.get("mode") === "snippet") { if (open !== "ui" && open !== "ui-external") { return false; } } return open; }), [] ]; } /** * Set the running mode * @param incoming */ export function setMode(incoming: BsTempOptions): TransformResult { const output = incoming.set( "mode", (function() { if (incoming.get("server")) { return "server"; } if (incoming.get("proxy")) { return "proxy"; } return "snippet"; })() ); return [output, []]; } /** * @param incoming */ export function setScheme(incoming: BsTempOptions): TransformResult { var scheme = "http"; if (incoming.getIn(["server", "https"])) { scheme = "https"; } if (incoming.get("https")) { scheme = "https"; } if (incoming.getIn(["proxy", "url", "protocol"])) { if (incoming.getIn(["proxy", "url", "protocol"]) === "https:") { scheme = "https"; } } return [incoming.set("scheme", scheme), []]; } /** * @param incoming */ export function setStartPath(incoming: BsTempOptions): TransformResult { if (incoming.get("proxy")) { var path = incoming.getIn(["proxy", "url", "path"]); if (path !== "/") { return [incoming.set("startPath", path), []]; } } return [incoming, []]; } /** * @param incoming */ export function setNamespace(incoming: BsTempOptions): TransformResult { var namespace = incoming.getIn(["socket", "namespace"]); if (_.isFunction(namespace)) { return [ incoming.setIn( ["socket", "namespace"], namespace((defaultConfig.socket as any).namespace) ), [] ]; } return [incoming, []]; } /** * @param incoming */ export function setServerOpts(incoming: BsTempOptions): TransformResult { if (!incoming.get("server")) { return [incoming, []]; } var indexarg = incoming.getIn(["server", "index"]) || "index.html"; var optPath = ["server", "serveStaticOptions"]; if (!incoming.getIn(optPath)) { return [ incoming.setIn( optPath, Immutable.Map({ index: indexarg }) ), [] ]; } if (!incoming.hasIn(optPath.concat(["index"]))) { return [incoming.setIn(optPath.concat(["index"]), indexarg), []]; } return [incoming, []]; } export function liftExtensionsOptionFromCli( incoming: BsTempOptions ): TransformResult { // cli extensions var optPath = ["server", "serveStaticOptions"]; if (incoming.get("extensions")) { return [ incoming.setIn( optPath.concat(["extensions"]), incoming.get("extensions") ), [] ]; } return [incoming, []]; } /** * Back-compat fixes for rewriteRules being set to a boolean */ export function fixRewriteRules(incoming: BsTempOptions): TransformResult { return [ incoming.update("rewriteRules", function(rr) { return Immutable.List([]) .concat(rr) .filter(Boolean); }), [] ]; } export function fixSnippetIgnorePaths( incoming: BsTempOptions ): TransformResult { var ignorePaths = incoming.getIn(["snippetOptions", "ignorePaths"]); if (ignorePaths) { if (_.isString(ignorePaths)) { ignorePaths = [ignorePaths]; } ignorePaths = ignorePaths.map(ensureSlash); return [ incoming.setIn( ["snippetOptions", "blacklist"], Immutable.List(ignorePaths) ), [] ]; } return [incoming, []]; } export function fixSnippetIncludePaths( incoming: BsTempOptions ): TransformResult { var includePaths = incoming.getIn(["snippetOptions", "whitelist"]); if (includePaths) { includePaths = includePaths.map(ensureSlash); return [ incoming.setIn( ["snippetOptions", "whitelist"], Immutable.List(includePaths) ), [] ]; } return [incoming, []]; } /** * Enforce paths to begin with a forward slash */ function ensureSlash(item) { if (item[0] !== "/") { return "/" + item; } return item; } /** * */ export function setMiddleware(incoming: BsTempOptions): TransformResult { var mw = getMiddlwares(incoming); return [incoming.set("middleware", mw), []]; } /** * top-level option, or given as part of the proxy/server option * @param item * @returns {*} */ function getMiddlwares(item) { var mw = item.get("middleware"); var serverMw = item.getIn(["server", "middleware"]); var proxyMw = item.getIn(["proxy", "middleware"]); var list = Immutable.List([]); if (mw) { return listMerge(list, mw); } if (serverMw) { return listMerge(list, serverMw); } if (proxyMw) { return listMerge(list, proxyMw); } return list; } /** * @param item * @returns {*} */ function isList(item) { return Immutable.List.isList(item); } /** * @param list * @param item * @returns {*} */ function listMerge(list, item) { if (_.isFunction(item)) { list = list.push(item); } if (isList(item) && item.size) { list = list.merge(item); } return list; } /** * @param incoming * @returns {*} */ export function setUiPort(incoming: BsTempOptions): TransformResult { if (incoming.get("uiPort")) { return [incoming.setIn(["ui", "port"], incoming.get("uiPort")), []]; } return [incoming, []]; } ================================================ FILE: packages/browser-sync/lib/plugins.js ================================================ var Immutable = require("immutable"); var Map = Immutable.Map; var isMap = Immutable.Map.isMap; var List = Immutable.List; var path = require("path"); var fs = require("fs"); const { parseParams } = require("./utils"); var Plugin = Immutable.Record({ moduleName: "", name: "", active: true, module: undefined, options: Map({}), via: "inline", dir: process.cwd(), init: undefined, errors: List([]) }); /** * Accept a string/object * and resolve it into the plugin format above * @param item * @returns {*} */ function resolvePlugin(item) { /** * Handle when string was given, such as plugins: ['bs-html-injector'] */ if (typeof item === "string") { return getFromString(item); } if (!isMap(item)) { return new Plugin().mergeDeep({ errors: [new Error("Plugin not supported in this format")] }); } if (item.has("module")) { var nameOrObj = item.get("module"); var options = item.get("options"); /** * The 'module' key can be a string, this allows * inline plugin references, but with options * eg: * * bs.init({ * plugins: [ * { * module: './myjs-file.js' * options: { * files: "*.html" * } * } * ] * }); */ if (typeof nameOrObj === "string") { return getFromString(nameOrObj).mergeDeep({ options: options }); } /** * If the plugin was given completely inline (because it needs options) * eg: * * bs.init({ * plugins: [ * { * module: { * plugin: function() { * console.log('My plugin code') * } * }, * options: { * files: "*.html" * } * } * ] * }) */ if (Immutable.Map.isMap(nameOrObj)) { return new Plugin({ module: nameOrObj, options: options }); } } /** * If a module was given directly. For example, ater calling require. * * eg: * var myplugin = require('./some-js'); * bs.init({plugins: [myplugin]}); */ if (item.has("plugin")) { return new Plugin({ module: item }); } /** * If we reach here, the plugin option was used incorrectly */ return new Plugin().mergeDeep({ errors: [new Error("Plugin was not configured correctly")] }); } module.exports.resolvePlugin = resolvePlugin; /** * Load a plugin from disk * @param item * @returns {*} */ function requirePlugin(item) { /** * if the "module" property already exists and * is not a string, then we bail and don't bother looking * for the file */ if (item.get("module") && typeof item.get("module") !== "string") { return item; } try { /** * Try a raw node require() call - this will be how * regular "npm installed" plugins wil work */ var maybe = require.resolve(item.get("name")); return item.set("module", require(maybe)); } catch (e) { /** * If require threw an MODULE_NOT_FOUND error, try again * by resolving from cwd. This is needed since cli * users will not add ./ to the front of a path (which * node requires to resolve from cwd) */ if (e.code === "MODULE_NOT_FOUND") { var maybe = path.resolve(process.cwd(), item.get("name")); if (fs.existsSync(maybe)) { return item.set("module", require(maybe)); } else { /** * Finally return a plugin that contains the error * this will be picked up later and discarded */ return item.update("errors", function(errors) { return errors.concat(e); }); } } throw e; } } module.exports.requirePlugin = requirePlugin; function getFromString(string) { /** * We allow query strings for plugins, so always split on ? */ var split = string.split("?"); var outGoing = new Plugin({ moduleName: split[0], name: split[0] }); if (split.length > 1) { return outGoing.update("options", function(opts) { const parsed = parseParams(split[1]); return opts.mergeDeep(parsed); }); } return outGoing; } ================================================ FILE: packages/browser-sync/lib/public/exit.js ================================================ "use strict"; /** * @param {BrowserSync} browserSync * @returns {Function} */ module.exports = function(browserSync) { function exit() { if (browserSync.active) { browserSync.events.emit("service:exit"); browserSync.cleanup(); } } return exit; }; ================================================ FILE: packages/browser-sync/lib/public/init.ts ================================================ var _ = require("../lodash.custom"); import { merge, printErrors } from "../cli/cli-options"; /** * @param {BrowserSync} browserSync * @param {String} [name] - instance name * @param {Object} pjson * @returns {Function} */ module.exports = function(browserSync, name, pjson) { return function() { /** * Handle new + old signatures for init. */ var args = require("../args")(_.toArray(arguments)); /** * If the current instance is already running, just return an error */ if (browserSync.active) { return args.cb(new Error(`Instance: ${name} is already running!`)); } // Env specific items args.config.version = pjson.version; args.config.cwd = args.config.cwd || process.cwd(); const [opts, errors] = merge(args.config); if (errors.length) { return args.cb(new Error(printErrors(errors))); } return browserSync.init(opts, args.cb); }; }; ================================================ FILE: packages/browser-sync/lib/public/notify.js ================================================ "use strict"; /** * @param {BrowserSync} browserSync * @returns {Function} */ module.exports = function(browserSync) { return function(msg, timeout) { if (msg) { browserSync.events.emit("browser:notify", { message: msg, timeout: timeout || 2000, override: true }); } }; }; ================================================ FILE: packages/browser-sync/lib/public/pause.js ================================================ "use strict"; /** * @param {BrowserSync} browserSync * @returns {Function} */ module.exports = function(browserSync) { return function() { browserSync.paused = true; }; }; ================================================ FILE: packages/browser-sync/lib/public/public-utils.js ================================================ "use strict"; var _ = require("../lodash.custom"); module.exports = { /** * Emit the internal `file:change` event * @param {EventEmitter} emitter * @param {string} path * @param {boolean} [log] */ emitChangeEvent: function emitChangeEvent(emitter, path, log) { emitter.emit("file:changed", { path: path, log: log, namespace: "core", event: "change" }); }, /** * Emit the internal `browser:reload` event * @param {EventEmitter} emitter */ emitBrowserReload: function emitChangeEvent(emitter) { emitter.emit("_browser:reload"); }, /** * Emit the internal `stream:changed` event * @param {EventEmitter} emitter * @param {Array} changed */ emitStreamChangedEvent: function(emitter, changed) { emitter.emit("stream:changed", { changed: changed }); }, /** * This code handles the switch between .reload & .stream * since 2.6.0 * @param name * @param args * @returns {boolean} */ isStreamArg: function(name, args) { if (name === "stream") { return true; } if (name !== "reload") { return false; } var firstArg = args[0]; /** * If here, it's reload with args */ if (_.isObject(firstArg)) { if (!Array.isArray(firstArg) && Object.keys(firstArg).length) { return firstArg.stream === true; } } return false; } }; ================================================ FILE: packages/browser-sync/lib/public/reload.js ================================================ "use strict"; var utils = require("../utils"); var publicUtils = require("./public-utils"); var _ = require("../lodash.custom"); var defaultConfig = require("../default-config"); var stream = require("./stream"); /** * @param emitter * @returns {Function} */ module.exports = function(emitter) { /** * Inform browsers about file changes. * * eg: reload("core.css") */ function browserSyncReload(opts) { /** * BACKWARDS COMPATIBILITY: * Passing an object as the only arg to the `reload` * method with at *least* the key-value pair of {stream: true}, * was only ever used for streams support - so it's safe to check * for that signature here and defer to the * dedicated `.stream()` method instead. */ if (_.isObject(opts)) { if (!Array.isArray(opts) && Object.keys(opts).length) { if (opts.stream === true) { return stream(emitter)(opts); } } } /** * Handle single string paths such as * reload("core.css") */ if (typeof opts === "string" && opts !== "undefined") { return publicUtils.emitChangeEvent(emitter, opts, true); } /** * Handle an array of file paths such as * reload(["core.css, "ie.css"]) */ if (Array.isArray(opts)) { return opts.forEach(function(filepath) { publicUtils.emitChangeEvent(emitter, filepath, true); }); } /** * At this point the argument given was neither an object, * array or string so we simply perform a reload. This is to * allow the following syntax to work as expected * * reload(); */ return publicUtils.emitBrowserReload(emitter); } return browserSyncReload; }; ================================================ FILE: packages/browser-sync/lib/public/resume.js ================================================ "use strict"; /** * @param {BrowserSync} browserSync * @returns {Function} */ module.exports = function(browserSync) { return function() { browserSync.paused = false; }; }; ================================================ FILE: packages/browser-sync/lib/public/stream.js ================================================ "use strict"; var path = require("path"); var micromatch = require("micromatch"); var utils = require("./public-utils"); /** * @param emitter * @returns {Function} */ module.exports = function(emitter) { /** * Return a transform/through stream that listens to file * paths and fires internal Browsersync events. * @param {{once: boolean, match: string|array}} [opts] * @returns {Stream.Transform} */ function browserSyncThroughStream(opts) { opts = opts || {}; var emitted = false; var Transform = require("stream").Transform; var reload = new Transform({ objectMode: true }); var changed = []; reload._transform = function(file, encoding, next) { var stream = this; /** * End is always called to send the current file down * stream. Browsersync never acts upon a stream, * we only `listen` to it. */ function end() { stream.push(file); // always send the file down-stream next(); } /** * If {match: } was provided, test the * current filepath against it */ if (opts.match) { if (!micromatch(file.path, opts.match, { dot: true }).length) { return end(); } } /** * if {once: true} provided, emit the reload event for the * first file only */ if (opts.once === true && !emitted) { utils.emitBrowserReload(emitter); emitted = true; } else { // handle multiple if (opts.once === true && emitted) { } else { if (file.path) { emitted = true; utils.emitChangeEvent(emitter, file.path, false); changed.push(path.basename(file.path)); } } } end(); }; /** * When this current operation has finished, emit the * steam:changed event so that any loggers can pick up it * @param next * @private */ reload._flush = function(next) { if (changed.length) { utils.emitStreamChangedEvent(emitter, changed); } next(); }; return reload; } return browserSyncThroughStream; }; ================================================ FILE: packages/browser-sync/lib/server/index.js ================================================ "use strict"; var enableDestroy = require("server-destroy"); var _ = require("../lodash.custom"); /** * Browsersync server * Three available modes: Snippet, Server or Proxy */ module.exports.plugin = function(bs) { var debug = bs.debug; var proxy = bs.options.get("proxy"); var type = bs.options.get("mode"); var bsServer = createServer(bs); if (type === "server" || type === "snippet") { debug( "Static Server running ({magenta:%s}) ...", bs.options.get("scheme") ); } if (proxy) { debug("Proxy running, proxing: {magenta:%s}", proxy.get("target")); } if (bsServer) { /** * Allow server to be destroyed gracefully */ enableDestroy(bsServer.server); /** * Listen on the available port */ bsServer.server.listen( bs.options.get("port"), bs.options.get("listen") ); /** * Hack to deal with https://github.com/socketio/socket.io/issues/1602#issuecomment-224270022 */ bs.registerCleanupTask(function() { if (bs.io && bs.io.sockets) { setCloseReceived(bs.io.sockets); } if (bs.ui && bs.ui.socket) { setCloseReceived(bs.ui.socket); } }); /** * Destroy the server on cleanup */ bs.registerCleanupTask(function() { bsServer.server.destroy(); }); } function setCloseReceived(io) { Object.keys(io.sockets).forEach(function(key) { _.set( io.sockets[key], "conn.transport.socket._closeReceived", true ); }); } debug("Running mode: %s", type.toUpperCase()); return { server: bsServer.server, app: bsServer.app }; }; /** * Launch the server for serving the client JS plus static files * @param {BrowserSync} bs * @returns {{staticServer: (http.Server), proxyServer: (http.Server)}} */ function createServer(bs) { var proxy = bs.options.get("proxy"); var server = bs.options.get("server"); if (!proxy && !server) { return require("./snippet-server")(bs); } if (proxy) { return require("./proxy-server")(bs); } if (server) { return require("./static-server")(bs); } } module.exports.createServer = createServer; ================================================ FILE: packages/browser-sync/lib/server/proxy-server.js ================================================ "use strict"; var httpProxy = require("http-proxy"); var utils = require("./utils"); var proxyUtils = require("./proxy-utils"); var Immutable = require("immutable"); var Map = require("immutable").Map; var List = require("immutable").List; /** * Default options that are passed along to http-proxy */ var defaultHttpProxyOptions = Map({ /** * This ensures targets are more likely to * accept each request */ changeOrigin: true, /** * This handles redirects */ autoRewrite: true, /** * This allows our self-signed certs to be used for development */ secure: false, ws: true }); var defaultCookieOptions = Map({ stripDomain: true }); var ProxyOption = Immutable.Record({ route: "", target: "", rewriteRules: true, /** * Functions to be called on proxy request * with args [proxyReq, req, res, options] */ proxyReq: List([]), /** * Functions to be called on proxy response * with args [proxyRes, req, res] */ proxyRes: List([]), /** * Functions to be called on proxy response * with args [proxyReq, req, socket, options, head] */ proxyReqWs: List([]), errHandler: undefined, url: Map({}), proxyOptions: Map(defaultHttpProxyOptions), cookies: Map(defaultCookieOptions), ws: false, middleware: List([]), reqHeaders: undefined }); /** * @param {BrowserSync} bs * @param {String} scripts * @returns {*} */ module.exports = function createProxyServer(bs) { var opt = new ProxyOption().mergeDeep(bs.options.get("proxy")); var proxy = httpProxy.createProxyServer( opt .get("proxyOptions") .set("target", opt.get("target")) .toJS() ); var target = opt.get("target"); var proxyReq = getProxyReqFunctions(opt.get("proxyReq"), opt, bs); var proxyRes = getProxyResFunctions(opt.get("proxyRes"), opt); var proxyResWs = opt.get("proxyReqWs"); bs.options = bs.options.update("middleware", function(mw) { return mw.concat({ id: "Browsersync Proxy", route: opt.get("route"), handle: function(req, res) { proxy.web(req, res, { target: target }); } }); }); var app = utils.getBaseApp(bs); /** * @type {*|{server, app}} */ var browserSyncServer = utils.getServer(app, bs.options); browserSyncServer.proxy = proxy; if (opt.get("ws")) { // debug(`+ ws upgrade for: ${x.get("target")}`); browserSyncServer.server.on("upgrade", function(req, socket, head) { proxy.ws(req, socket, head); }); } /** * Add any user provided functions for proxyReq, proxyReqWs and proxyRes */ applyFns("proxyReq", proxyReq); applyFns("proxyRes", proxyRes); applyFns("proxyReqWs", proxyResWs); /** * Handle Proxy errors */ proxy.on("error", function(err) { if (typeof opt.get("errHandler") === "function") { opt.get("errHandler").call(null, err); } }); /** * Apply functions to proxy events * @param {string} name - the name of the http-proxy event * @param {Array} fns - functions to call on each event */ function applyFns(name, fns) { if (!List.isList(fns)) fns = [fns]; proxy.on(name, function() { var args = arguments; fns.forEach(function(fn) { if (typeof fn === "function") { fn.apply(null, args); } }); }); } return browserSyncServer; }; /** * @param resFns * @returns {*} */ function getProxyResFunctions(resFns, opt) { if (opt.getIn(["cookies", "stripDomain"])) { return resFns.push(proxyUtils.checkCookies); } return resFns; } /** * @param reqFns * @returns {*} */ function getProxyReqFunctions(reqFns, opt, bs) { var reqHeaders = opt.getIn(["reqHeaders"]); if (!reqHeaders) { return reqFns; } /** * Back-compat for old `reqHeaders` option here a * function was given that returned an object * where key:value was header-name:header-value * This didn't really work as it clobbered all other headers, * but it remains for the unlucky few who used it. */ if (typeof reqHeaders === "function") { var output = reqHeaders.call(bs, opt.toJS()); if (Object.keys(output).length) { return reqFns.concat(function(proxyReq) { Object.keys(output).forEach(function(key) { proxyReq.setHeader(key, output[key]); }); }); } } /** * Now, if {key:value} given, set the each header * * eg: reqHeaders: { * 'is-dev': 'true' * } */ if (Map.isMap(reqHeaders)) { return reqFns.concat(function(proxyReq) { reqHeaders.forEach(function(value, key) { proxyReq.setHeader(key, value); }); }); } return reqFns; } ================================================ FILE: packages/browser-sync/lib/server/proxy-utils.js ================================================ var url = require("url"); module.exports.rewriteLinks = function(userServer) { var host = userServer.hostname; var string = host; var port = userServer.port; if (host && port) { if (parseInt(port, 10) !== 80) { string = host + ":" + port; } } var reg = new RegExp( // a simple, but exact match "https?:\\\\/\\\\/" + string + "|" + // following ['"] + exact "('|\")\\/\\/" + string + "|" + // exact match with optional trailing slash "https?://" + string + "(?!:)(/)?" + "|" + // following ['"] + exact + possible multiple (imr srcset etc) "('|\")(https?://|/|\\.)?" + string + "(?!:)(/)?(.*?)(?=[ ,'\"\\s])", "g" ); return { match: reg, //match: new RegExp("https?:\\\\/\\\\/" + string + "|https?://" + string + "(\/)?|('|\")(https?://|/|\\.)?" + string + "(\/)?(.*?)(?=[ ,'\"\\s])", "g"), //match: new RegExp("https?:\\\\?/\\\\?/" + string + "(\/)?|('|\")(https?://|\\\\?/|\\.)?" + string + "(\/)?(.*?)(?=[ ,'\"\\s])", "g"), //match: new RegExp('https?://' + string + '(\/)?|(\'|")(https?://|/|\\.)?' + string + '(\/)?(.*?)(?=[ ,\'"\\s])', 'g'), //match: new RegExp("https?:\\\\/\\\\/" + string, "g"), fn: function(req, res, match) { var proxyUrl = req.headers["host"]; /** * Reject subdomains */ if (match[0] === ".") { return match; } var captured = match[0] === "'" || match[0] === '"' ? match[0] : ""; /** * allow http https * @type {string} */ var pre = "//"; if (match[0] === "'" || match[0] === '"') { match = match.slice(1); } /** * parse the url * @type {number|*} */ var out = url.parse(match); /** * If host not set, just do a simple replace */ if (!out.host) { string = string.replace(/^(\/)/, ""); return captured + match.replace(string, proxyUrl); } /** * Only add trailing slash if one was * present in the original match */ if (out.path === "/") { if (match.slice(-1) === "/") { out.path = "/"; } else { out.path = ""; } } /** * Finally append all of parsed url */ return [ captured, pre, proxyUrl, out.path || "", out.hash || "" ].join(""); } }; }; /** * Remove 'domain' from any cookies * @param {Object} res */ module.exports.checkCookies = function checkCookies(res) { if (typeof res.headers["set-cookie"] !== "undefined") { res.headers["set-cookie"] = res.headers["set-cookie"].map(function( item ) { return rewriteCookies(item); }); } }; /** * Remove the domain from any cookies. * @param rawCookie * @returns {string} */ function rewriteCookies(rawCookie) { var objCookie = (function() { // simple parse function (does not remove quotes) var obj = {}; var pairs = rawCookie.split(/; */); pairs.forEach(function(pair) { var eqIndex = pair.indexOf("="); // skip things that don't look like key=value if (eqIndex < 0) { return; } var key = pair.substr(0, eqIndex).trim(); obj[key] = pair.substr(eqIndex + 1, pair.length).trim(); }); return obj; })(); var pairs = Object.keys(objCookie) .filter(function(item) { return item.toLowerCase() !== "domain"; }) .map(function(key) { return key + "=" + objCookie[key]; }); if (rawCookie.match(/httponly/i)) { pairs.push("HttpOnly"); } return pairs.join("; "); } module.exports.rewriteCookies = rewriteCookies; ================================================ FILE: packages/browser-sync/lib/server/serve-static-wrapper.ts ================================================ export default function() { const serveStatic = require("serve-static"); /** * Adding a custom mime-type for wasm whilst we wait for * the `send` package to be updated. */ const send = require("send"); send.mime.define({ "application/wasm": ["wasm"] }); return serveStatic; } ================================================ FILE: packages/browser-sync/lib/server/snippet-server.js ================================================ "use strict"; var connect = require("connect"); var serverUtils = require("./utils.js"); /** * Create a server for the snippet * @param {BrowserSync} bs * @param scripts * @returns {*} */ module.exports = function createSnippetServer(bs, scripts) { var app = serverUtils.getBaseApp(bs, bs.options, scripts); return serverUtils.getServer(app, bs.options); }; ================================================ FILE: packages/browser-sync/lib/server/static-server.js ================================================ var serverUtils = require("./utils.js"); var resolve = require("path").resolve; var utils = require("../utils.js"); var serveStatic = require("./serve-static-wrapper").default(); var serveIndex = require("serve-index"); /** * @param {BrowserSync} bs * @returns {*} */ module.exports = function createServer(bs) { var options = bs.options; var server = options.get("server"); var basedirs = utils.arrayify(server.get("baseDir")); var serveStaticOptions = server.get("serveStaticOptions").toJS(); // passed to 3rd party var _serveStatic = 0; var _routes = 0; bs.options = bs.options /** * Add directory Middleware if given in server.directory */ .update("middleware", function(mw) { if (!server.get("directory")) { return mw; } return mw.concat({ route: "", handle: serveIndex(resolve(basedirs[0]), { icons: true, view: "details" }), id: "Browsersync Server Directory Middleware" }); }) /** * Add middleware for server.baseDir Option */ .update("middleware", function(mw) { return mw.concat( basedirs.map(function(root) { return { route: "", id: "Browsersync Server ServeStatic Middleware - " + _serveStatic++, handle: serveStatic(resolve(root), serveStaticOptions) }; }) ); }) /** * Add middleware for server.routes */ .update("middleware", function(mw) { if (!server.get("routes")) { return mw; } return mw.concat( server.get("routes").map(function(root, urlPath) { // strip trailing slash if (urlPath[urlPath.length - 1] === "/") { urlPath = urlPath.slice(0, -1); } return { route: urlPath, id: "Browsersync Server Routes Middleware - " + _routes++, handle: serveStatic(resolve(root)) }; }) ); }); var app = serverUtils.getBaseApp(bs); /** * Finally, return the server + App */ return serverUtils.getServer(app, bs.options); }; ================================================ FILE: packages/browser-sync/lib/server/utils.js ================================================ "use strict"; var fs = require("fs"); var path = require("path"); var join = require("path").join; var connect = require("connect"); var Immutable = require("immutable"); var http = require("http"); var https = require("https"); var Map = require("immutable").Map; var fromJS = require("immutable").fromJS; var List = require("immutable").List; var snippet = require("./../snippet").utils; var _ = require("../lodash.custom"); var serveStatic = require("./serve-static-wrapper").default(); var serveIndex = require("serve-index"); var logger = require("../logger"); var snippetUtils = require("../snippet").utils; var lrSnippet = require("resp-modifier"); var certPath = join(__dirname, "..", "..", "certs"); function getCa(options) { var caOption = options.getIn(["https", "ca"]); // if not provided, use Browsersync self-signed if (typeof caOption === "undefined") { return fs.readFileSync(join(certPath, "server.csr")); } // if a string was given, read that file from disk if (typeof caOption === "string") { return fs.readFileSync(caOption); } // if an array was given, read all if (List.isList(caOption)) { return caOption.toArray().map(function(x) { return fs.readFileSync(x); }); } } function getKey(options) { return fs.readFileSync( options.getIn(["https", "key"]) || join(certPath, "server.key") ); } function getCert(options) { return fs.readFileSync( options.getIn(["https", "cert"]) || join(certPath, "server.crt") ); } function getHttpsServerDefaults(options) { return fromJS({ key: getKey(options), cert: getCert(options), ca: getCa(options), passphrase: options.getIn(["https", "passphrase"], "") }); } function getPFXDefaults(options) { return fromJS({ pfx: fs.readFileSync(options.getIn(["https", "pfx"])) }); } var serverUtils = { /** * @param options * @returns {{key, cert}} */ getHttpsOptions: function(options) { var userOption = options.get("https"); if (Map.isMap(userOption)) { if (userOption.has("pfx")) { return userOption.mergeDeep(getPFXDefaults(options)); } return userOption.mergeDeep(getHttpsServerDefaults(options)); } return getHttpsServerDefaults(options); }, /** * Get either http or https server * or use the httpModule provided in options if present */ getServer: function(app, options) { return { server: (function() { var httpModule = serverUtils.getHttpModule(options); if ( options.get("scheme") === "https" || options.get("httpModule") === "http2" ) { var opts = serverUtils.getHttpsOptions(options); return httpModule.createServer(opts.toJS(), app); } return httpModule.createServer(app); })(), app: app }; }, getHttpModule: function(options) { /** * Users may provide a string to be used by nodes * require lookup. */ var httpModule = options.get("httpModule"); if (typeof httpModule === "string") { /** * Note, this could throw, but let that happen as * the error message good enough. */ var maybe = require.resolve(httpModule); return require(maybe); } if (options.get("scheme") === "https") { return https; } return http; }, getMiddlewares: function(bs) { var clientJs = bs.pluginManager.hook("client:js", { port: bs.options.get("port"), options: bs.options }); var scripts = bs.pluginManager.get("client:script")( bs.options.toJS(), clientJs, "middleware" ); var defaultMiddlewares = [ { id: "Browsersync HTTP Protocol", route: require("../config").httpProtocol.path, handle: require("../http-protocol").middleware(bs) }, { id: "Browsersync IE8 Support", route: "", handle: snippet.isOldIe( bs.options.get("excludedFileTypes").toJS() ) }, { id: "Browsersync Response Modifier", route: "", handle: serverUtils.getSnippetMiddleware(bs) }, { id: "Browsersync Client - versioned", route: bs.options.getIn(["scriptPaths", "versioned"]), handle: scripts }, { id: "Browsersync Client", route: bs.options.getIn(["scriptPaths", "path"]), handle: scripts } ]; /** * Add cors middleware to the front of the stack * if a user provided a 'cors' flag */ if (bs.options.get("cors")) { defaultMiddlewares.unshift({ id: "Browsersync CORS support", route: "", handle: serverUtils.getCorsMiddlewware() }); } /** * Add connect-history-api-fallback if 'single' argument given */ if (bs.options.get("single")) { defaultMiddlewares.unshift({ id: "Browsersync SPA support", route: "", handle: require("connect-history-api-fallback")() }); } /** * Add serve static middleware */ if (bs.options.get("serveStatic")) { var ssMiddlewares = serverUtils.getServeStaticMiddlewares( bs.options.get("serveStatic"), bs.options.get("serveStaticOptions", Immutable.Map({})).toJS() ); var withErrors = ssMiddlewares.filter(function(x) { return x.get("errors").size > 0; }); var withoutErrors = ssMiddlewares.filter(function(x) { return x.get("errors").size === 0; }); if (withErrors.size) { withErrors.forEach(function(item) { logger.logger.error( "%s %s", chalk.red("Warning!"), item.getIn(["errors", 0, "data", "message"]) ); }); } if (withoutErrors.size) { withoutErrors.forEach(function(item) { defaultMiddlewares.push.apply( defaultMiddlewares, item.get("items").toJS() ); }); } } /** * Add user-provided middlewares */ var userMiddlewares = bs.options .get("middleware") .map(normaliseMiddleware) .toArray(); var beforeMiddlewares = userMiddlewares.filter(function(x) { return x.override; }); var afterMiddlewares = userMiddlewares .filter(function(x) { return !x.override; }) .concat( bs.options.get("mode") !== "proxy" && userMiddlewares.length === 0 && { id: "Browsersync 404/index support", route: "", handle: serveIndex(bs.options.get("cwd"), { icons: true, view: "details" }) } ); const mwStack = [] .concat(beforeMiddlewares, defaultMiddlewares, afterMiddlewares) .filter(Boolean); return mwStack; function normaliseMiddleware(item) { /** * Object given in options, which * ended up being a Map */ if (Map.isMap(item)) { return item.toJS(); } /** * Single function */ if (typeof item === "function") { return { route: "", handle: item }; } /** * Plain obj */ if (item.route !== undefined && item.handle) { return item; } } }, getBaseApp: function(bs) { var app = connect(); var middlewares = serverUtils.getMiddlewares(bs); /** * Add all internal middlewares */ middlewares.forEach(function(item) { app.stack.push(item); }); return app; }, getSnippetMiddleware: function(bs) { var rules = []; var blacklist = List([]) .concat(bs.options.getIn(["snippetOptions", "ignorePaths"])) .concat(bs.options.getIn(["snippetOptions", "blacklist"])) .filter(Boolean); var whitelist = List([]).concat( bs.options.getIn(["snippetOptions", "whitelist"]) ); // Snippet if (bs.options.get("snippet")) { rules.push( snippetUtils.getRegex( bs.options.get("snippet"), bs.options.get("snippetOptions") ) ); } // User bs.options.get("rewriteRules").forEach(function(rule) { if (Map.isMap(rule)) { rules.push(rule.toJS()); } if (_.isPlainObject(rule)) { rules.push(rule); } }); // Proxy if (bs.options.get("proxy")) { var proxyRule = require("./proxy-utils").rewriteLinks( bs.options.getIn(["proxy", "url"]).toJS() ); rules.push(proxyRule); } var lr = lrSnippet.create({ rules: rules, blacklist: blacklist.toArray(), whitelist: whitelist.toArray() }); return lr.middleware; }, getCorsMiddlewware: function() { return function(req, res, next) { // Website you wish to allow to connect res.setHeader("Access-Control-Allow-Origin", "*"); // Request methods you wish to allow res.setHeader( "Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE" ); // Request headers you wish to allow res.setHeader( "Access-Control-Allow-Headers", "X-Requested-With,content-type" ); // Set to true if you need the website to include cookies in the requests sent // to the API (e.g. in case you use sessions) res.setHeader("Access-Control-Allow-Credentials", true); next(); }; }, /** * @param ssOption * @param serveStaticOptions * @returns {*} */ getServeStaticMiddlewares: function(ssOption, serveStaticOptions) { return ssOption.map(function(dir, i) { /** * When a user gives a plain string only, eg: * serveStatic: ['./temp'] * -> * This means a middleware will be created with * route: '' * handle: serveStatic('./temp', options) */ if (_.isString(dir)) { return getFromString(dir); } /** * If a user gave an object eg: * serveStatic: [{route: "", dir: ["test", "./tmp"]}] * -> * This means we need to create a middle for each route + dir combo */ if (Immutable.Map.isMap(dir)) { return getFromMap(dir, i); } /** * At this point, an item in the serveStatic array was not a string * or an object so we return an error that can be logged */ return fromJS({ items: [], errors: [ { type: "Invalid Type", data: { message: "Only strings and Objects (with route+dir) are supported for the ServeStatic option" } } ] }); }); /** * @param {string} x * @returns {string} */ function getRoute(x) { if (x === "") return ""; return x[0] === "/" ? x : "/" + x; } /** * @param dir * @returns {Map} */ function getFromString(dir) { return fromJS({ items: [ { route: "", handle: serveStatic(dir, serveStaticOptions) } ], errors: [] }); } /** * @param dir * @returns {Map} */ function getFromMap(dir) { var ssOptions = (function() { if (dir.get("options")) { return dir.get("options").toJS(); } return {}; })(); var route = Immutable.List([]) .concat(dir.get("route")) .filter(_.isString); var _dir = Immutable.List([]) .concat(dir.get("dir")) .filter(_.isString); if (_dir.size === 0) { return fromJS({ items: [], errors: [ { type: "Invalid Object", data: { message: "Serve Static requires a 'dir' property when using an Object" } } ] }); } var ssItems = (function() { /** * iterate over every 'route' item * @type {Immutable.List|Immutable.List<*>|Immutable.List|*} */ var routeItems = (function() { /** * If no 'route' was given, assume we want to match all * paths */ if (route.size === 0) { return _dir.map(function(dirString) { return Map({ route: "", dir: dirString }); }); } return route.reduce(function(acc, routeString) { /** * For each 'route' item, also iterate through 'dirs' * @type {Immutable.Iterable} */ var perDir = _dir.map(function(dirString) { return Map({ route: getRoute(routeString), dir: dirString }); }); return acc.concat(perDir); }, List([])); })(); /** * Now create a serverStatic Middleware for each item */ return routeItems.map(function(routeItem) { return routeItem.merge({ handle: serveStatic(routeItem.get("dir"), ssOptions) }); }); })(); return fromJS({ items: ssItems, errors: [] }); } } }; module.exports = serverUtils; ================================================ FILE: packages/browser-sync/lib/snippet.js ================================================ "use strict"; var connectUtils = require("./connect-utils"); var config = require("./config"); var lrSnippet = require("resp-modifier"); var path = require("path"); var _ = require("./lodash.custom"); var utils = require("./utils"); var fs = require("fs"); var path = require("path"); /** * Utils for snippet injection */ var snippetUtils = { /** * @param {String} url * @param {Array} excludeList * @returns {boolean} */ isExcluded: function(url, excludeList) { var extension = path.extname(url); if (extension) { if (~url.indexOf("?")) { return true; } extension = extension.slice(1); return _.includes(excludeList, extension); } return false; }, /** * @param {String} snippet * @param {Object} options * @returns {{match: RegExp, fn: Function}} */ getRegex: function(snippet, options) { var fn = options.getIn(["rule", "fn"]); return { match: options.getIn(["rule", "match"]), fn: function(req, res, match) { return fn.apply(null, [snippet, match]); }, once: true, id: "bs-snippet" }; }, getSnippetMiddleware: function(snippet, options, rewriteRules) { return lrSnippet.create( snippetUtils.getRules(snippet, options, rewriteRules) ); }, getRules: function(snippet, options, rewriteRules) { var rules = [snippetUtils.getRegex(snippet, options)]; if (rewriteRules) { rules = rules.concat(rewriteRules); } return { rules: rules, blacklist: utils.arrayify(options.get("blacklist")), whitelist: utils.arrayify(options.get("whitelist")) }; }, /** * @param {Object} req * @param {Array} [excludeList] * @returns {Object} */ isOldIe: function(excludeList) { return function(req, res, next) { var ua = req.headers["user-agent"]; var match = /MSIE (\d)\.\d/.exec(ua); if (match) { if (parseInt(match[1], 10) < 9) { if (!snippetUtils.isExcluded(req.url, excludeList)) { req.headers["accept"] = "text/html"; } } } next(); }; }, /** * @param {Number} port * @param {BrowserSync.options} options * @returns {String} */ getClientJs: function(port, options) { return () => { const script = options.get("minify") ? "index.js" : "index.js"; const client = fs.readFileSync( require.resolve("browser-sync-client/dist/" + script), "utf8" ); return [connectUtils.socketConnector(options), client].join(";\n"); }; } }; module.exports.utils = snippetUtils; ================================================ FILE: packages/browser-sync/lib/sockets.ts ================================================ import {Server} from "socket.io"; import * as utils from "./server/utils"; /** * Plugin interface * @returns {*|function(this:exports)} */ export function plugin(server, clientEvents, bs) { return exports.init(server, clientEvents, bs); } /** * @param {http.Server} server * @param clientEvents * @param {BrowserSync} bs */ export function init(server, clientEvents, bs) { var emitter = bs.events; var socketConfig = bs.options.get("socket").toJS(); if ( bs.options.get("mode") === "proxy" && bs.options.getIn(["proxy", "ws"]) ) { server = utils.getServer(null, bs.options).server; server.listen(bs.options.getIn(["socket", "port"])); bs.registerCleanupTask(function() { server.close(); }); } var socketIoConfig = socketConfig.socketIoOptions; socketIoConfig.path = socketConfig.path; const io = new Server(); io.attach(server, { ...socketIoConfig, pingTimeout: socketConfig.clients.heartbeatTimeout, cors: { credentials: true, "origin": (origin, cb) => { return cb(null, origin) }, } }); io.of(socketConfig.namespace).on('connection', (socket) => { handleConnection(socket); }); /** * Handle each new connection * @param {Object} client */ function handleConnection(client) { // set ghostmode callbacks if (bs.options.get("ghostMode")) { addGhostMode(client); } client.emit("connection", bs.options.toJS()); //todo - trim the amount of options sent to clients emitter.emit("client:connected", { ua: client.handshake.headers["user-agent"] }); } /** * @param client */ function addGhostMode(client) { clientEvents.forEach(addEvent); function addEvent(event) { client.on(event, data => { client.broadcast.emit(event, data); }); } } // @ts-ignore io.sockets = io.of(socketConfig.namespace) return io; } ================================================ FILE: packages/browser-sync/lib/tunnel.js ================================================ "use strict"; var _ = require("./lodash.custom"); var utils = require("util"); /** * @param {BrowserSync} bs * @param {Function} cb */ module.exports = function(bs, cb) { var localtunnel; try { localtunnel = require("localtunnel"); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { var error = new Error("Could not find package `localtunnel`. From Browsersync version 3.0 you'll need to install this manually."); error.code = e.code; return cb(error); } return cb(e); } var opts = {}; var options = bs.options; var port = options.get("port"); if (_.isString(options.get("tunnel"))) { opts.subdomain = options.get("tunnel"); } bs.debug("Requesting a tunnel connection on port: {magenta:%s}", port); bs.debug( "Requesting a tunnel connection with options: {magenta:%s}", utils.inspect(opts) ); localtunnel(port, opts, function(err, tunnel) { if (err) { return cb(err); } tunnel.on("error", function(err) { bs.logger.info("Localtunnel issue: " + err.message); bs.logger.info( "Oops! The localtunnel appears to have disconnected. Reconnecting..." ); }); return cb(null, tunnel); }); }; ================================================ FILE: packages/browser-sync/lib/types.ts ================================================ import * as url from "url"; import { Map } from "immutable"; export type ServerIncoming = string | string[] | IServerOption; export interface IServerOption { baseDir: string[]; index?: string; directory?: boolean; serveStaticOptions?: any; routes?: { [route: string]: string }; middleware?: MiddlewareInput; } export type MiddlewareInput = Function | Function[] | Middleware | Middleware[]; export interface Middleware { route: string; id?: string; handle: Function; } export type BrowsersyncProxyIncoming = string | BrowsersyncProxy; export interface BrowsersyncProxy { target: string; url: Map; middleware?: MiddlewareInput; } export type PortsOption = { min: number | null; max: number | null; }; export type FilesObject = { match: string[]; fn?: Function; options?: any }; export type FilesNamespace = { globs: string[]; objs: FilesObject[] }; export type FilesNamespaces = { [name: string]: FilesNamespace }; ================================================ FILE: packages/browser-sync/lib/utils.ts ================================================ import { BsTempOptions } from "./cli/cli-options"; import * as devIp from "dev-ip"; import * as portScanner from "portscanner"; import * as path from "path"; import * as UAParser from "ua-parser-js"; import * as Immutable from "immutable"; import { List } from "immutable"; const _ = require("./lodash.custom"); const parser = new UAParser(); /** * @param {Object} options * @returns {String|boolean} - the IP address * @param devIp */ export function getHostIp(options: BsTempOptions, devIp: string[]) { if (options) { var host = options.get("host"); if (host && host !== "localhost") { return host; } if (options.get("detect") === false || !devIp.length) { return false; } } return devIp.length ? devIp[0] : false; } /** * Set URL Options */ export function getUrlOptions(options: BsTempOptions): Map { const scheme = options.get("scheme"); const port = options.get("port"); const urls: { [index: string]: string } = {}; const listen = options.get("listen"); if (options.get("online") === false || listen) { const host = listen || "localhost"; urls.local = getUrl(`${scheme}://${host}:${port}`, options); return Immutable.fromJS(urls); } const fn: typeof getHostIp = exports.getHostIp; const external = hostnameSuffix(fn(options, devIp()), options); const localhost = hostnameSuffix("localhost", options); return Immutable.fromJS(getUrls(external, localhost, scheme, options)); } /** * Append a start path if given in options * @param {String} url * @param {Object} options * @returns {String} */ export function getUrl(url: string, options: BsTempOptions) { var prefix = "/"; var startPath = options.get("startPath"); if (startPath) { if (startPath.charAt(0) === "/") { prefix = ""; } url = url + prefix + startPath; } return url; } /** * @param {String} external * @param {String} local * @param {String} scheme * @param {Object} options * @returns {{local: string, external: string}} */ export function getUrls(external, local, scheme, options) { var urls: { [index: string]: string } = { local: getUrl(_makeUrl(scheme, local, options.get("port")), options) }; if (external !== local) { urls.external = getUrl( _makeUrl(scheme, external, options.get("port")), options ); } return urls; } /** * @param {String} scheme * @param {String} host * @param {Number} port * @returns {String} * @private */ export function _makeUrl(scheme, host, port) { return scheme + "://" + host + ":" + port; } export type PortLookupCb = (error: null | Error, port: number) => void; /** * Get ports * @param {Object} options * @param {Function} cb */ export function getPorts(options: BsTempOptions, cb: PortLookupCb) { var port = options.get("port"); var ports = options.get("ports"); // backwards compatibility var host = options.get("listen", "localhost"); // backwards compatibility var max; if (ports) { port = ports.get("min"); max = ports.get("max") || null; } var fn: typeof getPort = exports.getPort; fn(host, port, max, cb); } export function getPort( host: string, port: number | string, max: number | string | null, cb: PortLookupCb ) { portScanner.findAPortNotInUse( port, max, { host: host, timeout: 1000 }, cb ); } /** * @param {String} ua * @returns {Object} */ export function getUaString(ua) { return parser.setUA(ua).getBrowser(); } /** * Open the page in browser * @param {String} url * @param {Object} options * @param {BrowserSync} bs */ export function openBrowser(url, options, bs) { const open = options.get("open"); const browser = options.get("browser"); if (_.isString(open)) { if (options.getIn(["urls", open])) { url = options.getIn(["urls", open]); } } const fn: typeof opnWrapper = exports.opnWrapper; if (open) { if (browser !== "default") { if (isList(browser)) { browser.forEach(function(browser) { fn(url, browser, bs); }); } else { fn(url, browser, bs); // single } } else { fn(url, null, bs); } } } /** * Wrapper for opn module * @param url * @param name * @param bs */ export function opnWrapper(url, name, bs) { var options = (function() { if (_.isString(name)) { return { app: name }; } if (Immutable.Map.isMap(name)) { return name.toJS(); } return {}; })(); var opn = require("opn"); opn(url, options).catch(function() { bs.events.emit("browser:error"); }); } /** * @param {Boolean} kill * @param {String|Error} [errMessage] * @param {Function} [cb] */ export function fail(kill, errMessage, cb) { if (kill) { if (_.isFunction(cb)) { if (errMessage.message) { // Is this an error object? cb(errMessage); } else { cb(new Error(errMessage)); } } process.exit(1); } } /** * hostnameSuffix * @param {String} host * @param {Object} options * @returns {String} */ export function hostnameSuffix(host, options) { var suffix = options.get("hostnameSuffix"); if (suffix) { return host + suffix; } return host; } /** * Determine if an array of file paths will cause a full page reload. * @param {Array} needles - filepath such as ["core.css", "index.html"] * @param {Array} haystack * @returns {Boolean} */ export function willCauseReload(needles, haystack) { return needles.some(function(needle) { return !_.includes(haystack, path.extname(needle).replace(".", "")); }); } export const isList = Immutable.List.isList; export const isMap = Immutable.Map.isMap; /** * @param {Map} options * @returns {Array} */ export function getConfigErrors(options) { var messages = require("./config").errors; var errors = []; if (options.get("server") && options.get("proxy")) { errors.push(messages["server+proxy"]); } return errors; } /** * @param {Map} options * @param {Function} [cb] */ export function verifyConfig(options, cb) { var errors = getConfigErrors(options); if (errors.length) { fail(true, errors.join("\n"), cb); return false; } return true; } export function eachSeries(arr, iterator, callback) { callback = callback || function() {}; var completed = 0; var iterate = function() { iterator(arr[completed], function(err) { if (err) { callback(err); callback = function() {}; } else { ++completed; if (completed >= arr.length) { callback(); } else { iterate(); } } }); }; iterate(); } /** * @param {Immutable.List|Array|String} incoming * @returns {Array} */ export function arrayify(incoming) { if (List.isList(incoming)) { return incoming.toArray(); } return [].concat(incoming).filter(Boolean); } export function defaultCallback(err?: Error) { if (err && err.message) { console.error(err.message); } } export const portscanner = portScanner; export const connect = require("connect"); export const serveStatic = require("./server/serve-static-wrapper").default(); export const easyExtender = require("easy-extender"); export { UAParser, devIp }; /** * Just for backwards compat around old argument styles */ export function parseParams(search: string): Record { const params = new URLSearchParams(search); const parsed = Object.create(null); for (let [key, value] of params) { let nextKey = key; let arrayType = false; if (nextKey.slice(-2) === "[]") { nextKey = key.slice(0, -2); arrayType = true; } const curr = parsed[nextKey]; if (curr && Array.isArray(curr)) { curr.push(value); } else if (curr) { // if it already exists, but is not already an array, upgrade to array parsed[nextKey] = [curr, value]; } else { // otherwise create the original value if (arrayType) { parsed[nextKey] = [value]; } else { parsed[nextKey] = value; } } } return parsed; } /** * Also for backwards compat around old argument styles */ export function serializeParams(args: Record = {}): URLSearchParams { const output = new URLSearchParams(); for (let [key, value] of Object.entries(args)) { if (Array.isArray(value)) { for (let valueElement of value) { output.append(key, valueElement); } } else { output.append(key, String(value)); } } return output; } ================================================ FILE: packages/browser-sync/package.json ================================================ { "name": "browser-sync", "description": "Live CSS Reload & Browser Syncing", "version": "3.0.4", "homepage": "https://browsersync.io/", "author": { "name": "Shane Osbourne" }, "repository": "BrowserSync/browser-sync", "license": "Apache-2.0", "main": "dist/index.js", "bin": "dist/bin.js", "files": [ "dist", "certs", "templates", "cli-options", "client/dist" ], "engines": { "node": ">= 8.0.0" }, "scripts": { "build": "npm run build:server", "build:server": "tsc", "build:watch": "tsc --watch", "env": "node ./test/env.js", "lodash": "lodash include=isUndefined,isFunction,toArray,includes,union,each,isString,merge,isObject,set exports=node", "prepublishOnly": "npm run build", "prettier": "prettier 'lib/**/*' 'examples/*' 'test/specs/**/*.js' --tab-width 4", "prettier:fix": "npm run prettier -- --write", "test": "npm run build && npm run env && npm run unit", "unit": "mocha --recursive test/specs --timeout 10000 --bail --exit", "watch": "npm run build && npm run serve:fixtures", "serve:fixtures": "node dist/bin test/fixtures -w --no-open" }, "dependencies": { "browser-sync-client": "^3.0.4", "browser-sync-ui": "^3.0.4", "bs-recipes": "1.3.4", "chalk": "4.1.2", "chokidar": "^3.5.1", "connect": "3.6.6", "connect-history-api-fallback": "^1", "dev-ip": "^1.0.1", "easy-extender": "^2.3.4", "eazy-logger": "^4.1.0", "etag": "^1.8.1", "fresh": "^0.5.2", "fs-extra": "3.0.1", "http-proxy": "^1.18.1", "immutable": "^3", "micromatch": "^4.0.8", "opn": "5.3.0", "portscanner": "2.2.0", "raw-body": "^2.3.2", "resp-modifier": "6.0.2", "rx": "4.1.0", "send": "^0.19.0", "serve-index": "^1.9.1", "serve-static": "^1.16.2", "server-destroy": "1.0.1", "socket.io": "^4.4.1", "ua-parser-js": "^1.0.33", "yargs": "^17.3.1" }, "devDependencies": { "@types/node": "^8", "bs-snippet-injector": "^2.0.1", "chai": "^3", "generate-changelog": "^1.7.0", "graceful-fs": "4.1.9", "http2": "^3.3.6", "mocha": "^10.2.0", "prettier": "^1.9.2", "q": "1.4.1", "request": "^2", "requirejs": "^2.3.5", "rimraf": "2.5.4", "sinon": "^1", "socket.io-client": "^2.4.0", "source-map-support": "^0.5.0", "strip-ansi": "^6.0.1", "supertest": "^3", "typescript": "^4.6.2", "vinyl": "1.2.0" }, "keywords": [ "browser sync", "css", "live reload", "sync" ] } ================================================ FILE: packages/browser-sync/readme.md ================================================

Keep multiple browsers & devices in sync when building websites.

Follow @Browsersync on twitter for news & updates.

## Features Please visit [browsersync.io](https://browsersync.io) for a full run-down of features ## Requirements Browsersync works by injecting an asynchronous script tag (``) right after the `` tag during initial request. In order for this to work properly the `` tag must be present. Alternatively you can provide a custom rule for the snippet using [snippetOptions](https://www.browsersync.io/docs/options/#option-snippetOptions) ## Upgrading from 1.x to 2.x ? Providing you haven't accessed any internal properties, everything will just work as there are no breaking changes to the public API. Internally however, we now use an immutable data structure for storing/retrieving options. So whereas before you could access urls like this... ```js browserSync({server: true}, function(err, bs) { console.log(bs.options.urls.local); }); ``` ... you now access them in the following way: ```js browserSync({server: true}, function(err, bs) { console.log(bs.options.getIn(["urls", "local"])); }); ``` ## Install and trouble shooting [browsersync.io docs](https://browsersync.io) ## Integrations / recipes [Browsersync recipes](https://github.com/Browsersync/recipes) ## Support If you've found Browser-sync useful and would like to contribute to its continued development & support, please feel free to send a donation of any size - it would be greatly appreciated! [Support via PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=shakyshane%40gmail%2ecom&lc=US&item_name=browser%2dsync) ## Supported by Originally supported by [JH](https://www.wearejh.com) - they provided financial support as well as access to a professional designer to help with Branding. Apache 2 Copyright (c) 2021 Shane Osbourne ================================================ FILE: packages/browser-sync/templates/cli-template.js ================================================ /* |-------------------------------------------------------------------------- | Browser-sync config file |-------------------------------------------------------------------------- | | For up-to-date information about the options: | http://www.browsersync.io/docs/options/ | | There are more options than you see here, these are just the ones that are | set internally. See the website for more info. | | */ module.exports = //OPTS; ================================================ FILE: packages/browser-sync/templates/connector.tmpl ================================================ window.___browserSync___ = {}; ___browserSync___.socketConfig = %config%; ___browserSync___.socketUrl = %url%; ___browserSync___.options = %options%; if (location.protocol == "https:" && /^http:/.test(___browserSync___.socketUrl)) { ___browserSync___.socketUrl = ___browserSync___.socketUrl.replace(/^http:/, "https:"); } ================================================ FILE: packages/browser-sync/templates/script-tags-simple.html ================================================ ================================================ FILE: packages/browser-sync/templates/script-tags.html ================================================ ================================================ FILE: packages/browser-sync/test/env.js ================================================ process.env.TESTING = true; ================================================ FILE: packages/browser-sync/test/fixtures/.tmp/temp.css ================================================ body { background: red; } ================================================ FILE: packages/browser-sync/test/fixtures/alt/index.htm ================================================ Test HTML Page

Hello from the test

Forms Scrolling Window
================================================ FILE: packages/browser-sync/test/fixtures/assets/import.css ================================================ @import "import2.css"; body { color: orange; } ================================================ FILE: packages/browser-sync/test/fixtures/assets/import2.css ================================================ body { background: red; } ================================================ FILE: packages/browser-sync/test/fixtures/assets/print.css ================================================ body { background: #322323; } .container { margin: 0 auto; width: 320px; } ================================================ FILE: packages/browser-sync/test/fixtures/assets/style.css ================================================ body { background: white; } .container { margin: 0 auto; width: 320px; } ================================================ FILE: packages/browser-sync/test/fixtures/base.html ================================================ Forms

Browsersync Ghost Mode: Form sync

Links: synced

Hompage

Radio Buttons: synced

Check Boxes: synced

================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/css/bootstrap-grid.css ================================================ /*! * Bootstrap Grid v4.0.0-beta.3 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors * Copyright 2011-2017 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @-ms-viewport { width: device-width; } html { box-sizing: border-box; -ms-overflow-style: scrollbar; } *, *::before, *::after { box-sizing: inherit; } .container { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container { max-width: 540px; } } @media (min-width: 768px) { .container { max-width: 720px; } } @media (min-width: 992px) { .container { max-width: 960px; } } @media (min-width: 1200px) { .container { max-width: 1140px; } } .container-fluid { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-sm-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-sm-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-sm-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-sm-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-sm-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-sm-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-sm-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-sm-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-sm-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-sm-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-sm-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-sm-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-sm-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-sm-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-md-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-md-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-md-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-md-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-md-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-md-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-md-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-md-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-md-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-md-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-md-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-md-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-md-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-md-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-lg-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-lg-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-lg-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-lg-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-lg-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-lg-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-lg-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-lg-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-lg-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-lg-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-lg-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-lg-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-lg-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-lg-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-xl-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-xl-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-xl-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-xl-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-xl-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-xl-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-xl-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-xl-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-xl-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-xl-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-xl-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-xl-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-xl-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-xl-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .flex-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-sm-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-md-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-lg-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-xl-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } /*# sourceMappingURL=bootstrap-grid.css.map */ ================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/css/bootstrap-reboot.css ================================================ /*! * Bootstrap Reboot v4.0.0-beta.3 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors * Copyright 2011-2017 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */ *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: transparent; } @-ms-viewport { width: device-width; } article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus { outline: 0 !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } dfn { font-style: italic; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } a:hover { color: #0056b3; text-decoration: underline; } a:not([href]):not([tabindex]) { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus { outline: 0; } pre, code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg:not(:root) { overflow: hidden; } a, area, button, [role="button"], input:not([type="range"]), label, select, summary, textarea { -ms-touch-action: manipulation; touch-action: manipulation; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #868e96; text-align: left; caption-side: bottom; } th { text-align: inherit; } label { display: inline-block; margin-bottom: .5rem; } button { border-radius: 0; } button:focus { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] { -webkit-appearance: listbox; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; cursor: pointer; } template { display: none; } [hidden] { display: none !important; } /*# sourceMappingURL=bootstrap-reboot.css.map */ ================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/css/bootstrap.css ================================================ /*! * Bootstrap v4.0.0-beta.3 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors * Copyright 2011-2017 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ :root { --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: #fd7e14; --yellow: #ffc107; --green: #28a745; --teal: #20c997; --cyan: #17a2b8; --white: #fff; --gray: #868e96; --gray-dark: #343a40; --primary: #007bff;s --secondarsy: #868e96; --success: #28a745; --info: #17a2b8; --warning: #ffc107; --danger: #dc3545; --light: #f8f9fa; --dask: #343a40; --breakpoint-xs: 0; --breakpoint-sm: 576px; --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: transparent; } @-ms-viewport { width: device-width; } article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus { outline: 0 !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } dfn { font-style: italic; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } a:hover { color: #0056b3; text-decoration: underline; } a:not([href]):not([tabindex]) { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover { color: inherit; text-decoration: none; } a:not([href]):not([tabindex]):focus { outline: 0; } pre, code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg:not(:root) { overflow: hidden; } a, area, button, [role="button"], input:not([type="range"]), label, select, summary, textarea { -ms-touch-action: manipulation; touch-action: manipulation; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #868e96; text-align: left; caption-side: bottom; } th { text-align: inherit; } label { display: inline-block; margin-bottom: .5rem; } button { border-radius: 0; } button:focus { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } button, html [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] { -webkit-appearance: listbox; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; cursor: pointer; } template { display: none; } [hidden] { display: none !important; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; font-family: inherit; font-weight: 500; line-height: 1.2; color: inherit; } h1, .h1 { font-size: 2.5rem; } h2, .h2 { font-size: 2rem; } h3, .h3 { font-size: 1.75rem; } h4, .h4 { font-size: 1.5rem; } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: 6rem; font-weight: 300; line-height: 1.2; } .display-2 { font-size: 5.5rem; font-weight: 300; line-height: 1.2; } .display-3 { font-size: 4.5rem; font-weight: 300; line-height: 1.2; } .display-4 { font-size: 3.5rem; font-weight: 300; line-height: 1.2; } hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } small, .small { font-size: 80%; font-weight: 400; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 90%; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote-footer { display: block; font-size: 80%; color: #868e96; } .blockquote-footer::before { content: "\2014 \00A0"; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.25rem; max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 90%; color: #868e96; } code, kbd, pre, samp { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } code { font-size: 87.5%; color: #e83e8c; word-break: break-word; } a > code { color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 87.5%; color: #fff; background-color: #212529; border-radius: 0.2rem; } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; } pre { display: block; font-size: 87.5%; color: #212529; } pre code { font-size: inherit; color: inherit; word-break: normal; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container { max-width: 540px; } } @media (min-width: 768px) { .container { max-width: 720px; } } @media (min-width: 992px) { .container { max-width: 960px; } } @media (min-width: 1200px) { .container { max-width: 1140px; } } .container-fluid { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-sm-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-sm-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-sm-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-sm-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-sm-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-sm-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-sm-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-sm-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-sm-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-sm-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-sm-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-sm-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-sm-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-sm-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-md-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-md-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-md-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-md-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-md-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-md-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-md-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-md-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-md-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-md-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-md-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-md-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-md-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-md-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-lg-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-lg-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-lg-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-lg-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-lg-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-lg-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-lg-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-lg-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-lg-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-lg-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-lg-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-lg-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-lg-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-lg-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .col-xl-auto { -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: none; } .col-xl-1 { -webkit-box-flex: 0; -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -webkit-box-flex: 0; -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -webkit-box-flex: 0; -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -webkit-box-flex: 0; -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -webkit-box-flex: 0; -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -webkit-box-flex: 0; -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -webkit-box-flex: 0; -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -webkit-box-ordinal-group: 0; -ms-flex-order: -1; order: -1; } .order-xl-1 { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; } .order-xl-2 { -webkit-box-ordinal-group: 3; -ms-flex-order: 2; order: 2; } .order-xl-3 { -webkit-box-ordinal-group: 4; -ms-flex-order: 3; order: 3; } .order-xl-4 { -webkit-box-ordinal-group: 5; -ms-flex-order: 4; order: 4; } .order-xl-5 { -webkit-box-ordinal-group: 6; -ms-flex-order: 5; order: 5; } .order-xl-6 { -webkit-box-ordinal-group: 7; -ms-flex-order: 6; order: 6; } .order-xl-7 { -webkit-box-ordinal-group: 8; -ms-flex-order: 7; order: 7; } .order-xl-8 { -webkit-box-ordinal-group: 9; -ms-flex-order: 8; order: 8; } .order-xl-9 { -webkit-box-ordinal-group: 10; -ms-flex-order: 9; order: 9; } .order-xl-10 { -webkit-box-ordinal-group: 11; -ms-flex-order: 10; order: 10; } .order-xl-11 { -webkit-box-ordinal-group: 12; -ms-flex-order: 11; order: 11; } .order-xl-12 { -webkit-box-ordinal-group: 13; -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .table { width: 100%; max-width: 100%; margin-bottom: 1rem; background-color: transparent; } .table th, .table td { padding: 0.75rem; vertical-align: top; border-top: 1px solid #dee2e6; } .table thead th { vertical-align: bottom; border-bottom: 2px solid #dee2e6; } .table tbody + tbody { border-top: 2px solid #dee2e6; } .table .table { background-color: #fff; } .table-sm th, .table-sm td { padding: 0.3rem; } .table-bordered { border: 1px solid #dee2e6; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6; } .table-bordered thead th, .table-bordered thead td { border-bottom-width: 2px; } .table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0, 0, 0, 0.05); } .table-hover tbody tr:hover { background-color: rgba(0, 0, 0, 0.075); } .table-primary, .table-primary > th, .table-primary > td { background-color: #b8daff; } .table-hover .table-primary:hover { background-color: #9fcdff; } .table-hover .table-primary:hover > td, .table-hover .table-primary:hover > th { background-color: #9fcdff; } .table-secondary, .table-secondary > th, .table-secondary > td { background-color: #dddfe2; } .table-hover .table-secondary:hover { background-color: #cfd2d6; } .table-hover .table-secondary:hover > td, .table-hover .table-secondary:hover > th { background-color: #cfd2d6; } .table-success, .table-success > th, .table-success > td { background-color: #c3e6cb; } .table-hover .table-success:hover { background-color: #b1dfbb; } .table-hover .table-success:hover > td, .table-hover .table-success:hover > th { background-color: #b1dfbb; } .table-info, .table-info > th, .table-info > td { background-color: #bee5eb; } .table-hover .table-info:hover { background-color: #abdde5; } .table-hover .table-info:hover > td, .table-hover .table-info:hover > th { background-color: #abdde5; } .table-warning, .table-warning > th, .table-warning > td { background-color: #ffeeba; } .table-hover .table-warning:hover { background-color: #ffe8a1; } .table-hover .table-warning:hover > td, .table-hover .table-warning:hover > th { background-color: #ffe8a1; } .table-danger, .table-danger > th, .table-danger > td { background-color: #f5c6cb; } .table-hover .table-danger:hover { background-color: #f1b0b7; } .table-hover .table-danger:hover > td, .table-hover .table-danger:hover > th { background-color: #f1b0b7; } .table-light, .table-light > th, .table-light > td { background-color: #fdfdfe; } .table-hover .table-light:hover { background-color: #ececf6; } .table-hover .table-light:hover > td, .table-hover .table-light:hover > th { background-color: #ececf6; } .table-dark, .table-dark > th, .table-dark > td { background-color: #c6c8ca; } .table-hover .table-dark:hover { background-color: #b9bbbe; } .table-hover .table-dark:hover > td, .table-hover .table-dark:hover > th { background-color: #b9bbbe; } .table-active, .table-active > th, .table-active > td { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover > td, .table-hover .table-active:hover > th { background-color: rgba(0, 0, 0, 0.075); } .table .thead-dark th { color: #fff; background-color: #212529; border-color: #32383e; } .table .thead-light th { color: #495057; background-color: #e9ecef; border-color: #dee2e6; } .table-dark { color: #fff; background-color: #212529; } .table-dark th, .table-dark td, .table-dark thead th { border-color: #32383e; } .table-dark.table-bordered { border: 0; } .table-dark.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.05); } .table-dark.table-hover tbody tr:hover { background-color: rgba(255, 255, 255, 0.075); } @media (max-width: 575.99px) { .table-responsive-sm { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-sm > .table-bordered { border: 0; } } @media (max-width: 767.99px) { .table-responsive-md { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-md > .table-bordered { border: 0; } } @media (max-width: 991.99px) { .table-responsive-lg { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-lg > .table-bordered { border: 0; } } @media (max-width: 1199.99px) { .table-responsive-xl { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-xl > .table-bordered { border: 0; } } .table-responsive { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive > .table-bordered { border: 0; } .form-control { display: block; width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 0.25rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control:focus { color: #495057; background-color: #fff; border-color: #80bdff; outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .form-control::-webkit-input-placeholder { color: #868e96; opacity: 1; } .form-control::-moz-placeholder { color: #868e96; opacity: 1; } .form-control:-ms-input-placeholder { color: #868e96; opacity: 1; } .form-control::-ms-input-placeholder { color: #868e96; opacity: 1; } .form-control::placeholder { color: #868e96; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } select.form-control:not([size]):not([multiple]) { height: calc(2.25rem + 2px); } select.form-control:focus::-ms-value { color: #495057; background-color: #fff; } .form-control-file, .form-control-range { display: block; width: 100%; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; line-height: 1.5; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; line-height: 1.5; } .form-control-plaintext { display: block; width: 100%; padding-top: 0.375rem; padding-bottom: 0.375rem; margin-bottom: 0; line-height: 1.5; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control, .input-group-sm > .input-group-prepend > .form-control-plaintext.input-group-text, .input-group-sm > .input-group-append > .form-control-plaintext.input-group-text, .input-group-sm > .input-group-prepend > .form-control-plaintext.btn, .input-group-sm > .input-group-append > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control, .input-group-lg > .input-group-prepend > .form-control-plaintext.input-group-text, .input-group-lg > .input-group-append > .form-control-plaintext.input-group-text, .input-group-lg > .input-group-prepend > .form-control-plaintext.btn, .input-group-lg > .input-group-append > .form-control-plaintext.btn { padding-right: 0; padding-left: 0; } .form-control-sm, .input-group-sm > .form-control, .input-group-sm > .input-group-prepend > .input-group-text, .input-group-sm > .input-group-append > .input-group-text, .input-group-sm > .input-group-prepend > .btn, .input-group-sm > .input-group-append > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]), .input-group-sm > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), .input-group-sm > .input-group-append > select.input-group-text:not([size]):not([multiple]), .input-group-sm > .input-group-prepend > select.btn:not([size]):not([multiple]), .input-group-sm > .input-group-append > select.btn:not([size]):not([multiple]) { height: calc(1.8125rem + 2px); } .form-control-lg, .input-group-lg > .form-control, .input-group-lg > .input-group-prepend > .input-group-text, .input-group-lg > .input-group-append > .input-group-text, .input-group-lg > .input-group-prepend > .btn, .input-group-lg > .input-group-append > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), .input-group-lg > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), .input-group-lg > .input-group-append > select.input-group-text:not([size]):not([multiple]), .input-group-lg > .input-group-prepend > select.btn:not([size]):not([multiple]), .input-group-lg > .input-group-append > select.btn:not([size]):not([multiple]) { height: calc(2.875rem + 2px); } .form-group { margin-bottom: 1rem; } .form-text { display: block; margin-top: 0.25rem; } .form-row { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; } .form-row > .col, .form-row > [class*="col-"] { padding-right: 5px; padding-left: 5px; } .form-check { position: relative; display: block; padding-left: 1.25rem; } .form-check-input { position: absolute; margin-top: 0.3rem; margin-left: -1.25rem; } .form-check-input:disabled ~ .form-check-label { color: #868e96; } .form-check-label { margin-bottom: 0; } .form-check-inline { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; padding-left: 0; margin-right: 0.75rem; } .form-check-inline .form-check-input { position: static; margin-top: 0; margin-right: 0.3125rem; margin-left: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #28a745; } .valid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; width: 250px; padding: .5rem; margin-top: .1rem; font-size: .875rem; line-height: 1; color: #fff; background-color: rgba(40, 167, 69, 0.8); border-radius: .2rem; } .was-validated .form-control:valid, .form-control.is-valid, .was-validated .custom-select:valid, .custom-select.is-valid { border-color: #28a745; } .was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .was-validated .form-control:valid ~ .valid-feedback, .was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, .form-control.is-valid ~ .valid-tooltip, .was-validated .custom-select:valid ~ .valid-feedback, .was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback, .custom-select.is-valid ~ .valid-tooltip { display: block; } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { background-color: #71dd8a; } .was-validated .custom-control-input:valid ~ .valid-feedback, .was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback, .custom-control-input.is-valid ~ .valid-tooltip { display: block; } .was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { background-color: #34ce57; } .was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { border-color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-label::before, .custom-file-input.is-valid ~ .custom-file-label::before { border-color: inherit; } .was-validated .custom-file-input:valid ~ .valid-feedback, .was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback, .custom-file-input.is-valid ~ .valid-tooltip { display: block; } .was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; width: 250px; padding: .5rem; margin-top: .1rem; font-size: .875rem; line-height: 1; color: #fff; background-color: rgba(220, 53, 69, 0.8); border-radius: .2rem; } .was-validated .form-control:invalid, .form-control.is-invalid, .was-validated .custom-select:invalid, .custom-select.is-invalid { border-color: #dc3545; } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .was-validated .form-control:invalid ~ .invalid-feedback, .was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, .form-control.is-invalid ~ .invalid-tooltip, .was-validated .custom-select:invalid ~ .invalid-feedback, .was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback, .custom-select.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { background-color: #efa2a9; } .was-validated .custom-control-input:invalid ~ .invalid-feedback, .was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback, .custom-control-input.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { background-color: #e4606d; } .was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-label::before, .custom-file-input.is-invalid ~ .custom-file-label::before { border-color: inherit; } .was-validated .custom-file-input:invalid ~ .invalid-feedback, .was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback, .custom-file-input.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .form-inline { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .form-inline .form-check { width: 100%; } @media (min-width: 576px) { .form-inline label { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; margin-bottom: 0; } .form-inline .form-group { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-flex: 0; -ms-flex: 0 0 auto; flex: 0 0 auto; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row wrap; flex-flow: row wrap; -webkit-box-align: center; -ms-flex-align: center; align-items: center; margin-bottom: 0; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-plaintext { display: inline-block; } .form-inline .input-group { width: auto; } .form-inline .form-check { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; width: auto; padding-left: 0; } .form-inline .form-check-input { position: relative; margin-top: 0; margin-right: 0.25rem; margin-left: 0; } .form-inline .custom-control { -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .form-inline .custom-control-label { margin-bottom: 0; } } .btn { display: inline-block; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .btn:focus, .btn:hover { text-decoration: none; } .btn:focus, .btn.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .btn.disabled, .btn:disabled { opacity: 0.65; } .btn:not([disabled]):not(.disabled) { cursor: pointer; } .btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active { background-image: none; } a.btn.disabled, fieldset[disabled] a.btn { pointer-events: none; } .btn-primary { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-primary:hover { color: #fff; background-color: #0069d9; border-color: #0062cc; } .btn-primary:focus, .btn-primary.focus { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { background-color: #007bff; border-color: #007bff; } .btn-primary:not([disabled]):not(.disabled):active, .btn-primary:not([disabled]):not(.disabled).active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0062cc; border-color: #005cbf; } .btn-primary:not([disabled]):not(.disabled):active:focus, .btn-primary:not([disabled]):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-secondary { color: #fff; background-color: #868e96; border-color: #868e96; } .btn-secondary:hover { color: #fff; background-color: #727b84; border-color: #6c757d; } .btn-secondary:focus, .btn-secondary.focus { box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { background-color: #868e96; border-color: #868e96; } .btn-secondary:not([disabled]):not(.disabled):active, .btn-secondary:not([disabled]):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #666e76; } .btn-secondary:not([disabled]):not(.disabled):active:focus, .btn-secondary:not([disabled]):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-success { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-success:hover { color: #fff; background-color: #218838; border-color: #1e7e34; } .btn-success:focus, .btn-success.focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-success.disabled, .btn-success:disabled { background-color: #28a745; border-color: #28a745; } .btn-success:not([disabled]):not(.disabled):active, .btn-success:not([disabled]):not(.disabled).active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #1e7e34; border-color: #1c7430; } .btn-success:not([disabled]):not(.disabled):active:focus, .btn-success:not([disabled]):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-info { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-info:hover { color: #fff; background-color: #138496; border-color: #117a8b; } .btn-info:focus, .btn-info.focus { box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-info.disabled, .btn-info:disabled { background-color: #17a2b8; border-color: #17a2b8; } .btn-info:not([disabled]):not(.disabled):active, .btn-info:not([disabled]):not(.disabled).active, .show > .btn-info.dropdown-toggle { color: #fff; background-color: #117a8b; border-color: #10707f; } .btn-info:not([disabled]):not(.disabled):active:focus, .btn-info:not([disabled]):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-warning { color: #212529; background-color: #ffc107; border-color: #ffc107; } .btn-warning:hover { color: #212529; background-color: #e0a800; border-color: #d39e00; } .btn-warning:focus, .btn-warning.focus { box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-warning.disabled, .btn-warning:disabled { background-color: #ffc107; border-color: #ffc107; } .btn-warning:not([disabled]):not(.disabled):active, .btn-warning:not([disabled]):not(.disabled).active, .show > .btn-warning.dropdown-toggle { color: #212529; background-color: #d39e00; border-color: #c69500; } .btn-warning:not([disabled]):not(.disabled):active:focus, .btn-warning:not([disabled]):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:hover { color: #fff; background-color: #c82333; border-color: #bd2130; } .btn-danger:focus, .btn-danger.focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-danger.disabled, .btn-danger:disabled { background-color: #dc3545; border-color: #dc3545; } .btn-danger:not([disabled]):not(.disabled):active, .btn-danger:not([disabled]):not(.disabled).active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #bd2130; border-color: #b21f2d; } .btn-danger:not([disabled]):not(.disabled):active:focus, .btn-danger:not([disabled]):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-light { color: #212529; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:hover { color: #212529; background-color: #e2e6ea; border-color: #dae0e5; } .btn-light:focus, .btn-light.focus { box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-light.disabled, .btn-light:disabled { background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:not([disabled]):not(.disabled):active, .btn-light:not([disabled]):not(.disabled).active, .show > .btn-light.dropdown-toggle { color: #212529; background-color: #dae0e5; border-color: #d3d9df; } .btn-light:not([disabled]):not(.disabled):active:focus, .btn-light:not([disabled]):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-dark { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-dark:hover { color: #fff; background-color: #23272b; border-color: #1d2124; } .btn-dark:focus, .btn-dark.focus { box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-dark.disabled, .btn-dark:disabled { background-color: #343a40; border-color: #343a40; } .btn-dark:not([disabled]):not(.disabled):active, .btn-dark:not([disabled]):not(.disabled).active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1d2124; border-color: #171a1d; } .btn-dark:not([disabled]):not(.disabled):active:focus, .btn-dark:not([disabled]):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-outline-primary { color: #007bff; background-color: transparent; background-image: none; border-color: #007bff; } .btn-outline-primary:hover { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:focus, .btn-outline-primary.focus { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-outline-primary.disabled, .btn-outline-primary:disabled { color: #007bff; background-color: transparent; } .btn-outline-primary:not([disabled]):not(.disabled):active, .btn-outline-primary:not([disabled]):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { color: #212529; background-color: #007bff; border-color: #007bff; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .btn-outline-secondary { color: #868e96; background-color: transparent; background-image: none; border-color: #868e96; } .btn-outline-secondary:hover { color: #fff; background-color: #868e96; border-color: #868e96; } .btn-outline-secondary:focus, .btn-outline-secondary.focus { box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-outline-secondary.disabled, .btn-outline-secondary:disabled { color: #868e96; background-color: transparent; } .btn-outline-secondary:not([disabled]):not(.disabled):active, .btn-outline-secondary:not([disabled]):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { color: #212529; background-color: #868e96; border-color: #868e96; box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); } .btn-outline-success { color: #28a745; background-color: transparent; background-image: none; border-color: #28a745; } .btn-outline-success:hover { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:focus, .btn-outline-success.focus { box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-outline-success.disabled, .btn-outline-success:disabled { color: #28a745; background-color: transparent; } .btn-outline-success:not([disabled]):not(.disabled):active, .btn-outline-success:not([disabled]):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { color: #212529; background-color: #28a745; border-color: #28a745; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .btn-outline-info { color: #17a2b8; background-color: transparent; background-image: none; border-color: #17a2b8; } .btn-outline-info:hover { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:focus, .btn-outline-info.focus { box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-outline-info.disabled, .btn-outline-info:disabled { color: #17a2b8; background-color: transparent; } .btn-outline-info:not([disabled]):not(.disabled):active, .btn-outline-info:not([disabled]):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { color: #212529; background-color: #17a2b8; border-color: #17a2b8; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .btn-outline-warning { color: #ffc107; background-color: transparent; background-image: none; border-color: #ffc107; } .btn-outline-warning:hover { color: #212529; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:focus, .btn-outline-warning.focus { box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-outline-warning.disabled, .btn-outline-warning:disabled { color: #ffc107; background-color: transparent; } .btn-outline-warning:not([disabled]):not(.disabled):active, .btn-outline-warning:not([disabled]):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { color: #212529; background-color: #ffc107; border-color: #ffc107; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .btn-outline-danger { color: #dc3545; background-color: transparent; background-image: none; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:focus, .btn-outline-danger.focus { box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-outline-danger.disabled, .btn-outline-danger:disabled { color: #dc3545; background-color: transparent; } .btn-outline-danger:not([disabled]):not(.disabled):active, .btn-outline-danger:not([disabled]):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { color: #212529; background-color: #dc3545; border-color: #dc3545; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .btn-outline-light { color: #f8f9fa; background-color: transparent; background-image: none; border-color: #f8f9fa; } .btn-outline-light:hover { color: #212529; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:focus, .btn-outline-light.focus { box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-light:not([disabled]):not(.disabled):active, .btn-outline-light:not([disabled]):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { color: #fff; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .btn-outline-dark { color: #343a40; background-color: transparent; background-image: none; border-color: #343a40; } .btn-outline-dark:hover { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:focus, .btn-outline-dark.focus { box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-outline-dark.disabled, .btn-outline-dark:disabled { color: #343a40; background-color: transparent; } .btn-outline-dark:not([disabled]):not(.disabled):active, .btn-outline-dark:not([disabled]):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { color: #212529; background-color: #343a40; border-color: #343a40; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .btn-link { font-weight: 400; color: #007bff; background-color: transparent; } .btn-link:hover { color: #0056b3; text-decoration: underline; background-color: transparent; border-color: transparent; } .btn-link:focus, .btn-link.focus { text-decoration: underline; border-color: transparent; box-shadow: none; } .btn-link:disabled, .btn-link.disabled { color: #868e96; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 0.5rem; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { opacity: 0; transition: opacity 0.15s linear; } .fade.show { opacity: 1; } .collapse { display: none; } .collapse.show { display: block; } tr.collapse.show { display: table-row; } tbody.collapse.show { display: table-row-group; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } .dropup, .dropdown { position: relative; } .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 10rem; padding: 0.5rem 0; margin: 0.125rem 0 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; } .dropup .dropdown-menu { margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-menu { margin-top: 0; margin-left: 0.125rem; } .dropright .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropright .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-toggle::after { vertical-align: 0; } .dropleft .dropdown-menu { margin-top: 0; margin-right: 0.125rem; } .dropleft .dropdown-toggle::after { display: inline-block; width: 0; height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropleft .dropdown-toggle::after { display: none; } .dropleft .dropdown-toggle::before { display: inline-block; width: 0; height: 0; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropleft .dropdown-toggle:empty::after { margin-left: 0; } .dropleft .dropdown-toggle::before { vertical-align: 0; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid #e9ecef; } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1.5rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:focus, .dropdown-item:hover { color: #16181b; text-decoration: none; background-color: #f8f9fa; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #007bff; } .dropdown-item.disabled, .dropdown-item:disabled { color: #868e96; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1.5rem; margin-bottom: 0; font-size: 0.875rem; color: #868e96; white-space: nowrap; } .btn-group, .btn-group-vertical { position: relative; display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; -webkit-box-flex: 0; -ms-flex: 0 1 auto; flex: 0 1 auto; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover { z-index: 1; } .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group, .btn-group-vertical .btn + .btn, .btn-group-vertical .btn + .btn-group, .btn-group-vertical .btn-group + .btn, .btn-group-vertical .btn-group + .btn-group { margin-left: -1px; } .btn-toolbar { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:first-child { margin-left: 0; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after { margin-left: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group-vertical { -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .btn-group-vertical .btn, .btn-group-vertical .btn-group { width: 100%; } .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-toggle > .btn, .btn-group-toggle > .btn-group > .btn { margin-bottom: 0; } .btn-group-toggle > .btn input[type="radio"], .btn-group-toggle > .btn input[type="checkbox"], .btn-group-toggle > .btn-group > .btn input[type="radio"], .btn-group-toggle > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; width: 100%; } .input-group .form-control, .input-group .custom-select, .input-group .custom-file { position: relative; -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; width: 1%; margin-bottom: 0; } .input-group .form-control:focus, .input-group .custom-select:focus, .input-group .custom-file:focus { z-index: 3; } .input-group .form-control + .form-control, .input-group .custom-select + .form-control, .input-group .custom-file + .form-control { margin-left: -1px; } .input-group .form-control:not(:last-child), .input-group .custom-select:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group .form-control:not(:first-child), .input-group .custom-select:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group .custom-file { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .input-group .custom-file:not(:last-child) .custom-file-control, .input-group .custom-file:not(:last-child) .custom-file-control::before { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group .custom-file:not(:first-child) .custom-file-control, .input-group .custom-file:not(:first-child) .custom-file-control::before { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group-prepend, .input-group-append { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .input-group-prepend .btn, .input-group-append .btn { position: relative; z-index: 2; } .input-group-prepend .btn + .btn, .input-group-prepend .btn + .input-group-text, .input-group-prepend .input-group-text + .input-group-text, .input-group-prepend .input-group-text + .btn, .input-group-append .btn + .btn, .input-group-append .btn + .input-group-text, .input-group-append .input-group-text + .input-group-text, .input-group-append .input-group-text + .btn { margin-left: -1px; } .input-group-prepend { margin-right: -1px; } .input-group-append { margin-left: -1px; } .input-group-text { padding: 0.375rem 0.75rem; margin-bottom: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-text input[type="radio"], .input-group-text input[type="checkbox"] { margin-top: 0; } .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group > .input-group-append:not(:last-child) > .btn, .input-group > .input-group-append:not(:last-child) > .input-group-text, .input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .input-group-append > .btn, .input-group > .input-group-append > .input-group-text, .input-group > .input-group-prepend:not(:first-child) > .btn, .input-group > .input-group-prepend:not(:first-child) > .input-group-text, .input-group > .input-group-prepend:first-child > .btn:not(:first-child), .input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .custom-control { position: relative; display: block; min-height: 1.5rem; padding-left: 1.5rem; } .custom-control-inline { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; margin-right: 1rem; } .custom-control-input { position: absolute; z-index: -1; opacity: 0; } .custom-control-input:checked ~ .custom-control-label::before { color: #fff; background-color: #007bff; } .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input:active ~ .custom-control-label::before { color: #fff; background-color: #b3d7ff; } .custom-control-input:disabled ~ .custom-control-label { color: #868e96; } .custom-control-input:disabled ~ .custom-control-label::before { background-color: #e9ecef; } .custom-control-label { margin-bottom: 0; } .custom-control-label::before { position: absolute; top: 0.25rem; left: 0; display: block; width: 1rem; height: 1rem; pointer-events: none; content: ""; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #dee2e6; } .custom-control-label::after { position: absolute; top: 0.25rem; left: 0; display: block; width: 1rem; height: 1rem; content: ""; background-repeat: no-repeat; background-position: center center; background-size: 50% 50%; } .custom-checkbox .custom-control-label::before { border-radius: 0.25rem; } .custom-checkbox .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; } .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { background-color: #007bff; } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); } .custom-radio .custom-control-label::before { border-radius: 50%; } .custom-radio .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; } .custom-radio .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } .custom-select { display: inline-block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; line-height: 1.5; color: #495057; vertical-align: middle; background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; background-size: 8px 10px; border: 1px solid #ced4da; border-radius: 0.25rem; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-select:focus { border-color: #80bdff; outline: 0; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-select:focus::-ms-value { color: #495057; background-color: #fff; } .custom-select[multiple], .custom-select[size]:not([size="1"]) { height: auto; padding-right: 0.75rem; background-image: none; } .custom-select:disabled { color: #868e96; background-color: #e9ecef; } .custom-select::-ms-expand { opacity: 0; } .custom-select-sm { height: calc(1.8125rem + 2px); padding-top: 0.375rem; padding-bottom: 0.375rem; font-size: 75%; } .custom-select-lg { height: calc(2.875rem + 2px); padding-top: 0.375rem; padding-bottom: 0.375rem; font-size: 125%; } .custom-file { position: relative; display: inline-block; width: 100%; height: calc(2.25rem + 2px); margin-bottom: 0; } .custom-file-input { position: relative; z-index: 2; width: 100%; height: calc(2.25rem + 2px); margin: 0; opacity: 0; } .custom-file-input:focus ~ .custom-file-control { border-color: #80bdff; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-file-input:focus ~ .custom-file-control::before { border-color: #80bdff; } .custom-file-input:lang(en) ~ .custom-file-label::after { content: "Browse"; } .custom-file-label { position: absolute; top: 0; right: 0; left: 0; z-index: 1; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; } .custom-file-label::after { position: absolute; top: 0; right: 0; bottom: 0; z-index: 3; display: block; height: calc(calc(2.25rem + 2px) - 1px * 2); padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; content: "Browse"; background-color: #e9ecef; border-left: 1px solid #ced4da; border-radius: 0 0.25rem 0.25rem 0; } .nav { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; } .nav-link:focus, .nav-link:hover { text-decoration: none; } .nav-link.disabled { color: #868e96; } .nav-tabs { border-bottom: 1px solid #dee2e6; } .nav-tabs .nav-item { margin-bottom: -1px; } .nav-tabs .nav-link { border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { border-color: #e9ecef #e9ecef #dee2e6; } .nav-tabs .nav-link.disabled { color: #868e96; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #dee2e6 #dee2e6 #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #007bff; } .nav-fill .nav-item { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; text-align: center; } .nav-justified .nav-item { -ms-flex-preferred-size: 0; flex-basis: 0; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; text-align: center; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; padding: 0.5rem 1rem; } .navbar > .container, .navbar > .container-fluid { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .navbar-brand { display: inline-block; padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 1rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; } .navbar-brand:focus, .navbar-brand:hover { text-decoration: none; } .navbar-nav { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-text { display: inline-block; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { -ms-flex-preferred-size: 100%; flex-basis: 100%; -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .navbar-toggler:focus, .navbar-toggler:hover { text-decoration: none; } .navbar-toggler:not([disabled]):not(.disabled) { cursor: pointer; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; content: ""; background: no-repeat center center; background-size: 100% 100%; } @media (max-width: 575.99px) { .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 576px) { .navbar-expand-sm { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row nowrap; flex-flow: row nowrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-sm .navbar-collapse { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } .navbar-expand-sm .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 767.99px) { .navbar-expand-md > .container, .navbar-expand-md > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 768px) { .navbar-expand-md { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row nowrap; flex-flow: row nowrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-md .navbar-nav { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-md .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-md > .container, .navbar-expand-md > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-md .navbar-collapse { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } .navbar-expand-md .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 991.99px) { .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 992px) { .navbar-expand-lg { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row nowrap; flex-flow: row nowrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-lg .navbar-collapse { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } .navbar-expand-lg .dropup .dropdown-menu { top: auto; bottom: 100%; } } @media (max-width: 1199.99px) { .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid { padding-right: 0; padding-left: 0; } } @media (min-width: 1200px) { .navbar-expand-xl { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row nowrap; flex-flow: row nowrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-xl .navbar-collapse { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } .navbar-expand-xl .dropup .dropdown-menu { top: auto; bottom: 100%; } } .navbar-expand { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row nowrap; flex-flow: row nowrap; -webkit-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand > .container, .navbar-expand > .container-fluid { padding-right: 0; padding-left: 0; } .navbar-expand .navbar-nav { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .dropdown-menu-right { right: 0; left: auto; } .navbar-expand .navbar-nav .nav-link { padding-right: .5rem; padding-left: .5rem; } .navbar-expand > .container, .navbar-expand > .container-fluid { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand .navbar-collapse { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-expand .dropup .dropdown-menu { top: auto; bottom: 100%; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.5); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-text a { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.5); } .navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.5); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.5); } .navbar-dark .navbar-text a { color: #fff; } .navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover { color: #fff; } .card { position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 1px solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group:first-child .list-group-item:first-child { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .card > .list-group:last-child .list-group-item:last-child { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .card-body { -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1.25rem; } .card-title { margin-bottom: 0.75rem; } .card-subtitle { margin-top: -0.375rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1.25rem; } .card-header { padding: 0.75rem 1.25rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; } .card-header + .list-group .list-group-item:first-child { border-top: 0; } .card-footer { padding: 0.75rem 1.25rem; background-color: rgba(0, 0, 0, 0.03); border-top: 1px solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); } .card-header-tabs { margin-right: -0.625rem; margin-bottom: -0.75rem; margin-left: -0.625rem; border-bottom: 0; } .card-header-pills { margin-right: -0.625rem; margin-left: -0.625rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1.25rem; } .card-img { width: 100%; border-radius: calc(0.25rem - 1px); } .card-img-top { width: 100%; border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .card-img-bottom { width: 100%; border-bottom-right-radius: calc(0.25rem - 1px); border-bottom-left-radius: calc(0.25rem - 1px); } .card-deck { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .card-deck .card { margin-bottom: 15px; } @media (min-width: 576px) { .card-deck { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row wrap; flex-flow: row wrap; margin-right: -15px; margin-left: -15px; } .card-deck .card { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-flex: 1; -ms-flex: 1 0 0%; flex: 1 0 0%; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; margin-right: 15px; margin-bottom: 0; margin-left: 15px; } } .card-group { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .card-group > .card { margin-bottom: 15px; } @media (min-width: 576px) { .card-group { -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-flow: row wrap; flex-flow: row wrap; } .card-group > .card { -webkit-box-flex: 1; -ms-flex: 1 0 0%; flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:first-child .card-img-top, .card-group > .card:first-child .card-header { border-top-right-radius: 0; } .card-group > .card:first-child .card-img-bottom, .card-group > .card:first-child .card-footer { border-bottom-right-radius: 0; } .card-group > .card:last-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:last-child .card-img-top, .card-group > .card:last-child .card-header { border-top-left-radius: 0; } .card-group > .card:last-child .card-img-bottom, .card-group > .card:last-child .card-footer { border-bottom-left-radius: 0; } .card-group > .card:only-child { border-radius: 0.25rem; } .card-group > .card:only-child .card-img-top, .card-group > .card:only-child .card-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .card-group > .card:only-child .card-img-bottom, .card-group > .card:only-child .card-footer { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .card-group > .card:not(:first-child):not(:last-child):not(:only-child) { border-radius: 0; } .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header, .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer { border-radius: 0; } } .card-columns .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-columns { -webkit-column-count: 3; -moz-column-count: 3; column-count: 3; -webkit-column-gap: 1.25rem; -moz-column-gap: 1.25rem; column-gap: 1.25rem; } .card-columns .card { display: inline-block; width: 100%; } } .breadcrumb { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0.75rem 1rem; margin-bottom: 1rem; list-style: none; background-color: #e9ecef; border-radius: 0.25rem; } .breadcrumb-item + .breadcrumb-item::before { display: inline-block; padding-right: 0.5rem; padding-left: 0.5rem; color: #868e96; content: "/"; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: underline; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: none; } .breadcrumb-item.active { color: #868e96; } .pagination { display: -webkit-box; display: -ms-flexbox; display: flex; padding-left: 0; list-style: none; border-radius: 0.25rem; } .page-link { position: relative; display: block; padding: 0.5rem 0.75rem; margin-left: -1px; line-height: 1.25; color: #007bff; background-color: #fff; border: 1px solid #dee2e6; } .page-link:focus, .page-link:hover { color: #0056b3; text-decoration: none; background-color: #e9ecef; border-color: #dee2e6; } .page-link:not([disabled]):not(.disabled) { cursor: pointer; } .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .page-item.active .page-link { z-index: 1; color: #fff; background-color: #007bff; border-color: #007bff; } .page-item.disabled .page-link { color: #868e96; pointer-events: none; cursor: auto; background-color: #fff; border-color: #dee2e6; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; line-height: 1.5; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .badge-pill { padding-right: 0.6em; padding-left: 0.6em; border-radius: 10rem; } .badge-primary { color: #fff; background-color: #007bff; } .badge-primary[href]:focus, .badge-primary[href]:hover { color: #fff; text-decoration: none; background-color: #0062cc; } .badge-secondary { color: #fff; background-color: #868e96; } .badge-secondary[href]:focus, .badge-secondary[href]:hover { color: #fff; text-decoration: none; background-color: #6c757d; } .badge-success { color: #fff; background-color: #28a745; } .badge-success[href]:focus, .badge-success[href]:hover { color: #fff; text-decoration: none; background-color: #1e7e34; } .badge-info { color: #fff; background-color: #17a2b8; } .badge-info[href]:focus, .badge-info[href]:hover { color: #fff; text-decoration: none; background-color: #117a8b; } .badge-warning { color: #212529; background-color: #ffc107; } .badge-warning[href]:focus, .badge-warning[href]:hover { color: #212529; text-decoration: none; background-color: #d39e00; } .badge-danger { color: #fff; background-color: #dc3545; } .badge-danger[href]:focus, .badge-danger[href]:hover { color: #fff; text-decoration: none; background-color: #bd2130; } .badge-light { color: #212529; background-color: #f8f9fa; } .badge-light[href]:focus, .badge-light[href]:hover { color: #212529; text-decoration: none; background-color: #dae0e5; } .badge-dark { color: #fff; background-color: #343a40; } .badge-dark[href]:focus, .badge-dark[href]:hover { color: #fff; text-decoration: none; background-color: #1d2124; } .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; background-color: #e9ecef; border-radius: 0.3rem; } @media (min-width: 576px) { .jumbotron { padding: 4rem 2rem; } } .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; } .alert { position: relative; padding: 0.75rem 1.25rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 4rem; } .alert-dismissible .close { position: absolute; top: 0; right: 0; padding: 0.75rem 1.25rem; color: inherit; } .alert-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-primary hr { border-top-color: #9fcdff; } .alert-primary .alert-link { color: #002752; } .alert-secondary { color: #464a4e; background-color: #e7e8ea; border-color: #dddfe2; } .alert-secondary hr { border-top-color: #cfd2d6; } .alert-secondary .alert-link { color: #2e3133; } .alert-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-success hr { border-top-color: #b1dfbb; } .alert-success .alert-link { color: #0b2e13; } .alert-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-info hr { border-top-color: #abdde5; } .alert-info .alert-link { color: #062c33; } .alert-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-warning hr { border-top-color: #ffe8a1; } .alert-warning .alert-link { color: #533f03; } .alert-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-danger hr { border-top-color: #f1b0b7; } .alert-danger .alert-link { color: #491217; } .alert-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-light hr { border-top-color: #ececf6; } .alert-light .alert-link { color: #686868; } .alert-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-dark hr { border-top-color: #b9bbbe; } .alert-dark .alert-link { color: #040505; } @-webkit-keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } .progress { display: -webkit-box; display: -ms-flexbox; display: flex; height: 1rem; overflow: hidden; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; } .progress-bar { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; color: #fff; text-align: center; background-color: #007bff; transition: width 0.6s ease; } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: progress-bar-stripes 1s linear infinite; animation: progress-bar-stripes 1s linear infinite; } .media { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; } .media-body { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } .list-group { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:focus, .list-group-item-action:hover { color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.75rem 1.25rem; margin-bottom: -1px; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .list-group-item:last-child { margin-bottom: 0; border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .list-group-item:focus, .list-group-item:hover { z-index: 1; text-decoration: none; } .list-group-item.disabled, .list-group-item:disabled { color: #868e96; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .list-group-flush .list-group-item { border-right: 0; border-left: 0; border-radius: 0; } .list-group-flush:first-child .list-group-item:first-child { border-top: 0; } .list-group-flush:last-child .list-group-item:last-child { border-bottom: 0; } .list-group-item-primary { color: #004085; background-color: #b8daff; } a.list-group-item-primary, button.list-group-item-primary { color: #004085; } a.list-group-item-primary:focus, a.list-group-item-primary:hover, button.list-group-item-primary:focus, button.list-group-item-primary:hover { color: #004085; background-color: #9fcdff; } a.list-group-item-primary.active, button.list-group-item-primary.active { color: #fff; background-color: #004085; border-color: #004085; } .list-group-item-secondary { color: #464a4e; background-color: #dddfe2; } a.list-group-item-secondary, button.list-group-item-secondary { color: #464a4e; } a.list-group-item-secondary:focus, a.list-group-item-secondary:hover, button.list-group-item-secondary:focus, button.list-group-item-secondary:hover { color: #464a4e; background-color: #cfd2d6; } a.list-group-item-secondary.active, button.list-group-item-secondary.active { color: #fff; background-color: #464a4e; border-color: #464a4e; } .list-group-item-success { color: #155724; background-color: #c3e6cb; } a.list-group-item-success, button.list-group-item-success { color: #155724; } a.list-group-item-success:focus, a.list-group-item-success:hover, button.list-group-item-success:focus, button.list-group-item-success:hover { color: #155724; background-color: #b1dfbb; } a.list-group-item-success.active, button.list-group-item-success.active { color: #fff; background-color: #155724; border-color: #155724; } .list-group-item-info { color: #0c5460; background-color: #bee5eb; } a.list-group-item-info, button.list-group-item-info { color: #0c5460; } a.list-group-item-info:focus, a.list-group-item-info:hover, button.list-group-item-info:focus, button.list-group-item-info:hover { color: #0c5460; background-color: #abdde5; } a.list-group-item-info.active, button.list-group-item-info.active { color: #fff; background-color: #0c5460; border-color: #0c5460; } .list-group-item-warning { color: #856404; background-color: #ffeeba; } a.list-group-item-warning, button.list-group-item-warning { color: #856404; } a.list-group-item-warning:focus, a.list-group-item-warning:hover, button.list-group-item-warning:focus, button.list-group-item-warning:hover { color: #856404; background-color: #ffe8a1; } a.list-group-item-warning.active, button.list-group-item-warning.active { color: #fff; background-color: #856404; border-color: #856404; } .list-group-item-danger { color: #721c24; background-color: #f5c6cb; } a.list-group-item-danger, button.list-group-item-danger { color: #721c24; } a.list-group-item-danger:focus, a.list-group-item-danger:hover, button.list-group-item-danger:focus, button.list-group-item-danger:hover { color: #721c24; background-color: #f1b0b7; } a.list-group-item-danger.active, button.list-group-item-danger.active { color: #fff; background-color: #721c24; border-color: #721c24; } .list-group-item-light { color: #818182; background-color: #fdfdfe; } a.list-group-item-light, button.list-group-item-light { color: #818182; } a.list-group-item-light:focus, a.list-group-item-light:hover, button.list-group-item-light:focus, button.list-group-item-light:hover { color: #818182; background-color: #ececf6; } a.list-group-item-light.active, button.list-group-item-light.active { color: #fff; background-color: #818182; border-color: #818182; } .list-group-item-dark { color: #1b1e21; background-color: #c6c8ca; } a.list-group-item-dark, button.list-group-item-dark { color: #1b1e21; } a.list-group-item-dark:focus, a.list-group-item-dark:hover, button.list-group-item-dark:focus, button.list-group-item-dark:hover { color: #1b1e21; background-color: #b9bbbe; } a.list-group-item-dark.active, button.list-group-item-dark.active { color: #fff; background-color: #1b1e21; border-color: #1b1e21; } .close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:focus, .close:hover { color: #000; text-decoration: none; opacity: .75; } .close:not([disabled]):not(.disabled) { cursor: pointer; } button.close { padding: 0; background-color: transparent; border: 0; -webkit-appearance: none; } .modal-open { overflow: hidden; } .modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; display: none; overflow: hidden; outline: 0; } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal-dialog { position: relative; width: auto; margin: 0.5rem; pointer-events: none; } .modal.fade .modal-dialog { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; -webkit-transform: translate(0, -25%); transform: translate(0, -25%); } .modal.show .modal-dialog { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .modal-dialog-centered { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; min-height: calc(100% - (0.5rem * 2)); } .modal-content { position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; width: 100%; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; outline: 0; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: start; -ms-flex-align: start; align-items: flex-start; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; padding: 1rem; border-bottom: 1px solid #e9ecef; border-top-left-radius: 0.3rem; border-top-right-radius: 0.3rem; } .modal-header .close { padding: 1rem; margin: -1rem -1rem -1rem auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; -webkit-box-flex: 1; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1rem; } .modal-footer { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; padding: 1rem; border-top: 1px solid #e9ecef; } .modal-footer > :not(:first-child) { margin-left: .25rem; } .modal-footer > :not(:last-child) { margin-right: .25rem; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 1.75rem auto; } .modal-dialog-centered { min-height: calc(100% - (1.75rem * 2)); } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg { max-width: 800px; } } .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .tooltip .arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { padding: 0.4rem 0; } .bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { bottom: 0; } .bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { top: 0; border-width: 0.4rem 0.4rem 0; border-top-color: #000; } .bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { padding: 0 0.4rem; } .bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { left: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { right: 0; border-width: 0.4rem 0.4rem 0.4rem 0; border-right-color: #000; } .bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { padding: 0.4rem 0; } .bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { top: 0; } .bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { bottom: 0; border-width: 0 0.4rem 0.4rem; border-bottom-color: #000; } .bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { padding: 0 0.4rem; } .bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { right: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { left: 0; border-width: 0.4rem 0 0.4rem 0.4rem; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: block; max-width: 276px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; } .popover .arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; margin: 0 0.3rem; } .popover .arrow::before, .popover .arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; } .bs-popover-top, .bs-popover-auto[x-placement^="top"] { margin-bottom: 0.5rem; } .bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow { bottom: calc((0.5rem + 1px) * -1); } .bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before, .bs-popover-top .arrow::after, .bs-popover-auto[x-placement^="top"] .arrow::after { border-width: 0.5rem 0.5rem 0; } .bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before { bottom: 0; border-top-color: rgba(0, 0, 0, 0.25); } .bs-popover-top .arrow::after, .bs-popover-auto[x-placement^="top"] .arrow::after { bottom: 1px; border-top-color: #fff; } .bs-popover-right, .bs-popover-auto[x-placement^="right"] { margin-left: 0.5rem; } .bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow { left: calc((0.5rem + 1px) * -1); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before, .bs-popover-right .arrow::after, .bs-popover-auto[x-placement^="right"] .arrow::after { border-width: 0.5rem 0.5rem 0.5rem 0; } .bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before { left: 0; border-right-color: rgba(0, 0, 0, 0.25); } .bs-popover-right .arrow::after, .bs-popover-auto[x-placement^="right"] .arrow::after { left: 1px; border-right-color: #fff; } .bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { margin-top: 0.5rem; } .bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow { top: calc((0.5rem + 1px) * -1); } .bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before, .bs-popover-bottom .arrow::after, .bs-popover-auto[x-placement^="bottom"] .arrow::after { border-width: 0 0.5rem 0.5rem 0.5rem; } .bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before { top: 0; border-bottom-color: rgba(0, 0, 0, 0.25); } .bs-popover-bottom .arrow::after, .bs-popover-auto[x-placement^="bottom"] .arrow::after { top: 1px; border-bottom-color: #fff; } .bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 1rem; margin-left: -0.5rem; content: ""; border-bottom: 1px solid #f7f7f7; } .bs-popover-left, .bs-popover-auto[x-placement^="left"] { margin-right: 0.5rem; } .bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow { right: calc((0.5rem + 1px) * -1); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before, .bs-popover-left .arrow::after, .bs-popover-auto[x-placement^="left"] .arrow::after { border-width: 0.5rem 0 0.5rem 0.5rem; } .bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before { right: 0; border-left-color: rgba(0, 0, 0, 0.25); } .bs-popover-left .arrow::after, .bs-popover-auto[x-placement^="left"] .arrow::after { right: 1px; border-left-color: #fff; } .popover-header { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 0.5rem 0.75rem; color: #212529; } .carousel { position: relative; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-item { position: relative; display: none; -webkit-box-align: center; -ms-flex-align: center; align-items: center; width: 100%; transition: -webkit-transform 0.6s ease; transition: transform 0.6s ease; transition: transform 0.6s ease, -webkit-transform 0.6s ease; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next, .carousel-item-prev { position: absolute; top: 0; } .carousel-item-next.carousel-item-left, .carousel-item-prev.carousel-item-right { -webkit-transform: translateX(0); transform: translateX(0); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-next.carousel-item-left, .carousel-item-prev.carousel-item-right { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .carousel-item-next, .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-next, .active.carousel-item-right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); } } .carousel-item-prev, .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } @supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { .carousel-item-prev, .active.carousel-item-left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; width: 15%; color: #fff; text-align: center; opacity: 0.5; } .carousel-control-prev:focus, .carousel-control-prev:hover, .carousel-control-next:focus, .carousel-control-next:hover { color: #fff; text-decoration: none; outline: 0; opacity: .9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: transparent no-repeat center center; background-size: 100% 100%; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); } .carousel-indicators { position: absolute; right: 0; bottom: 10px; left: 0; z-index: 15; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; } .carousel-indicators li { position: relative; -webkit-box-flex: 0; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; background-color: rgba(255, 255, 255, 0.5); } .carousel-indicators li::before { position: absolute; top: -10px; left: 0; display: inline-block; width: 100%; height: 10px; content: ""; } .carousel-indicators li::after { position: absolute; bottom: -10px; left: 0; display: inline-block; width: 100%; height: 10px; content: ""; } .carousel-indicators .active { background-color: #fff; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .bg-primary { background-color: #007bff !important; } a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { background-color: #0062cc !important; } .bg-secondary { background-color: #868e96 !important; } a.bg-secondary:focus, a.bg-secondary:hover, button.bg-secondary:focus, button.bg-secondary:hover { background-color: #6c757d !important; } .bg-success { background-color: #28a745 !important; } a.bg-success:focus, a.bg-success:hover, button.bg-success:focus, button.bg-success:hover { background-color: #1e7e34 !important; } .bg-info { background-color: #17a2b8 !important; } a.bg-info:focus, a.bg-info:hover, button.bg-info:focus, button.bg-info:hover { background-color: #117a8b !important; } .bg-warning { background-color: #ffc107 !important; } a.bg-warning:focus, a.bg-warning:hover, button.bg-warning:focus, button.bg-warning:hover { background-color: #d39e00 !important; } .bg-danger { background-color: #dc3545 !important; } a.bg-danger:focus, a.bg-danger:hover, button.bg-danger:focus, button.bg-danger:hover { background-color: #bd2130 !important; } .bg-light { background-color: #f8f9fa !important; } a.bg-light:focus, a.bg-light:hover, button.bg-light:focus, button.bg-light:hover { background-color: #dae0e5 !important; } .bg-dark { background-color: #343a40 !important; } a.bg-dark:focus, a.bg-dark:hover, button.bg-dark:focus, button.bg-dark:hover { background-color: #1d2124 !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .border { border: 1px solid #e9ecef !important; } .border-0 { border: 0 !important; } .border-top-0 { border-top: 0 !important; } .border-right-0 { border-right: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-left-0 { border-left: 0 !important; } .border-primary { border-color: #007bff !important; } .border-secondary { border-color: #868e96 !important; } .border-success { border-color: #28a745 !important; } .border-info { border-color: #17a2b8 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #343a40 !important; } .border-white { border-color: #fff !important; } .rounded { border-radius: 0.25rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-right { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-left { border-top-left-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-0 { border-radius: 0 !important; } .clearfix::after { display: block; clear: both; content: ""; } .d-none { display: none !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; } .d-inline-flex { display: -webkit-inline-box !important; display: -ms-inline-flexbox !important; display: inline-flex !important; } @media (min-width: 576px) { .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; } .d-sm-inline-flex { display: -webkit-inline-box !important; display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 768px) { .d-md-none { display: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; } .d-md-inline-flex { display: -webkit-inline-box !important; display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 992px) { .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; } .d-lg-inline-flex { display: -webkit-inline-box !important; display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 1200px) { .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: -webkit-box !important; display: -ms-flexbox !important; display: flex !important; } .d-xl-inline-flex { display: -webkit-inline-box !important; display: -ms-inline-flexbox !important; display: inline-flex !important; } } .d-print-block { display: none !important; } @media print { .d-print-block { display: block !important; } } .d-print-inline { display: none !important; } @media print { .d-print-inline { display: inline !important; } } .d-print-inline-block { display: none !important; } @media print { .d-print-inline-block { display: inline-block !important; } } @media print { .d-print-none { display: none !important; } } .embed-responsive { position: relative; display: block; width: 100%; padding: 0; overflow: hidden; } .embed-responsive::before { display: block; content: ""; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-21by9::before { padding-top: 42.857143%; } .embed-responsive-16by9::before { padding-top: 56.25%; } .embed-responsive-4by3::before { padding-top: 75%; } .embed-responsive-1by1::before { padding-top: 100%; } .flex-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-sm-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-md-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-lg-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -webkit-box-orient: horizontal !important; -webkit-box-direction: normal !important; -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -webkit-box-orient: vertical !important; -webkit-box-direction: normal !important; -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -webkit-box-orient: horizontal !important; -webkit-box-direction: reverse !important; -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -webkit-box-orient: vertical !important; -webkit-box-direction: reverse !important; -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .justify-content-xl-start { -webkit-box-pack: start !important; -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -webkit-box-pack: end !important; -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -webkit-box-pack: center !important; -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -webkit-box-pack: justify !important; -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -webkit-box-align: start !important; -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -webkit-box-align: end !important; -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -webkit-box-align: center !important; -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -webkit-box-align: baseline !important; -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -webkit-box-align: stretch !important; -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } .float-left { float: left !important; } .float-right { float: right !important; } .float-none { float: none !important; } @media (min-width: 576px) { .float-sm-left { float: left !important; } .float-sm-right { float: right !important; } .float-sm-none { float: none !important; } } @media (min-width: 768px) { .float-md-left { float: left !important; } .float-md-right { float: right !important; } .float-md-none { float: none !important; } } @media (min-width: 992px) { .float-lg-left { float: left !important; } .float-lg-right { float: right !important; } .float-lg-none { float: none !important; } } @media (min-width: 1200px) { .float-xl-left { float: left !important; } .float-xl-right { float: right !important; } .float-xl-none { float: none !important; } } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } @supports ((position: -webkit-sticky) or (position: sticky)) { .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; -webkit-clip-path: inset(50%); clip-path: inset(50%); border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; -webkit-clip-path: none; clip-path: none; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } .m-0 { margin: 0 !important; } .mt-0, .my-0 { margin-top: 0 !important; } .mr-0, .mx-0 { margin-right: 0 !important; } .mb-0, .my-0 { margin-bottom: 0 !important; } .ml-0, .mx-0 { margin-left: 0 !important; } .m-1 { margin: 0.25rem !important; } .mt-1, .my-1 { margin-top: 0.25rem !important; } .mr-1, .mx-1 { margin-right: 0.25rem !important; } .mb-1, .my-1 { margin-bottom: 0.25rem !important; } .ml-1, .mx-1 { margin-left: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .mt-2, .my-2 { margin-top: 0.5rem !important; } .mr-2, .mx-2 { margin-right: 0.5rem !important; } .mb-2, .my-2 { margin-bottom: 0.5rem !important; } .ml-2, .mx-2 { margin-left: 0.5rem !important; } .m-3 { margin: 1rem !important; } .mt-3, .my-3 { margin-top: 1rem !important; } .mr-3, .mx-3 { margin-right: 1rem !important; } .mb-3, .my-3 { margin-bottom: 1rem !important; } .ml-3, .mx-3 { margin-left: 1rem !important; } .m-4 { margin: 1.5rem !important; } .mt-4, .my-4 { margin-top: 1.5rem !important; } .mr-4, .mx-4 { margin-right: 1.5rem !important; } .mb-4, .my-4 { margin-bottom: 1.5rem !important; } .ml-4, .mx-4 { margin-left: 1.5rem !important; } .m-5 { margin: 3rem !important; } .mt-5, .my-5 { margin-top: 3rem !important; } .mr-5, .mx-5 { margin-right: 3rem !important; } .mb-5, .my-5 { margin-bottom: 3rem !important; } .ml-5, .mx-5 { margin-left: 3rem !important; } .p-0 { padding: 0 !important; } .pt-0, .py-0 { padding-top: 0 !important; } .pr-0, .px-0 { padding-right: 0 !important; } .pb-0, .py-0 { padding-bottom: 0 !important; } .pl-0, .px-0 { padding-left: 0 !important; } .p-1 { padding: 0.25rem !important; } .pt-1, .py-1 { padding-top: 0.25rem !important; } .pr-1, .px-1 { padding-right: 0.25rem !important; } .pb-1, .py-1 { padding-bottom: 0.25rem !important; } .pl-1, .px-1 { padding-left: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .pt-2, .py-2 { padding-top: 0.5rem !important; } .pr-2, .px-2 { padding-right: 0.5rem !important; } .pb-2, .py-2 { padding-bottom: 0.5rem !important; } .pl-2, .px-2 { padding-left: 0.5rem !important; } .p-3 { padding: 1rem !important; } .pt-3, .py-3 { padding-top: 1rem !important; } .pr-3, .px-3 { padding-right: 1rem !important; } .pb-3, .py-3 { padding-bottom: 1rem !important; } .pl-3, .px-3 { padding-left: 1rem !important; } .p-4 { padding: 1.5rem !important; } .pt-4, .py-4 { padding-top: 1.5rem !important; } .pr-4, .px-4 { padding-right: 1.5rem !important; } .pb-4, .py-4 { padding-bottom: 1.5rem !important; } .pl-4, .px-4 { padding-left: 1.5rem !important; } .p-5 { padding: 3rem !important; } .pt-5, .py-5 { padding-top: 3rem !important; } .pr-5, .px-5 { padding-right: 3rem !important; } .pb-5, .py-5 { padding-bottom: 3rem !important; } .pl-5, .px-5 { padding-left: 3rem !important; } .m-auto { margin: auto !important; } .mt-auto, .my-auto { margin-top: auto !important; } .mr-auto, .mx-auto { margin-right: auto !important; } .mb-auto, .my-auto { margin-bottom: auto !important; } .ml-auto, .mx-auto { margin-left: auto !important; } @media (min-width: 576px) { .m-sm-0 { margin: 0 !important; } .mt-sm-0, .my-sm-0 { margin-top: 0 !important; } .mr-sm-0, .mx-sm-0 { margin-right: 0 !important; } .mb-sm-0, .my-sm-0 { margin-bottom: 0 !important; } .ml-sm-0, .mx-sm-0 { margin-left: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .mt-sm-1, .my-sm-1 { margin-top: 0.25rem !important; } .mr-sm-1, .mx-sm-1 { margin-right: 0.25rem !important; } .mb-sm-1, .my-sm-1 { margin-bottom: 0.25rem !important; } .ml-sm-1, .mx-sm-1 { margin-left: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .mt-sm-2, .my-sm-2 { margin-top: 0.5rem !important; } .mr-sm-2, .mx-sm-2 { margin-right: 0.5rem !important; } .mb-sm-2, .my-sm-2 { margin-bottom: 0.5rem !important; } .ml-sm-2, .mx-sm-2 { margin-left: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .mt-sm-3, .my-sm-3 { margin-top: 1rem !important; } .mr-sm-3, .mx-sm-3 { margin-right: 1rem !important; } .mb-sm-3, .my-sm-3 { margin-bottom: 1rem !important; } .ml-sm-3, .mx-sm-3 { margin-left: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .mt-sm-4, .my-sm-4 { margin-top: 1.5rem !important; } .mr-sm-4, .mx-sm-4 { margin-right: 1.5rem !important; } .mb-sm-4, .my-sm-4 { margin-bottom: 1.5rem !important; } .ml-sm-4, .mx-sm-4 { margin-left: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .mt-sm-5, .my-sm-5 { margin-top: 3rem !important; } .mr-sm-5, .mx-sm-5 { margin-right: 3rem !important; } .mb-sm-5, .my-sm-5 { margin-bottom: 3rem !important; } .ml-sm-5, .mx-sm-5 { margin-left: 3rem !important; } .p-sm-0 { padding: 0 !important; } .pt-sm-0, .py-sm-0 { padding-top: 0 !important; } .pr-sm-0, .px-sm-0 { padding-right: 0 !important; } .pb-sm-0, .py-sm-0 { padding-bottom: 0 !important; } .pl-sm-0, .px-sm-0 { padding-left: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .pt-sm-1, .py-sm-1 { padding-top: 0.25rem !important; } .pr-sm-1, .px-sm-1 { padding-right: 0.25rem !important; } .pb-sm-1, .py-sm-1 { padding-bottom: 0.25rem !important; } .pl-sm-1, .px-sm-1 { padding-left: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .pt-sm-2, .py-sm-2 { padding-top: 0.5rem !important; } .pr-sm-2, .px-sm-2 { padding-right: 0.5rem !important; } .pb-sm-2, .py-sm-2 { padding-bottom: 0.5rem !important; } .pl-sm-2, .px-sm-2 { padding-left: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .pt-sm-3, .py-sm-3 { padding-top: 1rem !important; } .pr-sm-3, .px-sm-3 { padding-right: 1rem !important; } .pb-sm-3, .py-sm-3 { padding-bottom: 1rem !important; } .pl-sm-3, .px-sm-3 { padding-left: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .pt-sm-4, .py-sm-4 { padding-top: 1.5rem !important; } .pr-sm-4, .px-sm-4 { padding-right: 1.5rem !important; } .pb-sm-4, .py-sm-4 { padding-bottom: 1.5rem !important; } .pl-sm-4, .px-sm-4 { padding-left: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .pt-sm-5, .py-sm-5 { padding-top: 3rem !important; } .pr-sm-5, .px-sm-5 { padding-right: 3rem !important; } .pb-sm-5, .py-sm-5 { padding-bottom: 3rem !important; } .pl-sm-5, .px-sm-5 { padding-left: 3rem !important; } .m-sm-auto { margin: auto !important; } .mt-sm-auto, .my-sm-auto { margin-top: auto !important; } .mr-sm-auto, .mx-sm-auto { margin-right: auto !important; } .mb-sm-auto, .my-sm-auto { margin-bottom: auto !important; } .ml-sm-auto, .mx-sm-auto { margin-left: auto !important; } } @media (min-width: 768px) { .m-md-0 { margin: 0 !important; } .mt-md-0, .my-md-0 { margin-top: 0 !important; } .mr-md-0, .mx-md-0 { margin-right: 0 !important; } .mb-md-0, .my-md-0 { margin-bottom: 0 !important; } .ml-md-0, .mx-md-0 { margin-left: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .mt-md-1, .my-md-1 { margin-top: 0.25rem !important; } .mr-md-1, .mx-md-1 { margin-right: 0.25rem !important; } .mb-md-1, .my-md-1 { margin-bottom: 0.25rem !important; } .ml-md-1, .mx-md-1 { margin-left: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .mt-md-2, .my-md-2 { margin-top: 0.5rem !important; } .mr-md-2, .mx-md-2 { margin-right: 0.5rem !important; } .mb-md-2, .my-md-2 { margin-bottom: 0.5rem !important; } .ml-md-2, .mx-md-2 { margin-left: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .mt-md-3, .my-md-3 { margin-top: 1rem !important; } .mr-md-3, .mx-md-3 { margin-right: 1rem !important; } .mb-md-3, .my-md-3 { margin-bottom: 1rem !important; } .ml-md-3, .mx-md-3 { margin-left: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .mt-md-4, .my-md-4 { margin-top: 1.5rem !important; } .mr-md-4, .mx-md-4 { margin-right: 1.5rem !important; } .mb-md-4, .my-md-4 { margin-bottom: 1.5rem !important; } .ml-md-4, .mx-md-4 { margin-left: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .mt-md-5, .my-md-5 { margin-top: 3rem !important; } .mr-md-5, .mx-md-5 { margin-right: 3rem !important; } .mb-md-5, .my-md-5 { margin-bottom: 3rem !important; } .ml-md-5, .mx-md-5 { margin-left: 3rem !important; } .p-md-0 { padding: 0 !important; } .pt-md-0, .py-md-0 { padding-top: 0 !important; } .pr-md-0, .px-md-0 { padding-right: 0 !important; } .pb-md-0, .py-md-0 { padding-bottom: 0 !important; } .pl-md-0, .px-md-0 { padding-left: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .pt-md-1, .py-md-1 { padding-top: 0.25rem !important; } .pr-md-1, .px-md-1 { padding-right: 0.25rem !important; } .pb-md-1, .py-md-1 { padding-bottom: 0.25rem !important; } .pl-md-1, .px-md-1 { padding-left: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .pt-md-2, .py-md-2 { padding-top: 0.5rem !important; } .pr-md-2, .px-md-2 { padding-right: 0.5rem !important; } .pb-md-2, .py-md-2 { padding-bottom: 0.5rem !important; } .pl-md-2, .px-md-2 { padding-left: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .pt-md-3, .py-md-3 { padding-top: 1rem !important; } .pr-md-3, .px-md-3 { padding-right: 1rem !important; } .pb-md-3, .py-md-3 { padding-bottom: 1rem !important; } .pl-md-3, .px-md-3 { padding-left: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .pt-md-4, .py-md-4 { padding-top: 1.5rem !important; } .pr-md-4, .px-md-4 { padding-right: 1.5rem !important; } .pb-md-4, .py-md-4 { padding-bottom: 1.5rem !important; } .pl-md-4, .px-md-4 { padding-left: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .pt-md-5, .py-md-5 { padding-top: 3rem !important; } .pr-md-5, .px-md-5 { padding-right: 3rem !important; } .pb-md-5, .py-md-5 { padding-bottom: 3rem !important; } .pl-md-5, .px-md-5 { padding-left: 3rem !important; } .m-md-auto { margin: auto !important; } .mt-md-auto, .my-md-auto { margin-top: auto !important; } .mr-md-auto, .mx-md-auto { margin-right: auto !important; } .mb-md-auto, .my-md-auto { margin-bottom: auto !important; } .ml-md-auto, .mx-md-auto { margin-left: auto !important; } } @media (min-width: 992px) { .m-lg-0 { margin: 0 !important; } .mt-lg-0, .my-lg-0 { margin-top: 0 !important; } .mr-lg-0, .mx-lg-0 { margin-right: 0 !important; } .mb-lg-0, .my-lg-0 { margin-bottom: 0 !important; } .ml-lg-0, .mx-lg-0 { margin-left: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .mt-lg-1, .my-lg-1 { margin-top: 0.25rem !important; } .mr-lg-1, .mx-lg-1 { margin-right: 0.25rem !important; } .mb-lg-1, .my-lg-1 { margin-bottom: 0.25rem !important; } .ml-lg-1, .mx-lg-1 { margin-left: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .mt-lg-2, .my-lg-2 { margin-top: 0.5rem !important; } .mr-lg-2, .mx-lg-2 { margin-right: 0.5rem !important; } .mb-lg-2, .my-lg-2 { margin-bottom: 0.5rem !important; } .ml-lg-2, .mx-lg-2 { margin-left: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .mt-lg-3, .my-lg-3 { margin-top: 1rem !important; } .mr-lg-3, .mx-lg-3 { margin-right: 1rem !important; } .mb-lg-3, .my-lg-3 { margin-bottom: 1rem !important; } .ml-lg-3, .mx-lg-3 { margin-left: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .mt-lg-4, .my-lg-4 { margin-top: 1.5rem !important; } .mr-lg-4, .mx-lg-4 { margin-right: 1.5rem !important; } .mb-lg-4, .my-lg-4 { margin-bottom: 1.5rem !important; } .ml-lg-4, .mx-lg-4 { margin-left: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .mt-lg-5, .my-lg-5 { margin-top: 3rem !important; } .mr-lg-5, .mx-lg-5 { margin-right: 3rem !important; } .mb-lg-5, .my-lg-5 { margin-bottom: 3rem !important; } .ml-lg-5, .mx-lg-5 { margin-left: 3rem !important; } .p-lg-0 { padding: 0 !important; } .pt-lg-0, .py-lg-0 { padding-top: 0 !important; } .pr-lg-0, .px-lg-0 { padding-right: 0 !important; } .pb-lg-0, .py-lg-0 { padding-bottom: 0 !important; } .pl-lg-0, .px-lg-0 { padding-left: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .pt-lg-1, .py-lg-1 { padding-top: 0.25rem !important; } .pr-lg-1, .px-lg-1 { padding-right: 0.25rem !important; } .pb-lg-1, .py-lg-1 { padding-bottom: 0.25rem !important; } .pl-lg-1, .px-lg-1 { padding-left: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .pt-lg-2, .py-lg-2 { padding-top: 0.5rem !important; } .pr-lg-2, .px-lg-2 { padding-right: 0.5rem !important; } .pb-lg-2, .py-lg-2 { padding-bottom: 0.5rem !important; } .pl-lg-2, .px-lg-2 { padding-left: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .pt-lg-3, .py-lg-3 { padding-top: 1rem !important; } .pr-lg-3, .px-lg-3 { padding-right: 1rem !important; } .pb-lg-3, .py-lg-3 { padding-bottom: 1rem !important; } .pl-lg-3, .px-lg-3 { padding-left: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .pt-lg-4, .py-lg-4 { padding-top: 1.5rem !important; } .pr-lg-4, .px-lg-4 { padding-right: 1.5rem !important; } .pb-lg-4, .py-lg-4 { padding-bottom: 1.5rem !important; } .pl-lg-4, .px-lg-4 { padding-left: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .pt-lg-5, .py-lg-5 { padding-top: 3rem !important; } .pr-lg-5, .px-lg-5 { padding-right: 3rem !important; } .pb-lg-5, .py-lg-5 { padding-bottom: 3rem !important; } .pl-lg-5, .px-lg-5 { padding-left: 3rem !important; } .m-lg-auto { margin: auto !important; } .mt-lg-auto, .my-lg-auto { margin-top: auto !important; } .mr-lg-auto, .mx-lg-auto { margin-right: auto !important; } .mb-lg-auto, .my-lg-auto { margin-bottom: auto !important; } .ml-lg-auto, .mx-lg-auto { margin-left: auto !important; } } @media (min-width: 1200px) { .m-xl-0 { margin: 0 !important; } .mt-xl-0, .my-xl-0 { margin-top: 0 !important; } .mr-xl-0, .mx-xl-0 { margin-right: 0 !important; } .mb-xl-0, .my-xl-0 { margin-bottom: 0 !important; } .ml-xl-0, .mx-xl-0 { margin-left: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .mt-xl-1, .my-xl-1 { margin-top: 0.25rem !important; } .mr-xl-1, .mx-xl-1 { margin-right: 0.25rem !important; } .mb-xl-1, .my-xl-1 { margin-bottom: 0.25rem !important; } .ml-xl-1, .mx-xl-1 { margin-left: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .mt-xl-2, .my-xl-2 { margin-top: 0.5rem !important; } .mr-xl-2, .mx-xl-2 { margin-right: 0.5rem !important; } .mb-xl-2, .my-xl-2 { margin-bottom: 0.5rem !important; } .ml-xl-2, .mx-xl-2 { margin-left: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .mt-xl-3, .my-xl-3 { margin-top: 1rem !important; } .mr-xl-3, .mx-xl-3 { margin-right: 1rem !important; } .mb-xl-3, .my-xl-3 { margin-bottom: 1rem !important; } .ml-xl-3, .mx-xl-3 { margin-left: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .mt-xl-4, .my-xl-4 { margin-top: 1.5rem !important; } .mr-xl-4, .mx-xl-4 { margin-right: 1.5rem !important; } .mb-xl-4, .my-xl-4 { margin-bottom: 1.5rem !important; } .ml-xl-4, .mx-xl-4 { margin-left: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .mt-xl-5, .my-xl-5 { margin-top: 3rem !important; } .mr-xl-5, .mx-xl-5 { margin-right: 3rem !important; } .mb-xl-5, .my-xl-5 { margin-bottom: 3rem !important; } .ml-xl-5, .mx-xl-5 { margin-left: 3rem !important; } .p-xl-0 { padding: 0 !important; } .pt-xl-0, .py-xl-0 { padding-top: 0 !important; } .pr-xl-0, .px-xl-0 { padding-right: 0 !important; } .pb-xl-0, .py-xl-0 { padding-bottom: 0 !important; } .pl-xl-0, .px-xl-0 { padding-left: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .pt-xl-1, .py-xl-1 { padding-top: 0.25rem !important; } .pr-xl-1, .px-xl-1 { padding-right: 0.25rem !important; } .pb-xl-1, .py-xl-1 { padding-bottom: 0.25rem !important; } .pl-xl-1, .px-xl-1 { padding-left: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .pt-xl-2, .py-xl-2 { padding-top: 0.5rem !important; } .pr-xl-2, .px-xl-2 { padding-right: 0.5rem !important; } .pb-xl-2, .py-xl-2 { padding-bottom: 0.5rem !important; } .pl-xl-2, .px-xl-2 { padding-left: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .pt-xl-3, .py-xl-3 { padding-top: 1rem !important; } .pr-xl-3, .px-xl-3 { padding-right: 1rem !important; } .pb-xl-3, .py-xl-3 { padding-bottom: 1rem !important; } .pl-xl-3, .px-xl-3 { padding-left: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .pt-xl-4, .py-xl-4 { padding-top: 1.5rem !important; } .pr-xl-4, .px-xl-4 { padding-right: 1.5rem !important; } .pb-xl-4, .py-xl-4 { padding-bottom: 1.5rem !important; } .pl-xl-4, .px-xl-4 { padding-left: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .pt-xl-5, .py-xl-5 { padding-top: 3rem !important; } .pr-xl-5, .px-xl-5 { padding-right: 3rem !important; } .pb-xl-5, .py-xl-5 { padding-bottom: 3rem !important; } .pl-xl-5, .px-xl-5 { padding-left: 3rem !important; } .m-xl-auto { margin: auto !important; } .mt-xl-auto, .my-xl-auto { margin-top: auto !important; } .mr-xl-auto, .mx-xl-auto { margin-right: auto !important; } .mb-xl-auto, .my-xl-auto { margin-bottom: auto !important; } .ml-xl-auto, .mx-xl-auto { margin-left: auto !important; } } .text-justify { text-align: justify !important; } .text-nowrap { white-space: nowrap !important; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .text-center { text-align: center !important; } @media (min-width: 576px) { .text-sm-left { text-align: left !important; } .text-sm-right { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .text-md-left { text-align: left !important; } .text-md-right { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .text-lg-left { text-align: left !important; } .text-lg-right { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .text-xl-left { text-align: left !important; } .text-xl-right { text-align: right !important; } .text-xl-center { text-align: center !important; } } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .font-weight-light { font-weight: 300 !important; } .font-weight-normal { font-weight: 400 !important; } .font-weight-bold { font-weight: 700 !important; } .font-italic { font-style: italic !important; } .text-white { color: #fff !important; } .text-primary { color: #007bff !important; } a.text-primary:focus, a.text-primary:hover { color: #0062cc !important; } .text-secondary { color: #868e96 !important; } a.text-secondary:focus, a.text-secondary:hover { color: #6c757d !important; } .text-success { color: #28a745 !important; } a.text-success:focus, a.text-success:hover { color: #1e7e34 !important; } .text-info { color: #17a2b8 !important; } a.text-info:focus, a.text-info:hover { color: #117a8b !important; } .text-warning { color: #ffc107 !important; } a.text-warning:focus, a.text-warning:hover { color: #d39e00 !important; } .text-danger { color: #dc3545 !important; } a.text-danger:focus, a.text-danger:hover { color: #bd2130 !important; } .text-light { color: #f8f9fa !important; } a.text-light:focus, a.text-light:hover { color: #dae0e5 !important; } .text-dark { color: #343a40 !important; } a.text-dark:focus, a.text-dark:hover { color: #1d2124 !important; } .text-muted { color: #868e96 !important; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media print { *, *::before, *::after { text-shadow: none !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } abbr[title]::after { content: " (" attr(title) ")"; } pre { white-space: pre-wrap !important; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } .navbar { display: none; } .badge { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/css/justified-nav.css ================================================ body { padding-top: 20px; } .footer { padding-top: 40px; padding-bottom: 40px; margin-top: 40px; border-top: 1px solid #eee; } /* Main marketing message and sign up button */ .jumbotron { text-align: center; background-color: transparent; } .jumbotron .btn { padding: 14px 24px; font-size: 21px; } .navbar { background-image: linear-gradient(to bottom, #f7f7f7 0%, #eee 100%); border: 1px solid #e5e5e5; } @media (min-width: 768px) { .navbar-nav { display: -ms-flexbox; display: -webkit-box; display: flex; } .navbar-nav .nav-item { -ms-flex: 1 0 auto; -webkit-box-flex: 1; flex: 1 0 auto; } } /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { /* Remove the padding we set earlier */ .masthead, .marketing, .footer { padding-right: 0; padding-left: 0; } } ================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/index.html ================================================ Justified Nav Template for Bootstrap

Project name

Marketing stuff!

Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet.

Get started today

Heading

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

View details »

Heading

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

View details »

Heading

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.

View details »

© Company 2017

================================================ FILE: packages/browser-sync/test/fixtures/bootstrap/js/bootstrap.bundle.js ================================================ /*! * Bootstrap v4.0.0-beta.3 (https://getbootstrap.com) * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) : typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) : (factory((global.bootstrap = {}),global.jQuery)); }(this, (function (exports,$) { 'use strict'; $ = $ && $.hasOwnProperty('default') ? $['default'] : $; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Util = function ($$$1) { /** * ------------------------------------------------------------------------ * Private TransitionEnd Helpers * ------------------------------------------------------------------------ */ var transition = false; var MAX_UID = 1000000; // shoutout AngusCroll (https://goo.gl/pxwQGp) function toType(obj) { return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); } function getSpecialTransitionEndEvent() { return { bindType: transition.end, delegateType: transition.end, handle: function handle(event) { if ($$$1(event.target).is(this)) { return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params } return undefined; // eslint-disable-line no-undefined } }; } function transitionEndTest() { if (window.QUnit) { return false; } return { end: 'transitionend' }; } function transitionEndEmulator(duration) { var _this = this; var called = false; $$$1(this).one(Util.TRANSITION_END, function () { called = true; }); setTimeout(function () { if (!called) { Util.triggerTransitionEnd(_this); } }, duration); return this; } function setTransitionEndSupport() { transition = transitionEndTest(); $$$1.fn.emulateTransitionEnd = transitionEndEmulator; if (Util.supportsTransitionEnd()) { $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); } } function escapeId(selector) { // we escape IDs in case of special selectors (selector = '#myId:something') // $.escapeSelector does not exist in jQuery < 3 selector = typeof $$$1.escapeSelector === 'function' ? $$$1.escapeSelector(selector).substr(1) : selector.replace(/(:|\.|\[|\]|,|=|@)/g, '\\$1'); return selector; } /** * -------------------------------------------------------------------------- * Public Util Api * -------------------------------------------------------------------------- */ var Util = { TRANSITION_END: 'bsTransitionEnd', getUID: function getUID(prefix) { do { // eslint-disable-next-line no-bitwise prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here } while (document.getElementById(prefix)); return prefix; }, getSelectorFromElement: function getSelectorFromElement(element) { var selector = element.getAttribute('data-target'); if (!selector || selector === '#') { selector = element.getAttribute('href') || ''; } // if it's an ID if (selector.charAt(0) === '#') { selector = escapeId(selector); } try { var $selector = $$$1(document).find(selector); return $selector.length > 0 ? selector : null; } catch (error) { return null; } }, reflow: function reflow(element) { return element.offsetHeight; }, triggerTransitionEnd: function triggerTransitionEnd(element) { $$$1(element).trigger(transition.end); }, supportsTransitionEnd: function supportsTransitionEnd() { return Boolean(transition); }, isElement: function isElement(obj) { return (obj[0] || obj).nodeType; }, typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { for (var property in configTypes) { if (Object.prototype.hasOwnProperty.call(configTypes, property)) { var expectedTypes = configTypes[property]; var value = config[property]; var valueType = value && Util.isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); } } } } }; setTransitionEndSupport(); return Util; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Alert = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'alert'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.alert'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var TRANSITION_DURATION = 150; var Selector = { DISMISS: '[data-dismiss="alert"]' }; var Event = { CLOSE: "close" + EVENT_KEY, CLOSED: "closed" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { ALERT: 'alert', FADE: 'fade', SHOW: 'show' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Alert = /*#__PURE__*/ function () { function Alert(element) { this._element = element; } // getters var _proto = Alert.prototype; // public _proto.close = function close(element) { element = element || this._element; var rootElement = this._getRootElement(element); var customEvent = this._triggerCloseEvent(rootElement); if (customEvent.isDefaultPrevented()) { return; } this._removeElement(rootElement); }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); this._element = null; }; // private _proto._getRootElement = function _getRootElement(element) { var selector = Util.getSelectorFromElement(element); var parent = false; if (selector) { parent = $$$1(selector)[0]; } if (!parent) { parent = $$$1(element).closest("." + ClassName.ALERT)[0]; } return parent; }; _proto._triggerCloseEvent = function _triggerCloseEvent(element) { var closeEvent = $$$1.Event(Event.CLOSE); $$$1(element).trigger(closeEvent); return closeEvent; }; _proto._removeElement = function _removeElement(element) { var _this = this; $$$1(element).removeClass(ClassName.SHOW); if (!Util.supportsTransitionEnd() || !$$$1(element).hasClass(ClassName.FADE)) { this._destroyElement(element); return; } $$$1(element).one(Util.TRANSITION_END, function (event) { return _this._destroyElement(element, event); }).emulateTransitionEnd(TRANSITION_DURATION); }; _proto._destroyElement = function _destroyElement(element) { $$$1(element).detach().trigger(Event.CLOSED).remove(); }; // static Alert._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var $element = $$$1(this); var data = $element.data(DATA_KEY); if (!data) { data = new Alert(this); $element.data(DATA_KEY, data); } if (config === 'close') { data[config](this); } }); }; Alert._handleDismiss = function _handleDismiss(alertInstance) { return function (event) { if (event) { event.preventDefault(); } alertInstance.close(this); }; }; _createClass(Alert, null, [{ key: "VERSION", get: function get() { return VERSION; } }]); return Alert; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Alert._jQueryInterface; $$$1.fn[NAME].Constructor = Alert; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Alert._jQueryInterface; }; return Alert; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Button = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'button'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.button'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var ClassName = { ACTIVE: 'active', BUTTON: 'btn', FOCUS: 'focus' }; var Selector = { DATA_TOGGLE_CARROT: '[data-toggle^="button"]', DATA_TOGGLE: '[data-toggle="buttons"]', INPUT: 'input', ACTIVE: '.active', BUTTON: '.btn' }; var Event = { CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY) /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Button = /*#__PURE__*/ function () { function Button(element) { this._element = element; } // getters var _proto = Button.prototype; // public _proto.toggle = function toggle() { var triggerChangeEvent = true; var addAriaPressed = true; var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0]; if (rootElement) { var input = $$$1(this._element).find(Selector.INPUT)[0]; if (input) { if (input.type === 'radio') { if (input.checked && $$$1(this._element).hasClass(ClassName.ACTIVE)) { triggerChangeEvent = false; } else { var activeElement = $$$1(rootElement).find(Selector.ACTIVE)[0]; if (activeElement) { $$$1(activeElement).removeClass(ClassName.ACTIVE); } } } if (triggerChangeEvent) { if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { return; } input.checked = !$$$1(this._element).hasClass(ClassName.ACTIVE); $$$1(input).trigger('change'); } input.focus(); addAriaPressed = false; } } if (addAriaPressed) { this._element.setAttribute('aria-pressed', !$$$1(this._element).hasClass(ClassName.ACTIVE)); } if (triggerChangeEvent) { $$$1(this._element).toggleClass(ClassName.ACTIVE); } }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); this._element = null; }; // static Button._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); if (!data) { data = new Button(this); $$$1(this).data(DATA_KEY, data); } if (config === 'toggle') { data[config](); } }); }; _createClass(Button, null, [{ key: "VERSION", get: function get() { return VERSION; } }]); return Button; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { event.preventDefault(); var button = event.target; if (!$$$1(button).hasClass(ClassName.BUTTON)) { button = $$$1(button).closest(Selector.BUTTON); } Button._jQueryInterface.call($$$1(button), 'toggle'); }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { var button = $$$1(event.target).closest(Selector.BUTTON)[0]; $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Button._jQueryInterface; $$$1.fn[NAME].Constructor = Button; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Button._jQueryInterface; }; return Button; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Carousel = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'carousel'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.carousel'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var TRANSITION_DURATION = 600; var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch var Default = { interval: 5000, keyboard: true, slide: false, pause: 'hover', wrap: true }; var DefaultType = { interval: '(number|boolean)', keyboard: 'boolean', slide: '(boolean|string)', pause: '(string|boolean)', wrap: 'boolean' }; var Direction = { NEXT: 'next', PREV: 'prev', LEFT: 'left', RIGHT: 'right' }; var Event = { SLIDE: "slide" + EVENT_KEY, SLID: "slid" + EVENT_KEY, KEYDOWN: "keydown" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY, TOUCHEND: "touchend" + EVENT_KEY, LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { CAROUSEL: 'carousel', ACTIVE: 'active', SLIDE: 'slide', RIGHT: 'carousel-item-right', LEFT: 'carousel-item-left', NEXT: 'carousel-item-next', PREV: 'carousel-item-prev', ITEM: 'carousel-item' }; var Selector = { ACTIVE: '.active', ACTIVE_ITEM: '.active.carousel-item', ITEM: '.carousel-item', NEXT_PREV: '.carousel-item-next, .carousel-item-prev', INDICATORS: '.carousel-indicators', DATA_SLIDE: '[data-slide], [data-slide-to]', DATA_RIDE: '[data-ride="carousel"]' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Carousel = /*#__PURE__*/ function () { function Carousel(element, config) { this._items = null; this._interval = null; this._activeElement = null; this._isPaused = false; this._isSliding = false; this.touchTimeout = null; this._config = this._getConfig(config); this._element = $$$1(element)[0]; this._indicatorsElement = $$$1(this._element).find(Selector.INDICATORS)[0]; this._addEventListeners(); } // getters var _proto = Carousel.prototype; // public _proto.next = function next() { if (!this._isSliding) { this._slide(Direction.NEXT); } }; _proto.nextWhenVisible = function nextWhenVisible() { // Don't call next when the page isn't visible // or the carousel or its parent isn't visible if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') { this.next(); } }; _proto.prev = function prev() { if (!this._isSliding) { this._slide(Direction.PREV); } }; _proto.pause = function pause(event) { if (!event) { this._isPaused = true; } if ($$$1(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) { Util.triggerTransitionEnd(this._element); this.cycle(true); } clearInterval(this._interval); this._interval = null; }; _proto.cycle = function cycle(event) { if (!event) { this._isPaused = false; } if (this._interval) { clearInterval(this._interval); this._interval = null; } if (this._config.interval && !this._isPaused) { this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); } }; _proto.to = function to(index) { var _this = this; this._activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0]; var activeIndex = this._getItemIndex(this._activeElement); if (index > this._items.length - 1 || index < 0) { return; } if (this._isSliding) { $$$1(this._element).one(Event.SLID, function () { return _this.to(index); }); return; } if (activeIndex === index) { this.pause(); this.cycle(); return; } var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; this._slide(direction, this._items[index]); }; _proto.dispose = function dispose() { $$$1(this._element).off(EVENT_KEY); $$$1.removeData(this._element, DATA_KEY); this._items = null; this._config = null; this._element = null; this._interval = null; this._isPaused = null; this._isSliding = null; this._activeElement = null; this._indicatorsElement = null; }; // private _proto._getConfig = function _getConfig(config) { config = _extends({}, Default, config); Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._addEventListeners = function _addEventListeners() { var _this2 = this; if (this._config.keyboard) { $$$1(this._element).on(Event.KEYDOWN, function (event) { return _this2._keydown(event); }); } if (this._config.pause === 'hover') { $$$1(this._element).on(Event.MOUSEENTER, function (event) { return _this2.pause(event); }).on(Event.MOUSELEAVE, function (event) { return _this2.cycle(event); }); if ('ontouchstart' in document.documentElement) { // if it's a touch-enabled device, mouseenter/leave are fired as // part of the mouse compatibility events on first tap - the carousel // would stop cycling until user tapped out of it; // here, we listen for touchend, explicitly pause the carousel // (as if it's the second time we tap on it, mouseenter compat event // is NOT fired) and after a timeout (to allow for mouse compatibility // events to fire) we explicitly restart cycling $$$1(this._element).on(Event.TOUCHEND, function () { _this2.pause(); if (_this2.touchTimeout) { clearTimeout(_this2.touchTimeout); } _this2.touchTimeout = setTimeout(function (event) { return _this2.cycle(event); }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval); }); } } }; _proto._keydown = function _keydown(event) { if (/input|textarea/i.test(event.target.tagName)) { return; } switch (event.which) { case ARROW_LEFT_KEYCODE: event.preventDefault(); this.prev(); break; case ARROW_RIGHT_KEYCODE: event.preventDefault(); this.next(); break; default: return; } }; _proto._getItemIndex = function _getItemIndex(element) { this._items = $$$1.makeArray($$$1(element).parent().find(Selector.ITEM)); return this._items.indexOf(element); }; _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { var isNextDirection = direction === Direction.NEXT; var isPrevDirection = direction === Direction.PREV; var activeIndex = this._getItemIndex(activeElement); var lastItemIndex = this._items.length - 1; var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; if (isGoingToWrap && !this._config.wrap) { return activeElement; } var delta = direction === Direction.PREV ? -1 : 1; var itemIndex = (activeIndex + delta) % this._items.length; return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; }; _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { var targetIndex = this._getItemIndex(relatedTarget); var fromIndex = this._getItemIndex($$$1(this._element).find(Selector.ACTIVE_ITEM)[0]); var slideEvent = $$$1.Event(Event.SLIDE, { relatedTarget: relatedTarget, direction: eventDirectionName, from: fromIndex, to: targetIndex }); $$$1(this._element).trigger(slideEvent); return slideEvent; }; _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { if (this._indicatorsElement) { $$$1(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE); var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; if (nextIndicator) { $$$1(nextIndicator).addClass(ClassName.ACTIVE); } } }; _proto._slide = function _slide(direction, element) { var _this3 = this; var activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0]; var activeElementIndex = this._getItemIndex(activeElement); var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); var nextElementIndex = this._getItemIndex(nextElement); var isCycling = Boolean(this._interval); var directionalClassName; var orderClassName; var eventDirectionName; if (direction === Direction.NEXT) { directionalClassName = ClassName.LEFT; orderClassName = ClassName.NEXT; eventDirectionName = Direction.LEFT; } else { directionalClassName = ClassName.RIGHT; orderClassName = ClassName.PREV; eventDirectionName = Direction.RIGHT; } if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) { this._isSliding = false; return; } var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); if (slideEvent.isDefaultPrevented()) { return; } if (!activeElement || !nextElement) { // some weirdness is happening, so we bail return; } this._isSliding = true; if (isCycling) { this.pause(); } this._setActiveIndicatorElement(nextElement); var slidEvent = $$$1.Event(Event.SLID, { relatedTarget: nextElement, direction: eventDirectionName, from: activeElementIndex, to: nextElementIndex }); if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.SLIDE)) { $$$1(nextElement).addClass(orderClassName); Util.reflow(nextElement); $$$1(activeElement).addClass(directionalClassName); $$$1(nextElement).addClass(directionalClassName); $$$1(activeElement).one(Util.TRANSITION_END, function () { $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); _this3._isSliding = false; setTimeout(function () { return $$$1(_this3._element).trigger(slidEvent); }, 0); }).emulateTransitionEnd(TRANSITION_DURATION); } else { $$$1(activeElement).removeClass(ClassName.ACTIVE); $$$1(nextElement).addClass(ClassName.ACTIVE); this._isSliding = false; $$$1(this._element).trigger(slidEvent); } if (isCycling) { this.cycle(); } }; // static Carousel._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); var _config = _extends({}, Default, $$$1(this).data()); if (typeof config === 'object') { _config = _extends({}, _config, config); } var action = typeof config === 'string' ? config : _config.slide; if (!data) { data = new Carousel(this, _config); $$$1(this).data(DATA_KEY, data); } if (typeof config === 'number') { data.to(config); } else if (typeof action === 'string') { if (typeof data[action] === 'undefined') { throw new Error("No method named \"" + action + "\""); } data[action](); } else if (_config.interval) { data.pause(); data.cycle(); } }); }; Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { var selector = Util.getSelectorFromElement(this); if (!selector) { return; } var target = $$$1(selector)[0]; if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) { return; } var config = _extends({}, $$$1(target).data(), $$$1(this).data()); var slideIndex = this.getAttribute('data-slide-to'); if (slideIndex) { config.interval = false; } Carousel._jQueryInterface.call($$$1(target), config); if (slideIndex) { $$$1(target).data(DATA_KEY).to(slideIndex); } event.preventDefault(); }; _createClass(Carousel, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Carousel; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); $$$1(window).on(Event.LOAD_DATA_API, function () { $$$1(Selector.DATA_RIDE).each(function () { var $carousel = $$$1(this); Carousel._jQueryInterface.call($carousel, $carousel.data()); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Carousel._jQueryInterface; $$$1.fn[NAME].Constructor = Carousel; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Carousel._jQueryInterface; }; return Carousel; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Collapse = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'collapse'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.collapse'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var TRANSITION_DURATION = 600; var Default = { toggle: true, parent: '' }; var DefaultType = { toggle: 'boolean', parent: '(string|element)' }; var Event = { SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { SHOW: 'show', COLLAPSE: 'collapse', COLLAPSING: 'collapsing', COLLAPSED: 'collapsed' }; var Dimension = { WIDTH: 'width', HEIGHT: 'height' }; var Selector = { ACTIVES: '.show, .collapsing', DATA_TOGGLE: '[data-toggle="collapse"]' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Collapse = /*#__PURE__*/ function () { function Collapse(element, config) { this._isTransitioning = false; this._element = element; this._config = this._getConfig(config); this._triggerArray = $$$1.makeArray($$$1("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); var tabToggles = $$$1(Selector.DATA_TOGGLE); for (var i = 0; i < tabToggles.length; i++) { var elem = tabToggles[i]; var selector = Util.getSelectorFromElement(elem); if (selector !== null && $$$1(selector).filter(element).length > 0) { this._triggerArray.push(elem); } } this._parent = this._config.parent ? this._getParent() : null; if (!this._config.parent) { this._addAriaAndCollapsedClass(this._element, this._triggerArray); } if (this._config.toggle) { this.toggle(); } } // getters var _proto = Collapse.prototype; // public _proto.toggle = function toggle() { if ($$$1(this._element).hasClass(ClassName.SHOW)) { this.hide(); } else { this.show(); } }; _proto.show = function show() { var _this = this; if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) { return; } var actives; var activesData; if (this._parent) { actives = $$$1.makeArray($$$1(this._parent).children().children(Selector.ACTIVES)); if (!actives.length) { actives = null; } } if (actives) { activesData = $$$1(actives).data(DATA_KEY); if (activesData && activesData._isTransitioning) { return; } } var startEvent = $$$1.Event(Event.SHOW); $$$1(this._element).trigger(startEvent); if (startEvent.isDefaultPrevented()) { return; } if (actives) { Collapse._jQueryInterface.call($$$1(actives), 'hide'); if (!activesData) { $$$1(actives).data(DATA_KEY, null); } } var dimension = this._getDimension(); $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); this._element.style[dimension] = 0; if (this._triggerArray.length) { $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); } this.setTransitioning(true); var complete = function complete() { $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); _this._element.style[dimension] = ''; _this.setTransitioning(false); $$$1(_this._element).trigger(Event.SHOWN); }; if (!Util.supportsTransitionEnd()) { complete(); return; } var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); var scrollSize = "scroll" + capitalizedDimension; $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); this._element.style[dimension] = this._element[scrollSize] + "px"; }; _proto.hide = function hide() { var _this2 = this; if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) { return; } var startEvent = $$$1.Event(Event.HIDE); $$$1(this._element).trigger(startEvent); if (startEvent.isDefaultPrevented()) { return; } var dimension = this._getDimension(); this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; Util.reflow(this._element); $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); if (this._triggerArray.length) { for (var i = 0; i < this._triggerArray.length; i++) { var trigger = this._triggerArray[i]; var selector = Util.getSelectorFromElement(trigger); if (selector !== null) { var $elem = $$$1(selector); if (!$elem.hasClass(ClassName.SHOW)) { $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); } } } } this.setTransitioning(true); var complete = function complete() { _this2.setTransitioning(false); $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); }; this._element.style[dimension] = ''; if (!Util.supportsTransitionEnd()) { complete(); return; } $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); }; _proto.setTransitioning = function setTransitioning(isTransitioning) { this._isTransitioning = isTransitioning; }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); this._config = null; this._parent = null; this._element = null; this._triggerArray = null; this._isTransitioning = null; }; // private _proto._getConfig = function _getConfig(config) { config = _extends({}, Default, config); config.toggle = Boolean(config.toggle); // coerce string values Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._getDimension = function _getDimension() { var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH); return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; }; _proto._getParent = function _getParent() { var _this3 = this; var parent = null; if (Util.isElement(this._config.parent)) { parent = this._config.parent; // it's a jQuery object if (typeof this._config.parent.jquery !== 'undefined') { parent = this._config.parent[0]; } } else { parent = $$$1(this._config.parent)[0]; } var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; $$$1(parent).find(selector).each(function (i, element) { _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); }); return parent; }; _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { if (element) { var isOpen = $$$1(element).hasClass(ClassName.SHOW); if (triggerArray.length) { $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); } } }; // static Collapse._getTargetFromElement = function _getTargetFromElement(element) { var selector = Util.getSelectorFromElement(element); return selector ? $$$1(selector)[0] : null; }; Collapse._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var $this = $$$1(this); var data = $this.data(DATA_KEY); var _config = _extends({}, Default, $this.data(), typeof config === 'object' && config); if (!data && _config.toggle && /show|hide/.test(config)) { _config.toggle = false; } if (!data) { data = new Collapse(this, _config); $this.data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; _createClass(Collapse, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Collapse; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.currentTarget.tagName === 'A') { event.preventDefault(); } var $trigger = $$$1(this); var selector = Util.getSelectorFromElement(this); $$$1(selector).each(function () { var $target = $$$1(this); var data = $target.data(DATA_KEY); var config = data ? 'toggle' : $trigger.data(); Collapse._jQueryInterface.call($target, config); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Collapse._jQueryInterface; $$$1.fn[NAME].Constructor = Collapse; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Collapse._jQueryInterface; }; return Collapse; }($); /**! * @fileOverview Kickass library to create and place poppers near their reference elements. * @version 1.12.9 * @license * Copyright (c) 2016 Federico Zivolo and contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; var timeoutDuration = 0; for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { timeoutDuration = 1; break; } } function microtaskDebounce(fn) { var called = false; return function () { if (called) { return; } called = true; window.Promise.resolve().then(function () { called = false; fn(); }); }; } function taskDebounce(fn) { var scheduled = false; return function () { if (!scheduled) { scheduled = true; setTimeout(function () { scheduled = false; fn(); }, timeoutDuration); } }; } var supportsMicroTasks = isBrowser && window.Promise; /** * Create a debounced version of a method, that's asynchronously deferred * but called in the minimum time possible. * * @method * @memberof Popper.Utils * @argument {Function} fn * @returns {Function} */ var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce; /** * Check if the given variable is a function * @method * @memberof Popper.Utils * @argument {Any} functionToCheck - variable to check * @returns {Boolean} answer to: is a function? */ function isFunction(functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; } /** * Get CSS computed property of the given element * @method * @memberof Popper.Utils * @argument {Eement} element * @argument {String} property */ function getStyleComputedProperty(element, property) { if (element.nodeType !== 1) { return []; } // NOTE: 1 DOM access here var css = getComputedStyle(element, null); return property ? css[property] : css; } /** * Returns the parentNode or the host of the element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} parent */ function getParentNode(element) { if (element.nodeName === 'HTML') { return element; } return element.parentNode || element.host; } /** * Returns the scrolling parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} scroll parent */ function getScrollParent(element) { // Return body, `getScroll` will take care to get the correct `scrollTop` from it if (!element) { return document.body; } switch (element.nodeName) { case 'HTML': case 'BODY': return element.ownerDocument.body; case '#document': return element.body; } // Firefox want us to check `-x` and `-y` variations as well var _getStyleComputedProp = getStyleComputedProperty(element), overflow = _getStyleComputedProp.overflow, overflowX = _getStyleComputedProp.overflowX, overflowY = _getStyleComputedProp.overflowY; if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) { return element; } return getScrollParent(getParentNode(element)); } /** * Returns the offset parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} offset parent */ function getOffsetParent(element) { // NOTE: 1 DOM access here var offsetParent = element && element.offsetParent; var nodeName = offsetParent && offsetParent.nodeName; if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { if (element) { return element.ownerDocument.documentElement; } return document.documentElement; } // .offsetParent will return the closest TD or TABLE in case // no offsetParent is present, I hate this job... if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { return getOffsetParent(offsetParent); } return offsetParent; } function isOffsetContainer(element) { var nodeName = element.nodeName; if (nodeName === 'BODY') { return false; } return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; } /** * Finds the root node (document, shadowDOM root) of the given element * @method * @memberof Popper.Utils * @argument {Element} node * @returns {Element} root node */ function getRoot(node) { if (node.parentNode !== null) { return getRoot(node.parentNode); } return node; } /** * Finds the offset parent common to the two provided nodes * @method * @memberof Popper.Utils * @argument {Element} element1 * @argument {Element} element2 * @returns {Element} common offset parent */ function findCommonOffsetParent(element1, element2) { // This check is needed to avoid errors in case one of the elements isn't defined for any reason if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { return document.documentElement; } // Here we make sure to give as "start" the element that comes first in the DOM var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; var start = order ? element1 : element2; var end = order ? element2 : element1; // Get common ancestor container var range = document.createRange(); range.setStart(start, 0); range.setEnd(end, 0); var commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { if (isOffsetContainer(commonAncestorContainer)) { return commonAncestorContainer; } return getOffsetParent(commonAncestorContainer); } // one of the nodes is inside shadowDOM, find which one var element1root = getRoot(element1); if (element1root.host) { return findCommonOffsetParent(element1root.host, element2); } else { return findCommonOffsetParent(element1, getRoot(element2).host); } } /** * Gets the scroll value of the given element in the given side (top and left) * @method * @memberof Popper.Utils * @argument {Element} element * @argument {String} side `top` or `left` * @returns {number} amount of scrolled pixels */ function getScroll(element) { var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { var html = element.ownerDocument.documentElement; var scrollingElement = element.ownerDocument.scrollingElement || html; return scrollingElement[upperSide]; } return element[upperSide]; } /* * Sum or subtract the element scroll values (left and top) from a given rect object * @method * @memberof Popper.Utils * @param {Object} rect - Rect object you want to change * @param {HTMLElement} element - The element from the function reads the scroll values * @param {Boolean} subtract - set to true if you want to subtract the scroll values * @return {Object} rect - The modifier rect object */ function includeScroll(rect, element) { var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); var modifier = subtract ? -1 : 1; rect.top += scrollTop * modifier; rect.bottom += scrollTop * modifier; rect.left += scrollLeft * modifier; rect.right += scrollLeft * modifier; return rect; } /* * Helper to detect borders of a given element * @method * @memberof Popper.Utils * @param {CSSStyleDeclaration} styles * Result of `getStyleComputedProperty` on the given element * @param {String} axis - `x` or `y` * @return {number} borders - The borders size of the given axis */ function getBordersSize(styles, axis) { var sideA = axis === 'x' ? 'Left' : 'Top'; var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10); } /** * Tells if you are running Internet Explorer 10 * @method * @memberof Popper.Utils * @returns {Boolean} isIE10 */ var isIE10 = undefined; var isIE10$1 = function () { if (isIE10 === undefined) { isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1; } return isIE10; }; function getSize(axis, body, html, computedStyle) { return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0); } function getWindowSizes() { var body = document.body; var html = document.documentElement; var computedStyle = isIE10$1() && getComputedStyle(html); return { height: getSize('Height', body, html, computedStyle), width: getSize('Width', body, html, computedStyle) }; } var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends$1 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** * Given element offsets, generate an output similar to getBoundingClientRect * @method * @memberof Popper.Utils * @argument {Object} offsets * @returns {Object} ClientRect like output */ function getClientRect(offsets) { return _extends$1({}, offsets, { right: offsets.left + offsets.width, bottom: offsets.top + offsets.height }); } /** * Get bounding client rect of given element * @method * @memberof Popper.Utils * @param {HTMLElement} element * @return {Object} client rect */ function getBoundingClientRect(element) { var rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't // considered in DOM in some circumstances... // This isn't reproducible in IE10 compatibility mode of IE11 if (isIE10$1()) { try { rect = element.getBoundingClientRect(); var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); rect.top += scrollTop; rect.left += scrollLeft; rect.bottom += scrollTop; rect.right += scrollLeft; } catch (err) {} } else { rect = element.getBoundingClientRect(); } var result = { left: rect.left, top: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top }; // subtract scrollbar size from sizes var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; var width = sizes.width || element.clientWidth || result.right - result.left; var height = sizes.height || element.clientHeight || result.bottom - result.top; var horizScrollbar = element.offsetWidth - width; var vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border` // we make this check conditional for performance reasons if (horizScrollbar || vertScrollbar) { var styles = getStyleComputedProperty(element); horizScrollbar -= getBordersSize(styles, 'x'); vertScrollbar -= getBordersSize(styles, 'y'); result.width -= horizScrollbar; result.height -= vertScrollbar; } return getClientRect(result); } function getOffsetRectRelativeToArbitraryNode(children, parent) { var isIE10 = isIE10$1(); var isHTML = parent.nodeName === 'HTML'; var childrenRect = getBoundingClientRect(children); var parentRect = getBoundingClientRect(parent); var scrollParent = getScrollParent(children); var styles = getStyleComputedProperty(parent); var borderTopWidth = parseFloat(styles.borderTopWidth, 10); var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10); var offsets = getClientRect({ top: childrenRect.top - parentRect.top - borderTopWidth, left: childrenRect.left - parentRect.left - borderLeftWidth, width: childrenRect.width, height: childrenRect.height }); offsets.marginTop = 0; offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent // we do this only on HTML because it's the only element that behaves // differently when margins are applied to it. The margins are included in // the box of the documentElement, in the other cases not. if (!isIE10 && isHTML) { var marginTop = parseFloat(styles.marginTop, 10); var marginLeft = parseFloat(styles.marginLeft, 10); offsets.top -= borderTopWidth - marginTop; offsets.bottom -= borderTopWidth - marginTop; offsets.left -= borderLeftWidth - marginLeft; offsets.right -= borderLeftWidth - marginLeft; // Attach marginTop and marginLeft because in some circumstances we may need them offsets.marginTop = marginTop; offsets.marginLeft = marginLeft; } if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { offsets = includeScroll(offsets, parent); } return offsets; } function getViewportOffsetRectRelativeToArtbitraryNode(element) { var html = element.ownerDocument.documentElement; var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); var width = Math.max(html.clientWidth, window.innerWidth || 0); var height = Math.max(html.clientHeight, window.innerHeight || 0); var scrollTop = getScroll(html); var scrollLeft = getScroll(html, 'left'); var offset = { top: scrollTop - relativeOffset.top + relativeOffset.marginTop, left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, width: width, height: height }; return getClientRect(offset); } /** * Check if the given element is fixed or is inside a fixed parent * @method * @memberof Popper.Utils * @argument {Element} element * @argument {Element} customContainer * @returns {Boolean} answer to "isFixed?" */ function isFixed(element) { var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { return false; } if (getStyleComputedProperty(element, 'position') === 'fixed') { return true; } return isFixed(getParentNode(element)); } /** * Computed the boundaries limits and return them * @method * @memberof Popper.Utils * @param {HTMLElement} popper * @param {HTMLElement} reference * @param {number} padding * @param {HTMLElement} boundariesElement - Element used to define the boundaries * @returns {Object} Coordinates of the boundaries */ function getBoundaries(popper, reference, padding, boundariesElement) { // NOTE: 1 DOM access here var boundaries = { top: 0, left: 0 }; var offsetParent = findCommonOffsetParent(popper, reference); // Handle viewport case if (boundariesElement === 'viewport') { boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent); } else { // Handle other cases based on DOM element used as boundaries var boundariesNode = void 0; if (boundariesElement === 'scrollParent') { boundariesNode = getScrollParent(getParentNode(reference)); if (boundariesNode.nodeName === 'BODY') { boundariesNode = popper.ownerDocument.documentElement; } } else if (boundariesElement === 'window') { boundariesNode = popper.ownerDocument.documentElement; } else { boundariesNode = boundariesElement; } var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent); // In case of HTML, we need a different computation if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { var _getWindowSizes = getWindowSizes(), height = _getWindowSizes.height, width = _getWindowSizes.width; boundaries.top += offsets.top - offsets.marginTop; boundaries.bottom = height + offsets.top; boundaries.left += offsets.left - offsets.marginLeft; boundaries.right = width + offsets.left; } else { // for all the other DOM elements, this one is good boundaries = offsets; } } // Add paddings boundaries.left += padding; boundaries.top += padding; boundaries.right -= padding; boundaries.bottom -= padding; return boundaries; } function getArea(_ref) { var width = _ref.width, height = _ref.height; return width * height; } /** * Utility used to transform the `auto` placement to the placement with more * available space. * @method * @memberof Popper.Utils * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; if (placement.indexOf('auto') === -1) { return placement; } var boundaries = getBoundaries(popper, reference, padding, boundariesElement); var rects = { top: { width: boundaries.width, height: refRect.top - boundaries.top }, right: { width: boundaries.right - refRect.right, height: boundaries.height }, bottom: { width: boundaries.width, height: boundaries.bottom - refRect.bottom }, left: { width: refRect.left - boundaries.left, height: boundaries.height } }; var sortedAreas = Object.keys(rects).map(function (key) { return _extends$1({ key: key }, rects[key], { area: getArea(rects[key]) }); }).sort(function (a, b) { return b.area - a.area; }); var filteredAreas = sortedAreas.filter(function (_ref2) { var width = _ref2.width, height = _ref2.height; return width >= popper.clientWidth && height >= popper.clientHeight; }); var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; var variation = placement.split('-')[1]; return computedPlacement + (variation ? '-' + variation : ''); } /** * Get offsets to the reference element * @method * @memberof Popper.Utils * @param {Object} state * @param {Element} popper - the popper element * @param {Element} reference - the reference element (the popper will be relative to this) * @returns {Object} An object containing the offsets which will be applied to the popper */ function getReferenceOffsets(state, popper, reference) { var commonOffsetParent = findCommonOffsetParent(popper, reference); return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent); } /** * Get the outer sizes of the given element (offset size + margins) * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Object} object containing width and height properties */ function getOuterSizes(element) { var styles = getComputedStyle(element); var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight); var result = { width: element.offsetWidth + y, height: element.offsetHeight + x }; return result; } /** * Get the opposite placement of the given one * @method * @memberof Popper.Utils * @argument {String} placement * @returns {String} flipped placement */ function getOppositePlacement(placement) { var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; return placement.replace(/left|right|bottom|top/g, function (matched) { return hash[matched]; }); } /** * Get offsets to the popper * @method * @memberof Popper.Utils * @param {Object} position - CSS position the Popper will get applied * @param {HTMLElement} popper - the popper element * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) * @param {String} placement - one of the valid placement options * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper */ function getPopperOffsets(popper, referenceOffsets, placement) { placement = placement.split('-')[0]; // Get popper node sizes var popperRect = getOuterSizes(popper); // Add position, width and height to our offsets object var popperOffsets = { width: popperRect.width, height: popperRect.height }; // depending by the popper placement we have to compute its offsets slightly differently var isHoriz = ['right', 'left'].indexOf(placement) !== -1; var mainSide = isHoriz ? 'top' : 'left'; var secondarySide = isHoriz ? 'left' : 'top'; var measurement = isHoriz ? 'height' : 'width'; var secondaryMeasurement = !isHoriz ? 'height' : 'width'; popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; if (placement === secondarySide) { popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; } else { popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; } return popperOffsets; } /** * Mimics the `find` method of Array * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function find(arr, check) { // use native find if supported if (Array.prototype.find) { return arr.find(check); } // use `filter` to obtain the same behavior of `find` return arr.filter(check)[0]; } /** * Return the index of the matching object * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function findIndex(arr, prop, value) { // use native findIndex if supported if (Array.prototype.findIndex) { return arr.findIndex(function (cur) { return cur[prop] === value; }); } // use `find` + `indexOf` if `findIndex` isn't supported var match = find(arr, function (obj) { return obj[prop] === value; }); return arr.indexOf(match); } /** * Loop trough the list of modifiers and run them in order, * each of them will then edit the data object. * @method * @memberof Popper.Utils * @param {dataObject} data * @param {Array} modifiers * @param {String} ends - Optional modifier name used as stopper * @returns {dataObject} */ function runModifiers(modifiers, data, ends) { var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); modifiersToRun.forEach(function (modifier) { if (modifier['function']) { // eslint-disable-line dot-notation console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); } var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation if (modifier.enabled && isFunction(fn)) { // Add properties to offsets to make them a complete clientRect object // we do this before each modifier to make sure the previous one doesn't // mess with these values data.offsets.popper = getClientRect(data.offsets.popper); data.offsets.reference = getClientRect(data.offsets.reference); data = fn(data, modifier); } }); return data; } /** * Updates the position of the popper, computing the new offsets and applying * the new style.
* Prefer `scheduleUpdate` over `update` because of performance reasons. * @method * @memberof Popper */ function update() { // if popper is destroyed, don't perform any further update if (this.state.isDestroyed) { return; } var data = { instance: this, styles: {}, arrowStyles: {}, attributes: {}, flipped: false, offsets: {} }; // compute reference element offsets data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); // store the computed placement inside `originalPlacement` data.originalPlacement = data.placement; // compute the popper offsets data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); data.offsets.popper.position = 'absolute'; // run the modifiers data = runModifiers(this.modifiers, data); // the first `update` will call `onCreate` callback // the other ones will call `onUpdate` callback if (!this.state.isCreated) { this.state.isCreated = true; this.options.onCreate(data); } else { this.options.onUpdate(data); } } /** * Helper used to know if the given modifier is enabled. * @method * @memberof Popper.Utils * @returns {Boolean} */ function isModifierEnabled(modifiers, modifierName) { return modifiers.some(function (_ref) { var name = _ref.name, enabled = _ref.enabled; return enabled && name === modifierName; }); } /** * Get the prefixed supported property name * @method * @memberof Popper.Utils * @argument {String} property (camelCase) * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) */ function getSupportedPropertyName(property) { var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; var upperProp = property.charAt(0).toUpperCase() + property.slice(1); for (var i = 0; i < prefixes.length - 1; i++) { var prefix = prefixes[i]; var toCheck = prefix ? '' + prefix + upperProp : property; if (typeof document.body.style[toCheck] !== 'undefined') { return toCheck; } } return null; } /** * Destroy the popper * @method * @memberof Popper */ function destroy() { this.state.isDestroyed = true; // touch DOM only if `applyStyle` modifier is enabled if (isModifierEnabled(this.modifiers, 'applyStyle')) { this.popper.removeAttribute('x-placement'); this.popper.style.left = ''; this.popper.style.position = ''; this.popper.style.top = ''; this.popper.style[getSupportedPropertyName('transform')] = ''; } this.disableEventListeners(); // remove the popper if user explicity asked for the deletion on destroy // do not use `remove` because IE11 doesn't support it if (this.options.removeOnDestroy) { this.popper.parentNode.removeChild(this.popper); } return this; } /** * Get the window associated with the element * @argument {Element} element * @returns {Window} */ function getWindow(element) { var ownerDocument = element.ownerDocument; return ownerDocument ? ownerDocument.defaultView : window; } function attachToScrollParents(scrollParent, event, callback, scrollParents) { var isBody = scrollParent.nodeName === 'BODY'; var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; target.addEventListener(event, callback, { passive: true }); if (!isBody) { attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); } scrollParents.push(target); } /** * Setup needed event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function setupEventListeners(reference, options, state, updateBound) { // Resize event listener on window state.updateBound = updateBound; getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); // Scroll event listener on scroll parents var scrollElement = getScrollParent(reference); attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); state.scrollElement = scrollElement; state.eventsEnabled = true; return state; } /** * It will add resize/scroll events and start recalculating * position of the popper element when they are triggered. * @method * @memberof Popper */ function enableEventListeners() { if (!this.state.eventsEnabled) { this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); } } /** * Remove event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function removeEventListeners(reference, state) { // Remove resize event listener on window getWindow(reference).removeEventListener('resize', state.updateBound); // Remove scroll event listener on scroll parents state.scrollParents.forEach(function (target) { target.removeEventListener('scroll', state.updateBound); }); // Reset state state.updateBound = null; state.scrollParents = []; state.scrollElement = null; state.eventsEnabled = false; return state; } /** * It will remove resize/scroll events and won't recalculate popper position * when they are triggered. It also won't trigger onUpdate callback anymore, * unless you call `update` method manually. * @method * @memberof Popper */ function disableEventListeners() { if (this.state.eventsEnabled) { cancelAnimationFrame(this.scheduleUpdate); this.state = removeEventListeners(this.reference, this.state); } } /** * Tells if a given input is a number * @method * @memberof Popper.Utils * @param {*} input to check * @return {Boolean} */ function isNumeric(n) { return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); } /** * Set the style to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the style to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setStyles(element, styles) { Object.keys(styles).forEach(function (prop) { var unit = ''; // add unit if the value is numeric and is one of the following if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { unit = 'px'; } element.style[prop] = styles[prop] + unit; }); } /** * Set the attributes to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the attributes to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setAttributes(element, attributes) { Object.keys(attributes).forEach(function (prop) { var value = attributes[prop]; if (value !== false) { element.setAttribute(prop, attributes[prop]); } else { element.removeAttribute(prop); } }); } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} data.styles - List of style properties - values to apply to popper element * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element * @argument {Object} options - Modifiers configuration and options * @returns {Object} The same data object */ function applyStyle(data) { // any property present in `data.styles` will be applied to the popper, // in this way we can make the 3rd party modifiers add custom styles to it // Be aware, modifiers could override the properties defined in the previous // lines of this modifier! setStyles(data.instance.popper, data.styles); // any property present in `data.attributes` will be applied to the popper, // they will be set as HTML attributes of the element setAttributes(data.instance.popper, data.attributes); // if arrowElement is defined and arrowStyles has some properties if (data.arrowElement && Object.keys(data.arrowStyles).length) { setStyles(data.arrowElement, data.arrowStyles); } return data; } /** * Set the x-placement attribute before everything else because it could be used * to add margins to the popper margins needs to be calculated to get the * correct popper offsets. * @method * @memberof Popper.modifiers * @param {HTMLElement} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper. * @param {Object} options - Popper.js options */ function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { // compute reference element offsets var referenceOffsets = getReferenceOffsets(state, popper, reference); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); popper.setAttribute('x-placement', placement); // Apply `position` to popper before anything else because // without the position applied we can't guarantee correct computations setStyles(popper, { position: 'absolute' }); return options; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeStyle(data, options) { var x = options.x, y = options.y; var popper = data.offsets.popper; // Remove this legacy support in Popper.js v2 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { return modifier.name === 'applyStyle'; }).gpuAcceleration; if (legacyGpuAccelerationOption !== undefined) { console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); } var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; var offsetParent = getOffsetParent(data.instance.popper); var offsetParentRect = getBoundingClientRect(offsetParent); // Styles var styles = { position: popper.position }; // floor sides to avoid blurry text var offsets = { left: Math.floor(popper.left), top: Math.floor(popper.top), bottom: Math.floor(popper.bottom), right: Math.floor(popper.right) }; var sideA = x === 'bottom' ? 'top' : 'bottom'; var sideB = y === 'right' ? 'left' : 'right'; // if gpuAcceleration is set to `true` and transform is supported, // we use `translate3d` to apply the position to the popper we // automatically use the supported prefixed version if needed var prefixedProperty = getSupportedPropertyName('transform'); // now, let's make a step back and look at this code closely (wtf?) // If the content of the popper grows once it's been positioned, it // may happen that the popper gets misplaced because of the new content // overflowing its reference element // To avoid this problem, we provide two options (x and y), which allow // the consumer to define the offset origin. // If we position a popper on top of a reference element, we can set // `x` to `top` to make the popper grow towards its top instead of // its bottom. var left = void 0, top = void 0; if (sideA === 'bottom') { top = -offsetParentRect.height + offsets.bottom; } else { top = offsets.top; } if (sideB === 'right') { left = -offsetParentRect.width + offsets.right; } else { left = offsets.left; } if (gpuAcceleration && prefixedProperty) { styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; styles[sideA] = 0; styles[sideB] = 0; styles.willChange = 'transform'; } else { // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties var invertTop = sideA === 'bottom' ? -1 : 1; var invertLeft = sideB === 'right' ? -1 : 1; styles[sideA] = top * invertTop; styles[sideB] = left * invertLeft; styles.willChange = sideA + ', ' + sideB; } // Attributes var attributes = { 'x-placement': data.placement }; // Update `data` attributes, styles and arrowStyles data.attributes = _extends$1({}, attributes, data.attributes); data.styles = _extends$1({}, styles, data.styles); data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles); return data; } /** * Helper used to know if the given modifier depends from another one.
* It checks if the needed modifier is listed and enabled. * @method * @memberof Popper.Utils * @param {Array} modifiers - list of modifiers * @param {String} requestingName - name of requesting modifier * @param {String} requestedName - name of requested modifier * @returns {Boolean} */ function isModifierRequired(modifiers, requestingName, requestedName) { var requesting = find(modifiers, function (_ref) { var name = _ref.name; return name === requestingName; }); var isRequired = !!requesting && modifiers.some(function (modifier) { return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; }); if (!isRequired) { var _requesting = '`' + requestingName + '`'; var requested = '`' + requestedName + '`'; console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); } return isRequired; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function arrow(data, options) { var _data$offsets$arrow; // arrow depends on keepTogether in order to work if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { return data; } var arrowElement = options.element; // if arrowElement is a string, suppose it's a CSS selector if (typeof arrowElement === 'string') { arrowElement = data.instance.popper.querySelector(arrowElement); // if arrowElement is not found, don't run the modifier if (!arrowElement) { return data; } } else { // if the arrowElement isn't a query selector we must check that the // provided DOM node is child of its popper node if (!data.instance.popper.contains(arrowElement)) { console.warn('WARNING: `arrow.element` must be child of its popper element!'); return data; } } var placement = data.placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isVertical = ['left', 'right'].indexOf(placement) !== -1; var len = isVertical ? 'height' : 'width'; var sideCapitalized = isVertical ? 'Top' : 'Left'; var side = sideCapitalized.toLowerCase(); var altSide = isVertical ? 'left' : 'top'; var opSide = isVertical ? 'bottom' : 'right'; var arrowElementSize = getOuterSizes(arrowElement)[len]; // // extends keepTogether behavior making sure the popper and its // reference have enough pixels in conjuction // // top/left side if (reference[opSide] - arrowElementSize < popper[side]) { data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); } // bottom/right side if (reference[side] + arrowElementSize > popper[opSide]) { data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; } data.offsets.popper = getClientRect(data.offsets.popper); // compute center of the popper var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; // Compute the sideValue using the updated popper offsets // take popper margin in account because we don't have this info available var css = getStyleComputedProperty(data.instance.popper); var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10); var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10); var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; // prevent arrowElement from being placed not contiguously to its popper sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); data.arrowElement = arrowElement; data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow); return data; } /** * Get the opposite placement variation of the given one * @method * @memberof Popper.Utils * @argument {String} placement variation * @returns {String} flipped placement variation */ function getOppositeVariation(variation) { if (variation === 'end') { return 'start'; } else if (variation === 'start') { return 'end'; } return variation; } /** * List of accepted placements to use as values of the `placement` option.
* Valid placements are: * - `auto` * - `top` * - `right` * - `bottom` * - `left` * * Each placement can have a variation from this list: * - `-start` * - `-end` * * Variations are interpreted easily if you think of them as the left to right * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` * is right.
* Vertically (`left` and `right`), `start` is top and `end` is bottom. * * Some valid examples are: * - `top-end` (on top of reference, right aligned) * - `right-start` (on right of reference, top aligned) * - `bottom` (on bottom, centered) * - `auto-right` (on the side with more space available, alignment depends by placement) * * @static * @type {Array} * @enum {String} * @readonly * @method placements * @memberof Popper */ var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; // Get rid of `auto` `auto-start` and `auto-end` var validPlacements = placements.slice(3); /** * Given an initial placement, returns all the subsequent placements * clockwise (or counter-clockwise). * * @method * @memberof Popper.Utils * @argument {String} placement - A valid placement (it accepts variations) * @argument {Boolean} counter - Set to true to walk the placements counterclockwise * @returns {Array} placements including their variations */ function clockwise(placement) { var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var index = validPlacements.indexOf(placement); var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); return counter ? arr.reverse() : arr; } var BEHAVIORS = { FLIP: 'flip', CLOCKWISE: 'clockwise', COUNTERCLOCKWISE: 'counterclockwise' }; /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function flip(data, options) { // if `inner` modifier is enabled, we can't use the `flip` modifier if (isModifierEnabled(data.instance.modifiers, 'inner')) { return data; } if (data.flipped && data.placement === data.originalPlacement) { // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides return data; } var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement); var placement = data.placement.split('-')[0]; var placementOpposite = getOppositePlacement(placement); var variation = data.placement.split('-')[1] || ''; var flipOrder = []; switch (options.behavior) { case BEHAVIORS.FLIP: flipOrder = [placement, placementOpposite]; break; case BEHAVIORS.CLOCKWISE: flipOrder = clockwise(placement); break; case BEHAVIORS.COUNTERCLOCKWISE: flipOrder = clockwise(placement, true); break; default: flipOrder = options.behavior; } flipOrder.forEach(function (step, index) { if (placement !== step || flipOrder.length === index + 1) { return data; } placement = data.placement.split('-')[0]; placementOpposite = getOppositePlacement(placement); var popperOffsets = data.offsets.popper; var refOffsets = data.offsets.reference; // using floor because the reference offsets may contain decimals we are not going to consider here var floor = Math.floor; var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); if (overlapsRef || overflowsBoundaries || flippedVariation) { // this boolean to detect any flip loop data.flipped = true; if (overlapsRef || overflowsBoundaries) { placement = flipOrder[index + 1]; } if (flippedVariation) { variation = getOppositeVariation(variation); } data.placement = placement + (variation ? '-' + variation : ''); // this object contains `position`, we want to preserve it along with // any additional property we may add in the future data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); data = runModifiers(data.instance.modifiers, data, 'flip'); } }); return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function keepTogether(data) { var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var placement = data.placement.split('-')[0]; var floor = Math.floor; var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var side = isVertical ? 'right' : 'bottom'; var opSide = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; if (popper[side] < floor(reference[opSide])) { data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; } if (popper[opSide] > floor(reference[side])) { data.offsets.popper[opSide] = floor(reference[side]); } return data; } /** * Converts a string containing value + unit into a px value number * @function * @memberof {modifiers~offset} * @private * @argument {String} str - Value + unit string * @argument {String} measurement - `height` or `width` * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @returns {Number|String} * Value in pixels, or original string if no values were extracted */ function toValue(str, measurement, popperOffsets, referenceOffsets) { // separate value from unit var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); var value = +split[1]; var unit = split[2]; // If it's not a number it's an operator, I guess if (!value) { return str; } if (unit.indexOf('%') === 0) { var element = void 0; switch (unit) { case '%p': element = popperOffsets; break; case '%': case '%r': default: element = referenceOffsets; } var rect = getClientRect(element); return rect[measurement] / 100 * value; } else if (unit === 'vh' || unit === 'vw') { // if is a vh or vw, we calculate the size based on the viewport var size = void 0; if (unit === 'vh') { size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); } else { size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); } return size / 100 * value; } else { // if is an explicit pixel unit, we get rid of the unit and keep the value // if is an implicit unit, it's px, and we return just the value return value; } } /** * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. * @function * @memberof {modifiers~offset} * @private * @argument {String} offset * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @argument {String} basePlacement * @returns {Array} a two cells array with x and y offsets in numbers */ function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { var offsets = [0, 0]; // Use height if placement is left or right and index is 0 otherwise use width // in this way the first offset will use an axis and the second one // will use the other one var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; // Split the offset string to obtain a list of values and operands // The regex addresses values with the plus or minus sign in front (+10, -20, etc) var fragments = offset.split(/(\+|\-)/).map(function (frag) { return frag.trim(); }); // Detect if the offset string contains a pair of values or a single one // they could be separated by comma or space var divider = fragments.indexOf(find(fragments, function (frag) { return frag.search(/,|\s/) !== -1; })); if (fragments[divider] && fragments[divider].indexOf(',') === -1) { console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); } // If divider is found, we divide the list of values and operands to divide // them by ofset X and Y. var splitRegex = /\s*,\s*|\s+/; var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; // Convert the values with units to absolute pixels to allow our computations ops = ops.map(function (op, index) { // Most of the units rely on the orientation of the popper var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; var mergeWithPrevious = false; return op // This aggregates any `+` or `-` sign that aren't considered operators // e.g.: 10 + +5 => [10, +, +5] .reduce(function (a, b) { if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { a[a.length - 1] = b; mergeWithPrevious = true; return a; } else if (mergeWithPrevious) { a[a.length - 1] += b; mergeWithPrevious = false; return a; } else { return a.concat(b); } }, []) // Here we convert the string values into number values (in px) .map(function (str) { return toValue(str, measurement, popperOffsets, referenceOffsets); }); }); // Loop trough the offsets arrays and execute the operations ops.forEach(function (op, index) { op.forEach(function (frag, index2) { if (isNumeric(frag)) { offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); } }); }); return offsets; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @argument {Number|String} options.offset=0 * The offset value as described in the modifier description * @returns {Object} The data object, properly modified */ function offset(data, _ref) { var offset = _ref.offset; var placement = data.placement, _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var basePlacement = placement.split('-')[0]; var offsets = void 0; if (isNumeric(+offset)) { offsets = [+offset, 0]; } else { offsets = parseOffset(offset, popper, reference, basePlacement); } if (basePlacement === 'left') { popper.top += offsets[0]; popper.left -= offsets[1]; } else if (basePlacement === 'right') { popper.top += offsets[0]; popper.left += offsets[1]; } else if (basePlacement === 'top') { popper.left += offsets[0]; popper.top -= offsets[1]; } else if (basePlacement === 'bottom') { popper.left += offsets[0]; popper.top += offsets[1]; } data.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function preventOverflow(data, options) { var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); // If offsetParent is the reference element, we really want to // go one step up and use the next offsetParent as reference to // avoid to make this modifier completely useless and look like broken if (data.instance.reference === boundariesElement) { boundariesElement = getOffsetParent(boundariesElement); } var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement); options.boundaries = boundaries; var order = options.priority; var popper = data.offsets.popper; var check = { primary: function primary(placement) { var value = popper[placement]; if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { value = Math.max(popper[placement], boundaries[placement]); } return defineProperty({}, placement, value); }, secondary: function secondary(placement) { var mainSide = placement === 'right' ? 'left' : 'top'; var value = popper[mainSide]; if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); } return defineProperty({}, mainSide, value); } }; order.forEach(function (placement) { var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; popper = _extends$1({}, popper, check[side](placement)); }); data.offsets.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function shift(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var shiftvariation = placement.split('-')[1]; // if shift shiftvariation is specified, run the modifier if (shiftvariation) { var _data$offsets = data.offsets, reference = _data$offsets.reference, popper = _data$offsets.popper; var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; var side = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; var shiftOffsets = { start: defineProperty({}, side, reference[side]), end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) }; data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]); } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function hide(data) { if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { return data; } var refRect = data.offsets.reference; var bound = find(data.instance.modifiers, function (modifier) { return modifier.name === 'preventOverflow'; }).boundaries; if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === true) { return data; } data.hide = true; data.attributes['x-out-of-boundaries'] = ''; } else { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === false) { return data; } data.hide = false; data.attributes['x-out-of-boundaries'] = false; } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function inner(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); data.placement = getOppositePlacement(placement); data.offsets.popper = getClientRect(popper); return data; } /** * Modifier function, each modifier can have a function of this type assigned * to its `fn` property.
* These functions will be called on each update, this means that you must * make sure they are performant enough to avoid performance bottlenecks. * * @function ModifierFn * @argument {dataObject} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {dataObject} The data object, properly modified */ /** * Modifiers are plugins used to alter the behavior of your poppers.
* Popper.js uses a set of 9 modifiers to provide all the basic functionalities * needed by the library. * * Usually you don't want to override the `order`, `fn` and `onLoad` props. * All the other properties are configurations that could be tweaked. * @namespace modifiers */ var modifiers = { /** * Modifier used to shift the popper on the start or end of its reference * element.
* It will read the variation of the `placement` property.
* It can be one either `-end` or `-start`. * @memberof modifiers * @inner */ shift: { /** @prop {number} order=100 - Index used to define the order of execution */ order: 100, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: shift }, /** * The `offset` modifier can shift your popper on both its axis. * * It accepts the following units: * - `px` or unitless, interpreted as pixels * - `%` or `%r`, percentage relative to the length of the reference element * - `%p`, percentage relative to the length of the popper element * - `vw`, CSS viewport width unit * - `vh`, CSS viewport height unit * * For length is intended the main axis relative to the placement of the popper.
* This means that if the placement is `top` or `bottom`, the length will be the * `width`. In case of `left` or `right`, it will be the height. * * You can provide a single value (as `Number` or `String`), or a pair of values * as `String` divided by a comma or one (or more) white spaces.
* The latter is a deprecated method because it leads to confusion and will be * removed in v2.
* Additionally, it accepts additions and subtractions between different units. * Note that multiplications and divisions aren't supported. * * Valid examples are: * ``` * 10 * '10%' * '10, 10' * '10%, 10' * '10 + 10%' * '10 - 5vh + 3%' * '-10px + 5vh, 5px - 6%' * ``` * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap * > with their reference element, unfortunately, you will have to disable the `flip` modifier. * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373) * * @memberof modifiers * @inner */ offset: { /** @prop {number} order=200 - Index used to define the order of execution */ order: 200, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: offset, /** @prop {Number|String} offset=0 * The offset value as described in the modifier description */ offset: 0 }, /** * Modifier used to prevent the popper from being positioned outside the boundary. * * An scenario exists where the reference itself is not within the boundaries.
* We can say it has "escaped the boundaries" — or just "escaped".
* In this case we need to decide whether the popper should either: * * - detach from the reference and remain "trapped" in the boundaries, or * - if it should ignore the boundary and "escape with its reference" * * When `escapeWithReference` is set to`true` and reference is completely * outside its boundaries, the popper will overflow (or completely leave) * the boundaries in order to remain attached to the edge of the reference. * * @memberof modifiers * @inner */ preventOverflow: { /** @prop {number} order=300 - Index used to define the order of execution */ order: 300, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: preventOverflow, /** * @prop {Array} [priority=['left','right','top','bottom']] * Popper will try to prevent overflow following these priorities by default, * then, it could overflow on the left and on top of the `boundariesElement` */ priority: ['left', 'right', 'top', 'bottom'], /** * @prop {number} padding=5 * Amount of pixel used to define a minimum distance between the boundaries * and the popper this makes sure the popper has always a little padding * between the edges of its container */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='scrollParent' * Boundaries used by the modifier, can be `scrollParent`, `window`, * `viewport` or any DOM element. */ boundariesElement: 'scrollParent' }, /** * Modifier used to make sure the reference and its popper stay near eachothers * without leaving any gap between the two. Expecially useful when the arrow is * enabled and you want to assure it to point to its reference element. * It cares only about the first axis, you can still have poppers with margin * between the popper and its reference element. * @memberof modifiers * @inner */ keepTogether: { /** @prop {number} order=400 - Index used to define the order of execution */ order: 400, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: keepTogether }, /** * This modifier is used to move the `arrowElement` of the popper to make * sure it is positioned between the reference element and its popper element. * It will read the outer size of the `arrowElement` node to detect how many * pixels of conjuction are needed. * * It has no effect if no `arrowElement` is provided. * @memberof modifiers * @inner */ arrow: { /** @prop {number} order=500 - Index used to define the order of execution */ order: 500, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: arrow, /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ element: '[x-arrow]' }, /** * Modifier used to flip the popper's placement when it starts to overlap its * reference element. * * Requires the `preventOverflow` modifier before it in order to work. * * **NOTE:** this modifier will interrupt the current update cycle and will * restart it if it detects the need to flip the placement. * @memberof modifiers * @inner */ flip: { /** @prop {number} order=600 - Index used to define the order of execution */ order: 600, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: flip, /** * @prop {String|Array} behavior='flip' * The behavior used to change the popper's placement. It can be one of * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid * placements (with optional variations). */ behavior: 'flip', /** * @prop {number} padding=5 * The popper will flip if it hits the edges of the `boundariesElement` */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='viewport' * The element which will define the boundaries of the popper position, * the popper will never be placed outside of the defined boundaries * (except if keepTogether is enabled) */ boundariesElement: 'viewport' }, /** * Modifier used to make the popper flow toward the inner of the reference element. * By default, when this modifier is disabled, the popper will be placed outside * the reference element. * @memberof modifiers * @inner */ inner: { /** @prop {number} order=700 - Index used to define the order of execution */ order: 700, /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ enabled: false, /** @prop {ModifierFn} */ fn: inner }, /** * Modifier used to hide the popper when its reference element is outside of the * popper boundaries. It will set a `x-out-of-boundaries` attribute which can * be used to hide with a CSS selector the popper when its reference is * out of boundaries. * * Requires the `preventOverflow` modifier before it in order to work. * @memberof modifiers * @inner */ hide: { /** @prop {number} order=800 - Index used to define the order of execution */ order: 800, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: hide }, /** * Computes the style that will be applied to the popper element to gets * properly positioned. * * Note that this modifier will not touch the DOM, it just prepares the styles * so that `applyStyle` modifier can apply it. This separation is useful * in case you need to replace `applyStyle` with a custom implementation. * * This modifier has `850` as `order` value to maintain backward compatibility * with previous versions of Popper.js. Expect the modifiers ordering method * to change in future major versions of the library. * * @memberof modifiers * @inner */ computeStyle: { /** @prop {number} order=850 - Index used to define the order of execution */ order: 850, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: computeStyle, /** * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: true, /** * @prop {string} [x='bottom'] * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. * Change this if your popper should grow in a direction different from `bottom` */ x: 'bottom', /** * @prop {string} [x='left'] * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. * Change this if your popper should grow in a direction different from `right` */ y: 'right' }, /** * Applies the computed styles to the popper element. * * All the DOM manipulations are limited to this modifier. This is useful in case * you want to integrate Popper.js inside a framework or view library and you * want to delegate all the DOM manipulations to it. * * Note that if you disable this modifier, you must make sure the popper element * has its position set to `absolute` before Popper.js can do its work! * * Just disable this modifier and define you own to achieve the desired effect. * * @memberof modifiers * @inner */ applyStyle: { /** @prop {number} order=900 - Index used to define the order of execution */ order: 900, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: applyStyle, /** @prop {Function} */ onLoad: applyStyleOnLoad, /** * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: undefined } }; /** * The `dataObject` is an object containing all the informations used by Popper.js * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks. * @name dataObject * @property {Object} data.instance The Popper.js instance * @property {String} data.placement Placement applied to popper * @property {String} data.originalPlacement Placement originally defined on init * @property {Boolean} data.flipped True if popper has been flipped by flip modifier * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper. * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.boundaries Offsets of the popper boundaries * @property {Object} data.offsets The measurements of popper, reference and arrow elements. * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 */ /** * Default options provided to Popper.js constructor.
* These can be overriden using the `options` argument of Popper.js.
* To override an option, simply pass as 3rd argument an object with the same * structure of this object, example: * ``` * new Popper(ref, pop, { * modifiers: { * preventOverflow: { enabled: false } * } * }) * ``` * @type {Object} * @static * @memberof Popper */ var Defaults = { /** * Popper's placement * @prop {Popper.placements} placement='bottom' */ placement: 'bottom', /** * Whether events (resize, scroll) are initially enabled * @prop {Boolean} eventsEnabled=true */ eventsEnabled: true, /** * Set to true if you want to automatically remove the popper when * you call the `destroy` method. * @prop {Boolean} removeOnDestroy=false */ removeOnDestroy: false, /** * Callback called when the popper is created.
* By default, is set to no-op.
* Access Popper.js instance with `data.instance`. * @prop {onCreate} */ onCreate: function onCreate() {}, /** * Callback called when the popper is updated, this callback is not called * on the initialization/creation of the popper, but only on subsequent * updates.
* By default, is set to no-op.
* Access Popper.js instance with `data.instance`. * @prop {onUpdate} */ onUpdate: function onUpdate() {}, /** * List of modifiers used to modify the offsets before they are applied to the popper. * They provide most of the functionalities of Popper.js * @prop {modifiers} */ modifiers: modifiers }; /** * @callback onCreate * @param {dataObject} data */ /** * @callback onUpdate * @param {dataObject} data */ // Utils // Methods var Popper = function () { /** * Create a new Popper.js instance * @class Popper * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper. * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) * @return {Object} instance - The generated Popper.js instance */ function Popper(reference, popper) { var _this = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; classCallCheck(this, Popper); this.scheduleUpdate = function () { return requestAnimationFrame(_this.update); }; // make update() debounced, so that it only runs at most once-per-tick this.update = debounce(this.update.bind(this)); // with {} we create a new object with the options inside it this.options = _extends$1({}, Popper.Defaults, options); // init state this.state = { isDestroyed: false, isCreated: false, scrollParents: [] }; // get reference and popper elements (allow jQuery wrappers) this.reference = reference && reference.jquery ? reference[0] : reference; this.popper = popper && popper.jquery ? popper[0] : popper; // Deep merge modifiers options this.options.modifiers = {}; Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); }); // Refactoring modifiers' list (Object => Array) this.modifiers = Object.keys(this.options.modifiers).map(function (name) { return _extends$1({ name: name }, _this.options.modifiers[name]); }) // sort the modifiers by order .sort(function (a, b) { return a.order - b.order; }); // modifiers have the ability to execute arbitrary code when Popper.js get inited // such code is executed in the same order of its modifier // they could add new properties to their options configuration // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! this.modifiers.forEach(function (modifierOptions) { if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); } }); // fire the first update to position the popper in the right place this.update(); var eventsEnabled = this.options.eventsEnabled; if (eventsEnabled) { // setup event listeners, they will take care of update the position in specific situations this.enableEventListeners(); } this.state.eventsEnabled = eventsEnabled; } // We can't use class properties because they don't get listed in the // class prototype and break stuff like Sinon stubs createClass(Popper, [{ key: 'update', value: function update$$1() { return update.call(this); } }, { key: 'destroy', value: function destroy$$1() { return destroy.call(this); } }, { key: 'enableEventListeners', value: function enableEventListeners$$1() { return enableEventListeners.call(this); } }, { key: 'disableEventListeners', value: function disableEventListeners$$1() { return disableEventListeners.call(this); } /** * Schedule an update, it will run on the next UI update available * @method scheduleUpdate * @memberof Popper */ /** * Collection of utilities useful when writing custom modifiers. * Starting from version 1.7, this method is available only if you * include `popper-utils.js` before `popper.js`. * * **DEPRECATION**: This way to access PopperUtils is deprecated * and will be removed in v2! Use the PopperUtils module directly instead. * Due to the high instability of the methods contained in Utils, we can't * guarantee them to follow semver. Use them at your own risk! * @static * @private * @type {Object} * @deprecated since version 1.8 * @member Utils * @memberof Popper */ }]); return Popper; }(); /** * The `referenceObject` is an object that provides an interface compatible with Popper.js * and lets you use it as replacement of a real DOM node.
* You can use this method to position a popper relatively to a set of coordinates * in case you don't have a DOM node to use as reference. * * ``` * new Popper(referenceObject, popperNode); * ``` * * NB: This feature isn't supported in Internet Explorer 10 * @name referenceObject * @property {Function} data.getBoundingClientRect * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. * @property {number} data.clientWidth * An ES6 getter that will return the width of the virtual reference element. * @property {number} data.clientHeight * An ES6 getter that will return the height of the virtual reference element. */ Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; Popper.placements = placements; Popper.Defaults = Defaults; /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Dropdown = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'dropdown'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.dropdown'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, CLICK: "click" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY }; var ClassName = { DISABLED: 'disabled', SHOW: 'show', DROPUP: 'dropup', DROPRIGHT: 'dropright', DROPLEFT: 'dropleft', MENURIGHT: 'dropdown-menu-right', MENULEFT: 'dropdown-menu-left', POSITION_STATIC: 'position-static' }; var Selector = { DATA_TOGGLE: '[data-toggle="dropdown"]', FORM_CHILD: '.dropdown form', MENU: '.dropdown-menu', NAVBAR_NAV: '.navbar-nav', VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)' }; var AttachmentMap = { TOP: 'top-start', TOPEND: 'top-end', BOTTOM: 'bottom-start', BOTTOMEND: 'bottom-end', RIGHT: 'right-start', RIGHTEND: 'right-end', LEFT: 'left-start', LEFTEND: 'left-end' }; var Default = { offset: 0, flip: true, boundary: 'scrollParent' }; var DefaultType = { offset: '(number|string|function)', flip: 'boolean', boundary: '(string|element)' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Dropdown = /*#__PURE__*/ function () { function Dropdown(element, config) { this._element = element; this._popper = null; this._config = this._getConfig(config); this._menu = this._getMenuElement(); this._inNavbar = this._detectNavbar(); this._addEventListeners(); } // getters var _proto = Dropdown.prototype; // public _proto.toggle = function toggle() { if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) { return; } var parent = Dropdown._getParentFromElement(this._element); var isActive = $$$1(this._menu).hasClass(ClassName.SHOW); Dropdown._clearMenus(); if (isActive) { return; } var relatedTarget = { relatedTarget: this._element }; var showEvent = $$$1.Event(Event.SHOW, relatedTarget); $$$1(parent).trigger(showEvent); if (showEvent.isDefaultPrevented()) { return; } // Disable totally Popper.js for Dropdown in Navbar if (!this._inNavbar) { /** * Check for Popper dependency * Popper - https://popper.js.org */ if (typeof Popper === 'undefined') { throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)'); } var element = this._element; // for dropup with alignment we use the parent as popper container if ($$$1(parent).hasClass(ClassName.DROPUP)) { if ($$$1(this._menu).hasClass(ClassName.MENULEFT) || $$$1(this._menu).hasClass(ClassName.MENURIGHT)) { element = parent; } } // If boundary is not `scrollParent`, then set position to `static` // to allow the menu to "escape" the scroll parent's boundaries // https://github.com/twbs/bootstrap/issues/24251 if (this._config.boundary !== 'scrollParent') { $$$1(parent).addClass(ClassName.POSITION_STATIC); } this._popper = new Popper(element, this._menu, this._getPopperConfig()); } // if this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement && !$$$1(parent).closest(Selector.NAVBAR_NAV).length) { $$$1('body').children().on('mouseover', null, $$$1.noop); } this._element.focus(); this._element.setAttribute('aria-expanded', true); $$$1(this._menu).toggleClass(ClassName.SHOW); $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget)); }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); $$$1(this._element).off(EVENT_KEY); this._element = null; this._menu = null; if (this._popper !== null) { this._popper.destroy(); this._popper = null; } }; _proto.update = function update() { this._inNavbar = this._detectNavbar(); if (this._popper !== null) { this._popper.scheduleUpdate(); } }; // private _proto._addEventListeners = function _addEventListeners() { var _this = this; $$$1(this._element).on(Event.CLICK, function (event) { event.preventDefault(); event.stopPropagation(); _this.toggle(); }); }; _proto._getConfig = function _getConfig(config) { config = _extends({}, this.constructor.Default, $$$1(this._element).data(), config); Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); return config; }; _proto._getMenuElement = function _getMenuElement() { if (!this._menu) { var parent = Dropdown._getParentFromElement(this._element); this._menu = $$$1(parent).find(Selector.MENU)[0]; } return this._menu; }; _proto._getPlacement = function _getPlacement() { var $parentDropdown = $$$1(this._element).parent(); var placement = AttachmentMap.BOTTOM; // Handle dropup if ($parentDropdown.hasClass(ClassName.DROPUP)) { placement = AttachmentMap.TOP; if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { placement = AttachmentMap.TOPEND; } } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { placement = AttachmentMap.RIGHT; } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { placement = AttachmentMap.LEFT; } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { placement = AttachmentMap.BOTTOMEND; } return placement; }; _proto._detectNavbar = function _detectNavbar() { return $$$1(this._element).closest('.navbar').length > 0; }; _proto._getPopperConfig = function _getPopperConfig() { var _this2 = this; var offsetConf = {}; if (typeof this._config.offset === 'function') { offsetConf.fn = function (data) { data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets) || {}); return data; }; } else { offsetConf.offset = this._config.offset; } var popperConfig = { placement: this._getPlacement(), modifiers: { offset: offsetConf, flip: { enabled: this._config.flip }, preventOverflow: { boundariesElement: this._config.boundary } } }; return popperConfig; }; // static Dropdown._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); var _config = typeof config === 'object' ? config : null; if (!data) { data = new Dropdown(this, _config); $$$1(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; Dropdown._clearMenus = function _clearMenus(event) { if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { return; } var toggles = $$$1.makeArray($$$1(Selector.DATA_TOGGLE)); for (var i = 0; i < toggles.length; i++) { var parent = Dropdown._getParentFromElement(toggles[i]); var context = $$$1(toggles[i]).data(DATA_KEY); var relatedTarget = { relatedTarget: toggles[i] }; if (!context) { continue; } var dropdownMenu = context._menu; if (!$$$1(parent).hasClass(ClassName.SHOW)) { continue; } if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) { continue; } var hideEvent = $$$1.Event(Event.HIDE, relatedTarget); $$$1(parent).trigger(hideEvent); if (hideEvent.isDefaultPrevented()) { continue; } // if this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { $$$1('body').children().off('mouseover', null, $$$1.noop); } toggles[i].setAttribute('aria-expanded', 'false'); $$$1(dropdownMenu).removeClass(ClassName.SHOW); $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget)); } }; Dropdown._getParentFromElement = function _getParentFromElement(element) { var parent; var selector = Util.getSelectorFromElement(element); if (selector) { parent = $$$1(selector)[0]; } return parent || element.parentNode; }; Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { // If not input/textarea: // - And not a key in REGEXP_KEYDOWN => not a dropdown command // If input/textarea: // - If space key => not a dropdown command // - If key is other than escape // - If key is not up or down => not a dropdown command // - If trigger inside the menu => not a dropdown command if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { return; } event.preventDefault(); event.stopPropagation(); if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) { return; } var parent = Dropdown._getParentFromElement(this); var isActive = $$$1(parent).hasClass(ClassName.SHOW); if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { if (event.which === ESCAPE_KEYCODE) { var toggle = $$$1(parent).find(Selector.DATA_TOGGLE)[0]; $$$1(toggle).trigger('focus'); } $$$1(this).trigger('click'); return; } var items = $$$1(parent).find(Selector.VISIBLE_ITEMS).get(); if (!items.length) { return; } var index = items.indexOf(event.target); if (event.which === ARROW_UP_KEYCODE && index > 0) { // up index--; } if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // down index++; } if (index < 0) { index = 0; } items[index].focus(); }; _createClass(Dropdown, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Dropdown; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { event.preventDefault(); event.stopPropagation(); Dropdown._jQueryInterface.call($$$1(this), 'toggle'); }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { e.stopPropagation(); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Dropdown._jQueryInterface; $$$1.fn[NAME].Constructor = Dropdown; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Dropdown._jQueryInterface; }; return Dropdown; }($, Popper); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Modal = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'modal'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.modal'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var TRANSITION_DURATION = 300; var BACKDROP_TRANSITION_DURATION = 150; var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key var Default = { backdrop: true, keyboard: true, focus: true, show: true }; var DefaultType = { backdrop: '(boolean|string)', keyboard: 'boolean', focus: 'boolean', show: 'boolean' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, RESIZE: "resize" + EVENT_KEY, CLICK_DISMISS: "click.dismiss" + EVENT_KEY, KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY }; var ClassName = { SCROLLBAR_MEASURER: 'modal-scrollbar-measure', BACKDROP: 'modal-backdrop', OPEN: 'modal-open', FADE: 'fade', SHOW: 'show' }; var Selector = { DIALOG: '.modal-dialog', DATA_TOGGLE: '[data-toggle="modal"]', DATA_DISMISS: '[data-dismiss="modal"]', FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', STICKY_CONTENT: '.sticky-top', NAVBAR_TOGGLER: '.navbar-toggler' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Modal = /*#__PURE__*/ function () { function Modal(element, config) { this._config = this._getConfig(config); this._element = element; this._dialog = $$$1(element).find(Selector.DIALOG)[0]; this._backdrop = null; this._isShown = false; this._isBodyOverflowing = false; this._ignoreBackdropClick = false; this._originalBodyPadding = 0; this._scrollbarWidth = 0; } // getters var _proto = Modal.prototype; // public _proto.toggle = function toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); }; _proto.show = function show(relatedTarget) { var _this = this; if (this._isTransitioning || this._isShown) { return; } if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE)) { this._isTransitioning = true; } var showEvent = $$$1.Event(Event.SHOW, { relatedTarget: relatedTarget }); $$$1(this._element).trigger(showEvent); if (this._isShown || showEvent.isDefaultPrevented()) { return; } this._isShown = true; this._checkScrollbar(); this._setScrollbar(); this._adjustDialog(); $$$1(document.body).addClass(ClassName.OPEN); this._setEscapeEvent(); this._setResizeEvent(); $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { return _this.hide(event); }); $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { if ($$$1(event.target).is(_this._element)) { _this._ignoreBackdropClick = true; } }); }); this._showBackdrop(function () { return _this._showElement(relatedTarget); }); }; _proto.hide = function hide(event) { var _this2 = this; if (event) { event.preventDefault(); } if (this._isTransitioning || !this._isShown) { return; } var hideEvent = $$$1.Event(Event.HIDE); $$$1(this._element).trigger(hideEvent); if (!this._isShown || hideEvent.isDefaultPrevented()) { return; } this._isShown = false; var transition = Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE); if (transition) { this._isTransitioning = true; } this._setEscapeEvent(); this._setResizeEvent(); $$$1(document).off(Event.FOCUSIN); $$$1(this._element).removeClass(ClassName.SHOW); $$$1(this._element).off(Event.CLICK_DISMISS); $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS); if (transition) { $$$1(this._element).one(Util.TRANSITION_END, function (event) { return _this2._hideModal(event); }).emulateTransitionEnd(TRANSITION_DURATION); } else { this._hideModal(); } }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY); this._config = null; this._element = null; this._dialog = null; this._backdrop = null; this._isShown = null; this._isBodyOverflowing = null; this._ignoreBackdropClick = null; this._scrollbarWidth = null; }; _proto.handleUpdate = function handleUpdate() { this._adjustDialog(); }; // private _proto._getConfig = function _getConfig(config) { config = _extends({}, Default, config); Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._showElement = function _showElement(relatedTarget) { var _this3 = this; var transition = Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE); if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // don't move modals dom position document.body.appendChild(this._element); } this._element.style.display = 'block'; this._element.removeAttribute('aria-hidden'); this._element.scrollTop = 0; if (transition) { Util.reflow(this._element); } $$$1(this._element).addClass(ClassName.SHOW); if (this._config.focus) { this._enforceFocus(); } var shownEvent = $$$1.Event(Event.SHOWN, { relatedTarget: relatedTarget }); var transitionComplete = function transitionComplete() { if (_this3._config.focus) { _this3._element.focus(); } _this3._isTransitioning = false; $$$1(_this3._element).trigger(shownEvent); }; if (transition) { $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION); } else { transitionComplete(); } }; _proto._enforceFocus = function _enforceFocus() { var _this4 = this; $$$1(document).off(Event.FOCUSIN) // guard against infinite focus loop .on(Event.FOCUSIN, function (event) { if (document !== event.target && _this4._element !== event.target && !$$$1(_this4._element).has(event.target).length) { _this4._element.focus(); } }); }; _proto._setEscapeEvent = function _setEscapeEvent() { var _this5 = this; if (this._isShown && this._config.keyboard) { $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) { if (event.which === ESCAPE_KEYCODE) { event.preventDefault(); _this5.hide(); } }); } else if (!this._isShown) { $$$1(this._element).off(Event.KEYDOWN_DISMISS); } }; _proto._setResizeEvent = function _setResizeEvent() { var _this6 = this; if (this._isShown) { $$$1(window).on(Event.RESIZE, function (event) { return _this6.handleUpdate(event); }); } else { $$$1(window).off(Event.RESIZE); } }; _proto._hideModal = function _hideModal() { var _this7 = this; this._element.style.display = 'none'; this._element.setAttribute('aria-hidden', true); this._isTransitioning = false; this._showBackdrop(function () { $$$1(document.body).removeClass(ClassName.OPEN); _this7._resetAdjustments(); _this7._resetScrollbar(); $$$1(_this7._element).trigger(Event.HIDDEN); }); }; _proto._removeBackdrop = function _removeBackdrop() { if (this._backdrop) { $$$1(this._backdrop).remove(); this._backdrop = null; } }; _proto._showBackdrop = function _showBackdrop(callback) { var _this8 = this; var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; if (this._isShown && this._config.backdrop) { var doAnimate = Util.supportsTransitionEnd() && animate; this._backdrop = document.createElement('div'); this._backdrop.className = ClassName.BACKDROP; if (animate) { $$$1(this._backdrop).addClass(animate); } $$$1(this._backdrop).appendTo(document.body); $$$1(this._element).on(Event.CLICK_DISMISS, function (event) { if (_this8._ignoreBackdropClick) { _this8._ignoreBackdropClick = false; return; } if (event.target !== event.currentTarget) { return; } if (_this8._config.backdrop === 'static') { _this8._element.focus(); } else { _this8.hide(); } }); if (doAnimate) { Util.reflow(this._backdrop); } $$$1(this._backdrop).addClass(ClassName.SHOW); if (!callback) { return; } if (!doAnimate) { callback(); return; } $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); } else if (!this._isShown && this._backdrop) { $$$1(this._backdrop).removeClass(ClassName.SHOW); var callbackRemove = function callbackRemove() { _this8._removeBackdrop(); if (callback) { callback(); } }; if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE)) { $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION); } else { callbackRemove(); } } else if (callback) { callback(); } }; // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals // todo (fat): these should probably be refactored out of modal.js // ---------------------------------------------------------------------- _proto._adjustDialog = function _adjustDialog() { var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; if (!this._isBodyOverflowing && isModalOverflowing) { this._element.style.paddingLeft = this._scrollbarWidth + "px"; } if (this._isBodyOverflowing && !isModalOverflowing) { this._element.style.paddingRight = this._scrollbarWidth + "px"; } }; _proto._resetAdjustments = function _resetAdjustments() { this._element.style.paddingLeft = ''; this._element.style.paddingRight = ''; }; _proto._checkScrollbar = function _checkScrollbar() { var rect = document.body.getBoundingClientRect(); this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; this._scrollbarWidth = this._getScrollbarWidth(); }; _proto._setScrollbar = function _setScrollbar() { var _this9 = this; if (this._isBodyOverflowing) { // Note: DOMNode.style.paddingRight returns the actual value or '' if not set // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set // Adjust fixed content padding $$$1(Selector.FIXED_CONTENT).each(function (index, element) { var actualPadding = $$$1(element)[0].style.paddingRight; var calculatedPadding = $$$1(element).css('padding-right'); $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); }); // Adjust sticky content margin $$$1(Selector.STICKY_CONTENT).each(function (index, element) { var actualMargin = $$$1(element)[0].style.marginRight; var calculatedMargin = $$$1(element).css('margin-right'); $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); }); // Adjust navbar-toggler margin $$$1(Selector.NAVBAR_TOGGLER).each(function (index, element) { var actualMargin = $$$1(element)[0].style.marginRight; var calculatedMargin = $$$1(element).css('margin-right'); $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + "px"); }); // Adjust body padding var actualPadding = document.body.style.paddingRight; var calculatedPadding = $$$1('body').css('padding-right'); $$$1('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); } }; _proto._resetScrollbar = function _resetScrollbar() { // Restore fixed content padding $$$1(Selector.FIXED_CONTENT).each(function (index, element) { var padding = $$$1(element).data('padding-right'); if (typeof padding !== 'undefined') { $$$1(element).css('padding-right', padding).removeData('padding-right'); } }); // Restore sticky content and navbar-toggler margin $$$1(Selector.STICKY_CONTENT + ", " + Selector.NAVBAR_TOGGLER).each(function (index, element) { var margin = $$$1(element).data('margin-right'); if (typeof margin !== 'undefined') { $$$1(element).css('margin-right', margin).removeData('margin-right'); } }); // Restore body padding var padding = $$$1('body').data('padding-right'); if (typeof padding !== 'undefined') { $$$1('body').css('padding-right', padding).removeData('padding-right'); } }; _proto._getScrollbarWidth = function _getScrollbarWidth() { // thx d.walsh var scrollDiv = document.createElement('div'); scrollDiv.className = ClassName.SCROLLBAR_MEASURER; document.body.appendChild(scrollDiv); var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); return scrollbarWidth; }; // static Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); var _config = _extends({}, Modal.Default, $$$1(this).data(), typeof config === 'object' && config); if (!data) { data = new Modal(this, _config); $$$1(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](relatedTarget); } else if (_config.show) { data.show(relatedTarget); } }); }; _createClass(Modal, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return Modal; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { var _this10 = this; var target; var selector = Util.getSelectorFromElement(this); if (selector) { target = $$$1(selector)[0]; } var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _extends({}, $$$1(target).data(), $$$1(this).data()); if (this.tagName === 'A' || this.tagName === 'AREA') { event.preventDefault(); } var $target = $$$1(target).one(Event.SHOW, function (showEvent) { if (showEvent.isDefaultPrevented()) { // only register focus restorer if modal will actually get shown return; } $target.one(Event.HIDDEN, function () { if ($$$1(_this10).is(':visible')) { _this10.focus(); } }); }); Modal._jQueryInterface.call($$$1(target), config, this); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Modal._jQueryInterface; $$$1.fn[NAME].Constructor = Modal; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Modal._jQueryInterface; }; return Modal; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Tooltip = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'tooltip'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.tooltip'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var TRANSITION_DURATION = 150; var CLASS_PREFIX = 'bs-tooltip'; var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); var DefaultType = { animation: 'boolean', template: 'string', title: '(string|element|function)', trigger: 'string', delay: '(number|object)', html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', offset: '(number|string)', container: '(string|element|boolean)', fallbackPlacement: '(string|array)', boundary: '(string|element)' }; var AttachmentMap = { AUTO: 'auto', TOP: 'top', RIGHT: 'right', BOTTOM: 'bottom', LEFT: 'left' }; var Default = { animation: true, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, selector: false, placement: 'top', offset: 0, container: false, fallbackPlacement: 'flip', boundary: 'scrollParent' }; var HoverState = { SHOW: 'show', OUT: 'out' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, INSERTED: "inserted" + EVENT_KEY, CLICK: "click" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, FOCUSOUT: "focusout" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY }; var ClassName = { FADE: 'fade', SHOW: 'show' }; var Selector = { TOOLTIP: '.tooltip', TOOLTIP_INNER: '.tooltip-inner', ARROW: '.arrow' }; var Trigger = { HOVER: 'hover', FOCUS: 'focus', CLICK: 'click', MANUAL: 'manual' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Tooltip = /*#__PURE__*/ function () { function Tooltip(element, config) { /** * Check for Popper dependency * Popper - https://popper.js.org */ if (typeof Popper === 'undefined') { throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)'); } // private this._isEnabled = true; this._timeout = 0; this._hoverState = ''; this._activeTrigger = {}; this._popper = null; // protected this.element = element; this.config = this._getConfig(config); this.tip = null; this._setListeners(); } // getters var _proto = Tooltip.prototype; // public _proto.enable = function enable() { this._isEnabled = true; }; _proto.disable = function disable() { this._isEnabled = false; }; _proto.toggleEnabled = function toggleEnabled() { this._isEnabled = !this._isEnabled; }; _proto.toggle = function toggle(event) { if (!this._isEnabled) { return; } if (event) { var dataKey = this.constructor.DATA_KEY; var context = $$$1(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $$$1(event.currentTarget).data(dataKey, context); } context._activeTrigger.click = !context._activeTrigger.click; if (context._isWithActiveTrigger()) { context._enter(null, context); } else { context._leave(null, context); } } else { if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) { this._leave(null, this); return; } this._enter(null, this); } }; _proto.dispose = function dispose() { clearTimeout(this._timeout); $$$1.removeData(this.element, this.constructor.DATA_KEY); $$$1(this.element).off(this.constructor.EVENT_KEY); $$$1(this.element).closest('.modal').off('hide.bs.modal'); if (this.tip) { $$$1(this.tip).remove(); } this._isEnabled = null; this._timeout = null; this._hoverState = null; this._activeTrigger = null; if (this._popper !== null) { this._popper.destroy(); } this._popper = null; this.element = null; this.config = null; this.tip = null; }; _proto.show = function show() { var _this = this; if ($$$1(this.element).css('display') === 'none') { throw new Error('Please use show on visible elements'); } var showEvent = $$$1.Event(this.constructor.Event.SHOW); if (this.isWithContent() && this._isEnabled) { $$$1(this.element).trigger(showEvent); var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element); if (showEvent.isDefaultPrevented() || !isInTheDom) { return; } var tip = this.getTipElement(); var tipId = Util.getUID(this.constructor.NAME); tip.setAttribute('id', tipId); this.element.setAttribute('aria-describedby', tipId); this.setContent(); if (this.config.animation) { $$$1(tip).addClass(ClassName.FADE); } var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; var attachment = this._getAttachment(placement); this.addAttachmentClass(attachment); var container = this.config.container === false ? document.body : $$$1(this.config.container); $$$1(tip).data(this.constructor.DATA_KEY, this); if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) { $$$1(tip).appendTo(container); } $$$1(this.element).trigger(this.constructor.Event.INSERTED); this._popper = new Popper(this.element, tip, { placement: attachment, modifiers: { offset: { offset: this.config.offset }, flip: { behavior: this.config.fallbackPlacement }, arrow: { element: Selector.ARROW }, preventOverflow: { boundariesElement: this.config.boundary } }, onCreate: function onCreate(data) { if (data.originalPlacement !== data.placement) { _this._handlePopperPlacementChange(data); } }, onUpdate: function onUpdate(data) { _this._handlePopperPlacementChange(data); } }); $$$1(tip).addClass(ClassName.SHOW); // if this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement) { $$$1('body').children().on('mouseover', null, $$$1.noop); } var complete = function complete() { if (_this.config.animation) { _this._fixTransition(); } var prevHoverState = _this._hoverState; _this._hoverState = null; $$$1(_this.element).trigger(_this.constructor.Event.SHOWN); if (prevHoverState === HoverState.OUT) { _this._leave(null, _this); } }; if (Util.supportsTransitionEnd() && $$$1(this.tip).hasClass(ClassName.FADE)) { $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION); } else { complete(); } } }; _proto.hide = function hide(callback) { var _this2 = this; var tip = this.getTipElement(); var hideEvent = $$$1.Event(this.constructor.Event.HIDE); var complete = function complete() { if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { tip.parentNode.removeChild(tip); } _this2._cleanTipClass(); _this2.element.removeAttribute('aria-describedby'); $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN); if (_this2._popper !== null) { _this2._popper.destroy(); } if (callback) { callback(); } }; $$$1(this.element).trigger(hideEvent); if (hideEvent.isDefaultPrevented()) { return; } $$$1(tip).removeClass(ClassName.SHOW); // if this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { $$$1('body').children().off('mouseover', null, $$$1.noop); } this._activeTrigger[Trigger.CLICK] = false; this._activeTrigger[Trigger.FOCUS] = false; this._activeTrigger[Trigger.HOVER] = false; if (Util.supportsTransitionEnd() && $$$1(this.tip).hasClass(ClassName.FADE)) { $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION); } else { complete(); } this._hoverState = ''; }; _proto.update = function update() { if (this._popper !== null) { this._popper.scheduleUpdate(); } }; // protected _proto.isWithContent = function isWithContent() { return Boolean(this.getTitle()); }; _proto.addAttachmentClass = function addAttachmentClass(attachment) { $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); }; _proto.getTipElement = function getTipElement() { this.tip = this.tip || $$$1(this.config.template)[0]; return this.tip; }; _proto.setContent = function setContent() { var $tip = $$$1(this.getTipElement()); this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle()); $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); }; _proto.setElementContent = function setElementContent($element, content) { var html = this.config.html; if (typeof content === 'object' && (content.nodeType || content.jquery)) { // content is a DOM node or a jQuery if (html) { if (!$$$1(content).parent().is($element)) { $element.empty().append(content); } } else { $element.text($$$1(content).text()); } } else { $element[html ? 'html' : 'text'](content); } }; _proto.getTitle = function getTitle() { var title = this.element.getAttribute('data-original-title'); if (!title) { title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; } return title; }; // private _proto._getAttachment = function _getAttachment(placement) { return AttachmentMap[placement.toUpperCase()]; }; _proto._setListeners = function _setListeners() { var _this3 = this; var triggers = this.config.trigger.split(' '); triggers.forEach(function (trigger) { if (trigger === 'click') { $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) { return _this3.toggle(event); }); } else if (trigger !== Trigger.MANUAL) { var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN; var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT; $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) { return _this3._enter(event); }).on(eventOut, _this3.config.selector, function (event) { return _this3._leave(event); }); } $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () { return _this3.hide(); }); }); if (this.config.selector) { this.config = _extends({}, this.config, { trigger: 'manual', selector: '' }); } else { this._fixTitle(); } }; _proto._fixTitle = function _fixTitle() { var titleType = typeof this.element.getAttribute('data-original-title'); if (this.element.getAttribute('title') || titleType !== 'string') { this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); this.element.setAttribute('title', ''); } }; _proto._enter = function _enter(event, context) { var dataKey = this.constructor.DATA_KEY; context = context || $$$1(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $$$1(event.currentTarget).data(dataKey, context); } if (event) { context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; } if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { context._hoverState = HoverState.SHOW; return; } clearTimeout(context._timeout); context._hoverState = HoverState.SHOW; if (!context.config.delay || !context.config.delay.show) { context.show(); return; } context._timeout = setTimeout(function () { if (context._hoverState === HoverState.SHOW) { context.show(); } }, context.config.delay.show); }; _proto._leave = function _leave(event, context) { var dataKey = this.constructor.DATA_KEY; context = context || $$$1(event.currentTarget).data(dataKey); if (!context) { context = new this.constructor(event.currentTarget, this._getDelegateConfig()); $$$1(event.currentTarget).data(dataKey, context); } if (event) { context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; } if (context._isWithActiveTrigger()) { return; } clearTimeout(context._timeout); context._hoverState = HoverState.OUT; if (!context.config.delay || !context.config.delay.hide) { context.hide(); return; } context._timeout = setTimeout(function () { if (context._hoverState === HoverState.OUT) { context.hide(); } }, context.config.delay.hide); }; _proto._isWithActiveTrigger = function _isWithActiveTrigger() { for (var trigger in this._activeTrigger) { if (this._activeTrigger[trigger]) { return true; } } return false; }; _proto._getConfig = function _getConfig(config) { config = _extends({}, this.constructor.Default, $$$1(this.element).data(), config); if (typeof config.delay === 'number') { config.delay = { show: config.delay, hide: config.delay }; } if (typeof config.title === 'number') { config.title = config.title.toString(); } if (typeof config.content === 'number') { config.content = config.content.toString(); } Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); return config; }; _proto._getDelegateConfig = function _getDelegateConfig() { var config = {}; if (this.config) { for (var key in this.config) { if (this.constructor.Default[key] !== this.config[key]) { config[key] = this.config[key]; } } } return config; }; _proto._cleanTipClass = function _cleanTipClass() { var $tip = $$$1(this.getTipElement()); var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); if (tabClass !== null && tabClass.length > 0) { $tip.removeClass(tabClass.join('')); } }; _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) { this._cleanTipClass(); this.addAttachmentClass(this._getAttachment(data.placement)); }; _proto._fixTransition = function _fixTransition() { var tip = this.getTipElement(); var initConfigAnimation = this.config.animation; if (tip.getAttribute('x-placement') !== null) { return; } $$$1(tip).removeClass(ClassName.FADE); this.config.animation = false; this.hide(); this.show(); this.config.animation = initConfigAnimation; }; // static Tooltip._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); var _config = typeof config === 'object' && config; if (!data && /dispose|hide/.test(config)) { return; } if (!data) { data = new Tooltip(this, _config); $$$1(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; _createClass(Tooltip, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "NAME", get: function get() { return NAME; } }, { key: "DATA_KEY", get: function get() { return DATA_KEY; } }, { key: "Event", get: function get() { return Event; } }, { key: "EVENT_KEY", get: function get() { return EVENT_KEY; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Tooltip; }(); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Tooltip._jQueryInterface; $$$1.fn[NAME].Constructor = Tooltip; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Tooltip._jQueryInterface; }; return Tooltip; }($, Popper); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Popover = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'popover'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.popover'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var CLASS_PREFIX = 'bs-popover'; var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); var Default = _extends({}, Tooltip.Default, { placement: 'right', trigger: 'click', content: '', template: '' }); var DefaultType = _extends({}, Tooltip.DefaultType, { content: '(string|element|function)' }); var ClassName = { FADE: 'fade', SHOW: 'show' }; var Selector = { TITLE: '.popover-header', CONTENT: '.popover-body' }; var Event = { HIDE: "hide" + EVENT_KEY, HIDDEN: "hidden" + EVENT_KEY, SHOW: "show" + EVENT_KEY, SHOWN: "shown" + EVENT_KEY, INSERTED: "inserted" + EVENT_KEY, CLICK: "click" + EVENT_KEY, FOCUSIN: "focusin" + EVENT_KEY, FOCUSOUT: "focusout" + EVENT_KEY, MOUSEENTER: "mouseenter" + EVENT_KEY, MOUSELEAVE: "mouseleave" + EVENT_KEY /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var Popover = /*#__PURE__*/ function (_Tooltip) { _inheritsLoose(Popover, _Tooltip); function Popover() { return _Tooltip.apply(this, arguments) || this; } var _proto = Popover.prototype; // overrides _proto.isWithContent = function isWithContent() { return this.getTitle() || this._getContent(); }; _proto.addAttachmentClass = function addAttachmentClass(attachment) { $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); }; _proto.getTipElement = function getTipElement() { this.tip = this.tip || $$$1(this.config.template)[0]; return this.tip; }; _proto.setContent = function setContent() { var $tip = $$$1(this.getTipElement()); // we use append for html objects to maintain js events this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); var content = this._getContent(); if (typeof content === 'function') { content = content.call(this.element); } this.setElementContent($tip.find(Selector.CONTENT), content); $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); }; // private _proto._getContent = function _getContent() { return this.element.getAttribute('data-content') || this.config.content; }; _proto._cleanTipClass = function _cleanTipClass() { var $tip = $$$1(this.getTipElement()); var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); if (tabClass !== null && tabClass.length > 0) { $tip.removeClass(tabClass.join('')); } }; // static Popover._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $$$1(this).data(DATA_KEY); var _config = typeof config === 'object' ? config : null; if (!data && /destroy|hide/.test(config)) { return; } if (!data) { data = new Popover(this, _config); $$$1(this).data(DATA_KEY, data); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new Error("No method named \"" + config + "\""); } data[config](); } }); }; _createClass(Popover, null, [{ key: "VERSION", // getters get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }, { key: "NAME", get: function get() { return NAME; } }, { key: "DATA_KEY", get: function get() { return DATA_KEY; } }, { key: "Event", get: function get() { return Event; } }, { key: "EVENT_KEY", get: function get() { return EVENT_KEY; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return Popover; }(Tooltip); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ $$$1.fn[NAME] = Popover._jQueryInterface; $$$1.fn[NAME].Constructor = Popover; $$$1.fn[NAME].noConflict = function () { $$$1.fn[NAME] = JQUERY_NO_CONFLICT; return Popover._jQueryInterface; }; return Popover; }($); /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta.3): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var ScrollSpy = function ($$$1) { /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'scrollspy'; var VERSION = '4.0.0-beta.3'; var DATA_KEY = 'bs.scrollspy'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; var Default = { offset: 10, method: 'auto', target: '' }; var DefaultType = { offset: 'number', method: 'string', target: '(string|element)' }; var Event = { ACTIVATE: "activate" + EVENT_KEY, SCROLL: "scroll" + EVENT_KEY, LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY }; var ClassName = { DROPDOWN_ITEM: 'dropdown-item', DROPDOWN_MENU: 'dropdown-menu', ACTIVE: 'active' }; var Selector = { DATA_SPY: '[data-spy="scroll"]', ACTIVE: '.active', NAV_LIST_GROUP: '.nav, .list-group', NAV_LINKS: '.nav-link', NAV_ITEMS: '.nav-item', LIST_ITEMS: '.list-group-item', DROPDOWN: '.dropdown', DROPDOWN_ITEMS: '.dropdown-item', DROPDOWN_TOGGLE: '.dropdown-toggle' }; var OffsetMethod = { OFFSET: 'offset', POSITION: 'position' /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ }; var ScrollSpy = /*#__PURE__*/ function () { function ScrollSpy(element, config) { var _this = this; this._element = element; this._scrollElement = element.tagName === 'BODY' ? window : element; this._config = this._getConfig(config); this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); this._offsets = []; this._targets = []; this._activeTarget = null; this._scrollHeight = 0; $$$1(this._scrollElement).on(Event.SCROLL, function (event) { return _this._process(event); }); this.refresh(); this._process(); } // getters var _proto = ScrollSpy.prototype; // public _proto.refresh = function refresh() { var _this2 = this; var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET; var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; this._offsets = []; this._targets = []; this._scrollHeight = this._getScrollHeight(); var targets = $$$1.makeArray($$$1(this._selector)); targets.map(function (element) { var target; var targetSelector = Util.getSelectorFromElement(element); if (targetSelector) { target = $$$1(targetSelector)[0]; } if (target) { var targetBCR = target.getBoundingClientRect(); if (targetBCR.width || targetBCR.height) { // todo (fat): remove sketch reliance on jQuery position/offset return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector]; } } return null; }).filter(function (item) { return item; }).sort(function (a, b) { return a[0] - b[0]; }).forEach(function (item) { _this2._offsets.push(item[0]); _this2._targets.push(item[1]); }); }; _proto.dispose = function dispose() { $$$1.removeData(this._element, DATA_KEY); $$$1(this._scrollElement).off(EVENT_KEY); this._element = null; this._scrollElement = null; this._config = null; this._selector = null; this._offsets = null; this._targets = null; this._activeTarget = null; this._scrollHeight = null; }; // private _proto._getConfig = function _getConfig(config) { config = _extends({}, Default, config); if (typeof config.target !== 'string') { var id = $$$1(config.target).attr('id'); if (!id) { id = Util.getUID(NAME); $$$1(config.target).attr('id', id); } config.target = "#" + id; } Util.typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._getScrollTop = function _getScrollTop() { return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; }; _proto._getScrollHeight = function _getScrollHeight() { return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); }; _proto._getOffsetHeight = function _getOffsetHeight() { return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; }; _proto._process = function _process() { var scrollTop = this._getScrollTop() + this._config.offset; var scrollHeight = this._getScrollHeight(); var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); if (this._scrollHeight !== scrollHeight) { this.refresh(); } if (scrollTop >= maxScroll) { var target = this._targets[this._targets.length - 1]; if (this._activeTarget !== target) { this._activate(target); } return; } if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { this._activeTarget = null; this._clear(); return; } for (var i = this._offsets.length; i--;) { var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); if (isActiveTarget) { this._activate(this._targets[i]); } } }; _proto._activate = function _activate(target) { this._activeTarget = target; this._clear(); var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style queries = queries.map(function (selector) { return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); }); var $link = $$$1(queries.join(',')); if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); $link.addClass(ClassName.ACTIVE); } else { // Set triggered link as active $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active // With both