: '\u003CrootDir\u003E\u002Fsrc\u002F$1'\n },\n transform: {\n '^.+\\\\.js
: '\u003CrootDir\u003E\u002Fnode_modules\u002Fbabel-jest',\n '.*\\\\.(vue)
: '\u003CrootDir\u003E\u002Fnode_modules\u002Fvue-jest'\n },\n testPathIgnorePatterns: [\n '\u003CrootDir\u003E\u002Ftest\u002Fe2e'\n ],\n snapshotSerializers: ['\u003CrootDir\u003E\u002Fnode_modules\u002Fjest-serializer-vue'],\n setupFiles: ['\u003CrootDir\u003E\u002Ftest\u002Funit\u002Fsetup'],\n mapCoverage: true,\n coverageDirectory: '\u003CrootDir\u003E\u002Ftest\u002Funit\u002Fcoverage',\n collectCoverageFrom: [\n 'src\u002F**\u002F*.{js,vue}',\n '!src\u002Fmain.js',\n '!**\u002Fnode_modules\u002F**'\n ]\n}\n","id":"c41b2aee-222b-4b90-93cf-2a3e63864a7c","is_binary":false,"title":"jest.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"rkhXlo6yJGr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJ6xiaJyzH"},{"code":"\u002F\u002F https:\u002F\u002Feslint.org\u002Fdocs\u002Fuser-guide\u002Fconfiguring\n\nmodule.exports = {\n root: true,\n parser: 'babel-eslint',\n parserOptions: {\n sourceType: 'module'\n },\n env: {\n browser: true,\n },\n extends: 'airbnb-base',\n \u002F\u002F required to lint *.vue files\n plugins: [\n 'html'\n ],\n \u002F\u002F check if imports actually resolve\n settings: {\n 'import\u002Fresolver': {\n webpack: {\n config: 'build\u002Fwebpack.base.conf.js'\n }\n }\n },\n \u002F\u002F add your custom rules here\n rules: {\n \u002F\u002F don't require .vue extension when importing\n 'import\u002Fextensions': ['error', 'always', {\n js: 'never',\n vue: 'never'\n }],\n \u002F\u002F disallow reassignment of function parameters\n \u002F\u002F disallow parameter object manipulation except for specific exclusions\n 'no-param-reassign': ['error', {\n props: true,\n ignorePropertyModificationsFor: [\n 'state', \u002F\u002F for vuex state\n 'acc', \u002F\u002F for reduce accumulators\n 'e' \u002F\u002F for e.returnvalue\n ]\n }],\n \u002F\u002F allow optionalDependencies\n 'import\u002Fno-extraneous-dependencies': ['error', {\n optionalDependencies: ['test\u002Funit\u002Findex.js']\n }],\n \u002F\u002F allow debugger during development\n 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',\n \"comma-dangle\": [\"error\", \"never\"],\n \"no-plusplus\": \"off\",\n \"space-infix-ops\": \"off\",\n \"no-console\": process.env.NODE_ENV === 'production' ? 'error' : 'off',\n \"import\u002Fprefer-default-export\": \"off\",\n \"space-before-function-paren\": 0\n }\n}\n","id":"8f41c8df-7d38-46fe-a841-3b98310232c8","is_binary":false,"title":".eslintrc.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"Sy4eejpyyGr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":".DS_Store\nnode_modules\u002F\n\u002Fdist\u002F\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npackage-lock.json\n\u002Ftest\u002Funit\u002Fcoverage\u002F\n\u002Ftest\u002Fe2e\u002Freports\u002F\nselenium-debug.log\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n","id":"77a3c505-e75e-4eb0-bc8f-eacd9c110fd0","is_binary":false,"title":".gitignore","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"SJrlgsa11GH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":"\u002F\u002F https:\u002F\u002Fgithub.com\u002Fmichael-ciniawsky\u002Fpostcss-load-config\n\nmodule.exports = {\n \"plugins\": {\n \u002F\u002F to edit target browsers: use \"browserslist\" field in package.json\n \"postcss-import\": {},\n \"autoprefixer\": {}\n }\n}\n","id":"efcb78f7-45be-4f93-bdb1-1eba89288cb5","is_binary":false,"title":".postcssrc.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"rJ8xeja1yGB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":"# twitch-curi\n\n\u003E A [Curi](https:\u002F\u002Fcuri.js.org) demo that clones Twitch.tv\n\n[Demo on CodeSandbox](https:\u002F\u002Fcodesandbox.io\u002Fs\u002Fgithub\u002Fpshrmn\u002Ftwitch-curi-demo)\n","id":"064c0382-9193-4190-9981-ae02cc27c48f","is_binary":false,"title":"README.md","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"BkPxxjakkfB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":"'use strict'\nrequire('.\u002Fcheck-versions')()\n\nprocess.env.NODE_ENV = 'production'\n\nconst ora = require('ora')\nconst rm = require('rimraf')\nconst path = require('path')\nconst chalk = require('chalk')\nconst webpack = require('webpack')\nconst config = require('..\u002Fconfig')\nconst webpackConfig = require('.\u002Fwebpack.prod.conf')\n\nconst spinner = ora('building for production...')\nspinner.start()\n\nrm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err =\u003E {\n if (err) throw err\n webpack(webpackConfig, (err, stats) =\u003E {\n spinner.stop()\n if (err) throw err\n process.stdout.write(stats.toString({\n colors: true,\n modules: false,\n children: false,\n chunks: false,\n chunkModules: false\n }) + '\\n\\n')\n\n if (stats.hasErrors()) {\n console.log(chalk.red(' Build failed with errors.\\n'))\n process.exit(1)\n }\n\n console.log(chalk.cyan(' Build complete.\\n'))\n console.log(chalk.yellow(\n ' Tip: built files are meant to be served over an HTTP server.\\n' +\n ' Opening index.html over file:\u002F\u002F won\\'t work.\\n'\n ))\n })\n})\n","id":"614f80ee-56e5-4bec-b301-fea9259e1710","is_binary":false,"title":"build.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"rydeejTk1fS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst chalk = require('chalk')\nconst semver = require('semver')\nconst packageConfig = require('..\u002Fpackage.json')\nconst shell = require('shelljs')\n\nfunction exec (cmd) {\n return require('child_process').execSync(cmd).toString().trim()\n}\n\nconst versionRequirements = [\n {\n name: 'node',\n currentVersion: semver.clean(process.version),\n versionRequirement: packageConfig.engines.node\n }\n]\n\nif (shell.which('npm')) {\n versionRequirements.push({\n name: 'npm',\n currentVersion: exec('npm --version'),\n versionRequirement: packageConfig.engines.npm\n })\n}\n\nmodule.exports = function () {\n const warnings = []\n\n for (let i = 0; i \u003C versionRequirements.length; i++) {\n const mod = versionRequirements[i]\n\n if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {\n warnings.push(mod.name + ': ' +\n chalk.red(mod.currentVersion) + ' should be ' +\n chalk.green(mod.versionRequirement)\n )\n }\n }\n\n if (warnings.length) {\n console.log('')\n console.log(chalk.yellow('To use this template, you must update following to modules:'))\n console.log()\n\n for (let i = 0; i \u003C warnings.length; i++) {\n const warning = warnings[i]\n console.log(' ' + warning)\n }\n\n console.log()\n process.exit(1)\n }\n}\n","id":"162157c0-fd1d-4eb9-ae59-9822523a7f59","is_binary":false,"title":"check-versions.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"BJtlgs6JkMS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"https:\u002F\u002Frawcdn.githack.com\u002Fpshrmn\u002Ftwitch-curi-demo\u002Ff823120279757279f541fd4a7dbff35ad1ebc484\u002Fbuild\u002Flogo.png","id":"00cada40-894e-44ff-8113-57d49ba866a2","is_binary":true,"title":"logo.png","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"Bk5egjpyJGB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst path = require('path')\nconst config = require('..\u002Fconfig')\nconst ExtractTextPlugin = require('extract-text-webpack-plugin')\nconst packageConfig = require('..\u002Fpackage.json')\n\nexports.assetsPath = function (_path) {\n const assetsSubDirectory = process.env.NODE_ENV === 'production'\n ? config.build.assetsSubDirectory\n : config.dev.assetsSubDirectory\n\n return path.posix.join(assetsSubDirectory, _path)\n}\n\nexports.cssLoaders = function (options) {\n options = options || {}\n\n const cssLoader = {\n loader: 'css-loader',\n options: {\n sourceMap: options.sourceMap\n }\n }\n\n const postcssLoader = {\n loader: 'postcss-loader',\n options: {\n sourceMap: options.sourceMap\n }\n }\n\n \u002F\u002F generate loader string to be used with extract text plugin\n function generateLoaders (loader, loaderOptions) {\n const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]\n\n if (loader) {\n loaders.push({\n loader: loader + '-loader',\n options: Object.assign({}, loaderOptions, {\n sourceMap: options.sourceMap\n })\n })\n }\n\n \u002F\u002F Extract CSS when that option is specified\n \u002F\u002F (which is the case during production build)\n if (options.extract) {\n return ExtractTextPlugin.extract({\n use: loaders,\n fallback: 'vue-style-loader'\n })\n } else {\n return ['vue-style-loader'].concat(loaders)\n }\n }\n\n \u002F\u002F https:\u002F\u002Fvue-loader.vuejs.org\u002Fen\u002Fconfigurations\u002Fextract-css.html\n return {\n css: generateLoaders(),\n postcss: generateLoaders(),\n less: generateLoaders('less'),\n sass: generateLoaders('sass', { indentedSyntax: true }),\n scss: generateLoaders('sass'),\n stylus: generateLoaders('stylus'),\n styl: generateLoaders('stylus')\n }\n}\n\n\u002F\u002F Generate loaders for standalone style files (outside of .vue)\nexports.styleLoaders = function (options) {\n const output = []\n const loaders = exports.cssLoaders(options)\n\n for (const extension in loaders) {\n const loader = loaders[extension]\n output.push({\n test: new RegExp('\\\\.' + extension + '
),\n use: loader\n })\n }\n\n return output\n}\n\nexports.createNotifierCallback = () =\u003E {\n const notifier = require('node-notifier')\n\n return (severity, errors) =\u003E {\n if (severity !== 'error') return\n\n const error = errors[0]\n const filename = error.file && error.file.split('!').pop()\n\n notifier.notify({\n title: packageConfig.name,\n message: severity + ': ' + error.name,\n subtitle: filename || '',\n icon: path.join(__dirname, 'logo.png')\n })\n }\n}\n","id":"a31a6d7e-4c89-47cc-95ca-ef6be330e379","is_binary":false,"title":"utils.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"SyoexjT1JMr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst utils = require('.\u002Futils')\nconst config = require('..\u002Fconfig')\nconst isProduction = process.env.NODE_ENV === 'production'\nconst sourceMapEnabled = isProduction\n ? config.build.productionSourceMap\n : config.dev.cssSourceMap\n\nmodule.exports = {\n loaders: utils.cssLoaders({\n sourceMap: sourceMapEnabled,\n extract: isProduction\n }),\n cssSourceMap: sourceMapEnabled,\n cacheBusting: config.dev.cacheBusting,\n transformToRequire: {\n video: ['src', 'poster'],\n source: 'src',\n img: 'src',\n image: 'xlink:href'\n }\n}\n","id":"0a5dfaa1-923a-4cc5-94b7-a4d3aa7f0d18","is_binary":false,"title":"vue-loader.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"B13llspyJGr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"import Vue from 'vue'\n\nVue.config.productionTip = false\n","id":"260fb066-d4c7-4b67-bc6b-178b667a4493","is_binary":false,"title":"setup.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"rypQeoT1kMB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJ6xiaJyzH"},{"code":"'use strict'\nconst path = require('path')\nconst utils = require('.\u002Futils')\nconst config = require('..\u002Fconfig')\nconst vueLoaderConfig = require('.\u002Fvue-loader.conf')\n\nfunction resolve (dir) {\n return path.join(__dirname, '..', dir)\n}\n\nconst createLintingRule = () =\u003E ({\n test: \u002F\\.(js|vue)$\u002F,\n loader: 'eslint-loader',\n enforce: 'pre',\n include: [resolve('src'), resolve('test')],\n options: {\n formatter: require('eslint-friendly-formatter'),\n emitWarning: !config.dev.showEslintErrorsInOverlay\n }\n})\n\nmodule.exports = {\n context: path.resolve(__dirname, '..\u002F'),\n entry: {\n app: '.\u002Fsrc\u002Fmain.js'\n },\n output: {\n path: config.build.assetsRoot,\n filename: '[name].js',\n publicPath: process.env.NODE_ENV === 'production'\n ? config.build.assetsPublicPath\n : config.dev.assetsPublicPath\n },\n resolve: {\n extensions: ['.js', '.vue', '.json'],\n alias: {\n 'vue
: 'vue\u002Fdist\u002Fvue.esm.js',\n '@': resolve('src'),\n }\n },\n module: {\n rules: [\n ...(config.dev.useEslint ? [createLintingRule()] : []),\n {\n test: \u002F\\.vue$\u002F,\n loader: 'vue-loader',\n options: vueLoaderConfig\n },\n {\n test: \u002F\\.js$\u002F,\n loader: 'babel-loader',\n include: [resolve('src'), resolve('test')]\n },\n {\n test: \u002F\\.(png|jpe?g|gif|svg)(\\?.*)?$\u002F,\n loader: 'url-loader',\n options: {\n limit: 10000,\n name: utils.assetsPath('img\u002F[name].[hash:7].[ext]')\n }\n },\n {\n test: \u002F\\.(mp4|webm|ogg|mp3|wav|flac|aac)(\\?.*)?$\u002F,\n loader: 'url-loader',\n options: {\n limit: 10000,\n name: utils.assetsPath('media\u002F[name].[hash:7].[ext]')\n }\n },\n {\n test: \u002F\\.(woff2?|eot|ttf|otf)(\\?.*)?$\u002F,\n loader: 'url-loader',\n options: {\n limit: 10000,\n name: utils.assetsPath('fonts\u002F[name].[hash:7].[ext]')\n }\n }\n ]\n },\n node: {\n \u002F\u002F prevent webpack from injecting useless setImmediate polyfill because Vue\n \u002F\u002F source contains it (although only uses it if it's native).\n setImmediate: false,\n \u002F\u002F prevent webpack from injecting mocks to Node native modules\n \u002F\u002F that does not make sense for the client\n dgram: 'empty',\n fs: 'empty',\n net: 'empty',\n tls: 'empty',\n child_process: 'empty'\n }\n}\n","id":"b103a9df-a065-4476-b2fe-2124b2724904","is_binary":false,"title":"webpack.base.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"r1allsTy1zB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst utils = require('.\u002Futils')\nconst webpack = require('webpack')\nconst config = require('..\u002Fconfig')\nconst merge = require('webpack-merge')\nconst baseWebpackConfig = require('.\u002Fwebpack.base.conf')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')\nconst portfinder = require('portfinder')\n\nconst HOST = process.env.HOST\nconst PORT = process.env.PORT && Number(process.env.PORT)\n\nconst devWebpackConfig = merge(baseWebpackConfig, {\n module: {\n rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })\n },\n \u002F\u002F cheap-module-eval-source-map is faster for development\n devtool: config.dev.devtool,\n\n \u002F\u002F these devServer options should be customized in \u002Fconfig\u002Findex.js\n devServer: {\n clientLogLevel: 'warning',\n historyApiFallback: true,\n hot: true,\n compress: true,\n host: HOST || config.dev.host,\n port: PORT || config.dev.port,\n open: config.dev.autoOpenBrowser,\n overlay: config.dev.errorOverlay\n ? { warnings: false, errors: true }\n : false,\n publicPath: config.dev.assetsPublicPath,\n proxy: config.dev.proxyTable,\n quiet: true, \u002F\u002F necessary for FriendlyErrorsPlugin\n watchOptions: {\n poll: config.dev.poll,\n }\n },\n plugins: [\n new webpack.DefinePlugin({\n 'process.env': require('..\u002Fconfig\u002Fdev.env')\n }),\n new webpack.HotModuleReplacementPlugin(),\n new webpack.NamedModulesPlugin(), \u002F\u002F HMR shows correct file names in console on update.\n new webpack.NoEmitOnErrorsPlugin(),\n \u002F\u002F https:\u002F\u002Fgithub.com\u002Fampedandwired\u002Fhtml-webpack-plugin\n new HtmlWebpackPlugin({\n filename: 'index.html',\n template: 'index.html',\n inject: true\n }),\n ]\n})\n\nmodule.exports = new Promise((resolve, reject) =\u003E {\n portfinder.basePort = process.env.PORT || config.dev.port\n portfinder.getPort((err, port) =\u003E {\n if (err) {\n reject(err)\n } else {\n \u002F\u002F publish the new Port, necessary for e2e tests\n process.env.PORT = port\n \u002F\u002F add port to devServer config\n devWebpackConfig.devServer.port = port\n\n \u002F\u002F Add FriendlyErrorsPlugin\n devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({\n compilationSuccessInfo: {\n messages: [`Your application is running here: http:\u002F\u002F${devWebpackConfig.devServer.host}:${port}`],\n },\n onErrors: config.dev.notifyOnErrors\n ? utils.createNotifierCallback()\n : undefined\n }))\n\n resolve(devWebpackConfig)\n }\n })\n})\n","id":"dd1a4720-5902-4cf8-930c-975acbf236c1","is_binary":false,"title":"webpack.dev.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"ry0xlopJ1Mr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst path = require('path')\nconst utils = require('.\u002Futils')\nconst webpack = require('webpack')\nconst config = require('..\u002Fconfig')\nconst merge = require('webpack-merge')\nconst baseWebpackConfig = require('.\u002Fwebpack.base.conf')\nconst CopyWebpackPlugin = require('copy-webpack-plugin')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst ExtractTextPlugin = require('extract-text-webpack-plugin')\nconst OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')\nconst UglifyJsPlugin = require('uglifyjs-webpack-plugin')\n\nconst env = process.env.NODE_ENV === 'testing'\n ? require('..\u002Fconfig\u002Ftest.env')\n : require('..\u002Fconfig\u002Fprod.env')\n\nconst webpackConfig = merge(baseWebpackConfig, {\n module: {\n rules: utils.styleLoaders({\n sourceMap: config.build.productionSourceMap,\n extract: true,\n usePostCSS: true\n })\n },\n devtool: config.build.productionSourceMap ? config.build.devtool : false,\n output: {\n path: config.build.assetsRoot,\n filename: utils.assetsPath('js\u002F[name].[chunkhash].js'),\n chunkFilename: utils.assetsPath('js\u002F[id].[chunkhash].js')\n },\n plugins: [\n \u002F\u002F http:\u002F\u002Fvuejs.github.io\u002Fvue-loader\u002Fen\u002Fworkflow\u002Fproduction.html\n new webpack.DefinePlugin({\n 'process.env': env\n }),\n new UglifyJsPlugin({\n uglifyOptions: {\n compress: {\n warnings: false\n }\n },\n sourceMap: config.build.productionSourceMap,\n parallel: true\n }),\n \u002F\u002F extract css into its own file\n new ExtractTextPlugin({\n filename: utils.assetsPath('css\u002F[name].[contenthash].css'),\n \u002F\u002F Setting the following option to `false` will not extract CSS from codesplit chunks.\n \u002F\u002F Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.\n \u002F\u002F It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, \n \u002F\u002F increasing file size: https:\u002F\u002Fgithub.com\u002Fvuejs-templates\u002Fwebpack\u002Fissues\u002F1110\n allChunks: true,\n }),\n \u002F\u002F Compress extracted CSS. We are using this plugin so that possible\n \u002F\u002F duplicated CSS from different components can be deduped.\n new OptimizeCSSPlugin({\n cssProcessorOptions: config.build.productionSourceMap\n ? { safe: true, map: { inline: false } }\n : { safe: true }\n }),\n \u002F\u002F generate dist index.html with correct asset hash for caching.\n \u002F\u002F you can customize output by editing \u002Findex.html\n \u002F\u002F see https:\u002F\u002Fgithub.com\u002Fampedandwired\u002Fhtml-webpack-plugin\n new HtmlWebpackPlugin({\n filename: process.env.NODE_ENV === 'testing'\n ? 'index.html'\n : config.build.index,\n template: 'index.html',\n inject: true,\n minify: {\n removeComments: true,\n collapseWhitespace: true,\n removeAttributeQuotes: true\n \u002F\u002F more options:\n \u002F\u002F https:\u002F\u002Fgithub.com\u002Fkangax\u002Fhtml-minifier#options-quick-reference\n },\n \u002F\u002F necessary to consistently work with multiple chunks via CommonsChunkPlugin\n chunksSortMode: 'dependency'\n }),\n \u002F\u002F keep module.id stable when vender modules does not change\n new webpack.HashedModuleIdsPlugin(),\n \u002F\u002F enable scope hoisting\n new webpack.optimize.ModuleConcatenationPlugin(),\n \u002F\u002F split vendor js into its own file\n new webpack.optimize.CommonsChunkPlugin({\n name: 'vendor',\n minChunks (module) {\n \u002F\u002F any required modules inside node_modules are extracted to vendor\n return (\n module.resource &&\n \u002F\\.js$\u002F.test(module.resource) &&\n module.resource.indexOf(\n path.join(__dirname, '..\u002Fnode_modules')\n ) === 0\n )\n }\n }),\n \u002F\u002F extract webpack runtime and module manifest to its own file in order to\n \u002F\u002F prevent vendor hash from being updated whenever app bundle is updated\n new webpack.optimize.CommonsChunkPlugin({\n name: 'manifest',\n minChunks: Infinity\n }),\n \u002F\u002F This instance extracts shared chunks from code splitted chunks and bundles them\n \u002F\u002F in a separate chunk, similar to the vendor chunk\n \u002F\u002F see: https:\u002F\u002Fwebpack.js.org\u002Fplugins\u002Fcommons-chunk-plugin\u002F#extra-async-commons-chunk\n new webpack.optimize.CommonsChunkPlugin({\n name: 'app',\n async: 'vendor-async',\n children: true,\n minChunks: 3\n }),\n\n \u002F\u002F copy custom static assets\n new CopyWebpackPlugin([\n {\n from: path.resolve(__dirname, '..\u002Fstatic'),\n to: config.build.assetsSubDirectory,\n ignore: ['.*']\n }\n ])\n ]\n})\n\nif (config.build.productionGzip) {\n const CompressionWebpackPlugin = require('compression-webpack-plugin')\n\n webpackConfig.plugins.push(\n new CompressionWebpackPlugin({\n asset: '[path].gz[query]',\n algorithm: 'gzip',\n test: new RegExp(\n '\\\\.(' +\n config.build.productionGzipExtensions.join('|') +\n ')
\n ),\n threshold: 10240,\n minRatio: 0.8\n })\n )\n}\n\nif (config.build.bundleAnalyzerReport) {\n const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin\n webpackConfig.plugins.push(new BundleAnalyzerPlugin())\n}\n\nmodule.exports = webpackConfig\n","id":"2d506e7d-3b0e-4144-9d03-09f8a585ed54","is_binary":false,"title":"webpack.prod.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"By1bgip1kfH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJgeiTyJGr"},{"code":"'use strict'\nconst merge = require('webpack-merge')\nconst prodEnv = require('.\u002Fprod.env')\n\nmodule.exports = merge(prodEnv, {\n NODE_ENV: '\"development\"'\n})\n","id":"1eafe23b-06c1-4c0e-b8cc-22648771e1d3","is_binary":false,"title":"dev.env.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"Bke-eoTy1MB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"By-ejT11Mr"},{"code":"'use strict'\n\u002F\u002F Template version: 1.2.6\n\u002F\u002F see http:\u002F\u002Fvuejs-templates.github.io\u002Fwebpack for documentation.\n\nconst path = require('path')\n\nmodule.exports = {\n dev: {\n\n \u002F\u002F Paths\n assetsSubDirectory: 'static',\n assetsPublicPath: '\u002F',\n proxyTable: {},\n\n \u002F\u002F Various Dev Server settings\n host: 'localhost', \u002F\u002F can be overwritten by process.env.HOST\n port: 8080, \u002F\u002F can be overwritten by process.env.PORT, if port is in use, a free one will be determined\n autoOpenBrowser: false,\n errorOverlay: true,\n notifyOnErrors: true,\n poll: false, \u002F\u002F https:\u002F\u002Fwebpack.js.org\u002Fconfiguration\u002Fdev-server\u002F#devserver-watchoptions-\n\n \u002F\u002F Use Eslint Loader?\n \u002F\u002F If true, your code will be linted during bundling and\n \u002F\u002F linting errors and warnings will be shown in the console.\n useEslint: true,\n \u002F\u002F If true, eslint errors and warnings will also be shown in the error overlay\n \u002F\u002F in the browser.\n showEslintErrorsInOverlay: false,\n\n \u002F**\n * Source Maps\n *\u002F\n\n \u002F\u002F https:\u002F\u002Fwebpack.js.org\u002Fconfiguration\u002Fdevtool\u002F#development\n devtool: 'eval-source-map',\n\n \u002F\u002F If you have problems debugging vue-files in devtools,\n \u002F\u002F set this to false - it *may* help\n \u002F\u002F https:\u002F\u002Fvue-loader.vuejs.org\u002Fen\u002Foptions.html#cachebusting\n cacheBusting: true,\n\n \u002F\u002F CSS Sourcemaps off by default because relative paths are \"buggy\"\n \u002F\u002F with this option, according to the CSS-Loader README\n \u002F\u002F (https:\u002F\u002Fgithub.com\u002Fwebpack\u002Fcss-loader#sourcemaps)\n \u002F\u002F In our experience, they generally work as expected,\n \u002F\u002F just be aware of this issue when enabling this option.\n cssSourceMap: false,\n },\n\n build: {\n \u002F\u002F Template for index.html\n index: path.resolve(__dirname, '..\u002Fdist\u002Findex.html'),\n\n \u002F\u002F Paths\n assetsRoot: path.resolve(__dirname, '..\u002Fdist'),\n assetsSubDirectory: 'static',\n assetsPublicPath: '\u002F',\n\n \u002F**\n * Source Maps\n *\u002F\n\n productionSourceMap: true,\n \u002F\u002F https:\u002F\u002Fwebpack.js.org\u002Fconfiguration\u002Fdevtool\u002F#production\n devtool: '#source-map',\n\n \u002F\u002F Gzip off by default as many popular static hosts such as\n \u002F\u002F Surge or Netlify already gzip all static assets for you.\n \u002F\u002F Before setting to `true`, make sure to:\n \u002F\u002F npm install --save-dev compression-webpack-plugin\n productionGzip: false,\n productionGzipExtensions: ['js', 'css'],\n\n \u002F\u002F Run the build command with an extra argument to\n \u002F\u002F View the bundle analyzer report after build finishes:\n \u002F\u002F `npm run build --report`\n \u002F\u002F Set to `true` or `false` to always turn it on or off\n bundleAnalyzerReport: process.env.npm_config_report\n }\n}\n","id":"f0f4c6e9-5bdd-44a0-870b-982b6cff9619","is_binary":false,"title":"index.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"B1ZbejTJ1MS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"By-ejT11Mr"},{"code":"'use strict'\nmodule.exports = {\n NODE_ENV: '\"production\"'\n}\n","id":"c8735928-3ce7-4e42-bf32-9259ae47c78a","is_binary":false,"title":"prod.env.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"r1M-esT1JMH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"By-ejT11Mr"},{"code":"'use strict'\nconst merge = require('webpack-merge')\nconst devEnv = require('.\u002Fdev.env')\n\nmodule.exports = merge(devEnv, {\n NODE_ENV: '\"testing\"'\n})\n","id":"2d5dd0e1-0231-4306-8930-f581d9034cf7","is_binary":false,"title":"test.env.js","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"rJQ-ejTkJfH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"By-ejT11Mr"},{"code":"\u003C!DOCTYPE html\u003E\n\u003Chtml\u003E\n \u003Chead\u003E\n \u003Cmeta charset=\"utf-8\"\u003E\n \u003Cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"\u003E\n \u003Ctitle\u003Etwitch-curi\u003C\u002Ftitle\u003E\n \u003C\u002Fhead\u003E\n \u003Cbody\u003E\n \u003Cdiv id=\"app\"\u003E\u003C\u002Fdiv\u003E\n \u003C!-- built files will be auto injected --\u003E\n \u003C\u002Fbody\u003E\n\u003C\u002Fhtml\u003E\n","id":"f2acd0f4-3f47-4e8f-b4b4-f412936e187a","is_binary":false,"title":"index.html","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"HkEbgjakkGB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":"{\n \"name\": \"twitch-curi\",\n \"version\": \"1.0.0\",\n \"description\": \"A Curi demo that clones Twitch.tv\",\n \"author\": \"Paul Sherman \u003Cpaul.sherman.88@gmail.com\u003E\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"webpack-dev-server --inline --progress --config build\u002Fwebpack.dev.conf.js\",\n \"start\": \"npm run dev\",\n \"unit\": \"jest --config test\u002Funit\u002Fjest.conf.js --coverage\",\n \"e2e\": \"node test\u002Fe2e\u002Frunner.js\",\n \"test\": \"npm run unit && npm run e2e\",\n \"lint\": \"eslint --ext .js,.vue src test\u002Funit\u002Fspecs test\u002Fe2e\u002Fspecs\",\n \"build\": \"node build\u002Fbuild.js\"\n },\n \"dependencies\": {\n \"@curi\u002Fhelpers\": \"^2.0.0\",\n \"@curi\u002Finteractions\": \"^2.0.0\",\n \"@curi\u002Frouter\": \"^2.0.1\",\n \"@curi\u002Fvue\": \"^2.0.0-alpha.11\",\n \"@fortawesome\u002Ffontawesome\": \"^1.0.1\",\n \"@fortawesome\u002Ffontawesome-free-solid\": \"^5.0.1\",\n \"@fortawesome\u002Fvue-fontawesome\": \"^0.0.21\",\n \"@hickory\u002Fbrowser\": \"^2.0.1\",\n \"vue\": \"^2.5.2\"\n },\n \"devDependencies\": {\n \"autoprefixer\": \"^7.1.2\",\n \"babel-core\": \"^6.22.1\",\n \"babel-eslint\": \"^7.1.1\",\n \"babel-helper-vue-jsx-merge-props\": \"^2.0.3\",\n \"babel-jest\": \"^21.0.2\",\n \"babel-loader\": \"^7.1.1\",\n \"babel-plugin-dynamic-import-node\": \"^1.2.0\",\n \"babel-plugin-syntax-jsx\": \"^6.18.0\",\n \"babel-plugin-transform-es2015-modules-commonjs\": \"^6.26.0\",\n \"babel-plugin-transform-runtime\": \"^6.22.0\",\n \"babel-plugin-transform-vue-jsx\": \"^3.5.0\",\n \"babel-preset-env\": \"^1.3.2\",\n \"babel-preset-stage-2\": \"^6.22.0\",\n \"babel-register\": \"^6.22.0\",\n \"chalk\": \"^2.0.1\",\n \"chromedriver\": \"^2.27.2\",\n \"copy-webpack-plugin\": \"^4.0.1\",\n \"cross-spawn\": \"^5.0.1\",\n \"css-loader\": \"^0.28.0\",\n \"eslint\": \"^4.18.2\",\n \"eslint-config-airbnb-base\": \"^11.3.0\",\n \"eslint-friendly-formatter\": \"^3.0.0\",\n \"eslint-import-resolver-webpack\": \"^0.8.3\",\n \"eslint-loader\": \"^1.7.1\",\n \"eslint-plugin-html\": \"^3.0.0\",\n \"eslint-plugin-import\": \"^2.7.0\",\n \"eventsource-polyfill\": \"^0.9.6\",\n \"extract-text-webpack-plugin\": \"^3.0.0\",\n \"file-loader\": \"^1.1.4\",\n \"friendly-errors-webpack-plugin\": \"^1.6.1\",\n \"html-webpack-plugin\": \"^2.30.1\",\n \"jest\": \"^21.2.0\",\n \"jest-serializer-vue\": \"^0.3.0\",\n \"nightwatch\": \"^0.9.12\",\n \"node-notifier\": \"^5.1.2\",\n \"optimize-css-assets-webpack-plugin\": \"^3.2.0\",\n \"ora\": \"^1.2.0\",\n \"portfinder\": \"^1.0.13\",\n \"postcss-import\": \"^11.0.0\",\n \"postcss-loader\": \"^2.0.8\",\n \"rimraf\": \"^2.6.0\",\n \"selenium-server\": \"^3.0.1\",\n \"semver\": \"^5.3.0\",\n \"shelljs\": \"^0.7.6\",\n \"uglifyjs-webpack-plugin\": \"^1.1.1\",\n \"url-loader\": \"^0.5.8\",\n \"vue-jest\": \"^1.0.2\",\n \"vue-loader\": \"^13.3.0\",\n \"vue-style-loader\": \"^3.0.1\",\n \"vue-template-compiler\": \"^2.5.2\",\n \"webpack\": \"^3.6.0\",\n \"webpack-bundle-analyzer\": \"^2.9.0\",\n \"webpack-dev-server\": \"^2.9.1\",\n \"webpack-merge\": \"^4.1.0\"\n },\n \"engines\": {\n \"node\": \"\u003E= 4.0.0\",\n \"npm\": \"\u003E= 3.0.0\"\n },\n \"browserslist\": [\n \"\u003E 1%\",\n \"last 2 versions\",\n \"not ie \u003C= 8\"\n ]\n}\n","id":"f484fddc-fba6-476a-823b-eb39bdcb1dd4","is_binary":false,"title":"package.json","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"Syrbei611MS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":null},{"code":"import Vue from 'vue';\n\u002F\u002Fimport Home from '@\u002Fpages\u002FHome';\n\ndescribe('Home.vue', () =\u003E {\n it('should render correct contents', () =\u003E {\n \u002F*\n const Constructor = Vue.extend(Home);\n const vm = new Constructor().$mount();\n const h1 = vm.$el.querySelector('h1');\n expect(h1.textContent).toEqual('Home page');\n *\u002F\n });\n});\n","id":"1fd94782-3599-4ed3-8e54-08d7176ba1ed","is_binary":false,"title":"Home.spec.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"HJ0QljakkfS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk0xsTkJfB"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv :class=\"{ 'chat': true, hidden }\"\u003E\n \u003Cdiv class='toggle' v-on:click=\"hidden = !hidden\"\u003E\n {{hidden ? '←' : '→'}}\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='lines' ref='lines'\u003E\n \u003Cdiv\n v-for=\"line in stream.chat.chatLines\"\n :key=\"line.key\"\n class=\"line\"\n \u003E\n \u003Cspan class='username'\u003E{{line.username}}:\u003C\u002Fspan\u003E {{line.text}}\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n export default {\n name: 'Chat',\n props: ['stream'],\n data() {\n return {\n hidden: false\n };\n },\n watch: {\n stream(newStream, oldStream) {\n if (newStream !== oldStream) {\n oldStream.chat.stop();\n newStream.chat.start();\n this.hidden = false;\n }\n }\n },\n mounted() {\n this.stream.chat.start();\n },\n updated() {\n const lines = this.$refs.lines;\n const height = lines.scrollTop + lines.clientHeight;\n const bottom = lines.scrollHeight;\n \u002F\u002F This threshold might need to be tweaked. The first\n \u002F\u002F message that extends beyond the natural height, if\n \u002F\u002F significantly long, will break this. Another check\n \u002F\u002F here may be useful to prevent this, but I'm not\n \u002F\u002F bothering with it for the time being.\n const nearBottom = height\u002Fbottom \u003E 0.9;\n if (nearBottom) {\n this.$refs.lines.scrollTop = this.$refs.lines.scrollHeight;\n }\n },\n destroyed() {\n this.stream.chat.stop();\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .chat {\n height: calc(100vh - 50px);\n margin-left: 25px;\n position: relative;\n }\n\n .chat.hidden {\n width: 0px;\n }\n\n .hidden .lines {\n display: none;\n }\n\n .lines {\n width: 300px;\n border-left: 1px solid #222233;\n height: 100%;\n padding: 5px;\n overflow-y: scroll;\n }\n\n .line {\n margin-bottom: 5px;\n }\n\n span.username {\n font-weight: bold;\n }\n\n .toggle {\n position: absolute;\n left: -25px;\n width: 25px;\n height: 35px;\n background: #efefef;\n color: #e13333;\n font-size: 20px;\n line-height: 1.5em;\n cursor: pointer;\n }\n\u003C\u002Fstyle\u003E\n","id":"aa3f5b60-c2fe-434f-bf74-5fd014cbc0a7","is_binary":false,"title":"Chat.vue","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"r15Wgi6yJMr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='carousel'\u003E\n \u003Cbutton v-on:click=\"scrollLeft()\"\u003E\n \u003Cfont-awesome-icon :icon='leftArrow' \u002F\u003E\n \u003C\u002Fbutton\u003E\n \u003Cdiv class='items' ref='items'\u003E\n \u003Cslot\u003E\u003C\u002Fslot\u003E\n \u003C\u002Fdiv\u003E\n \u003Cbutton v-on:click=\"scrollRight()\"\u003E\n \u003Cfont-awesome-icon :icon='rightArrow' \u002F\u003E\n \u003C\u002Fbutton\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import FontAwesomeIcon from '@fortawesome\u002Fvue-fontawesome';\n import { faChevronLeft, faChevronRight } from '@fortawesome\u002Ffontawesome-free-solid';\n\n export default {\n name: 'Carousel',\n data() {\n return {\n left: 0\n };\n },\n computed: {\n leftArrow: () =\u003E faChevronLeft,\n rightArrow: () =\u003E faChevronRight\n },\n methods: {\n scrollLeft() {\n const parentWidth = this.$refs.items.offsetWidth;\n const offset = parentWidth \u003E= 250 ? 250 : 125;\n this.$refs.items.scrollLeft -= offset;\n },\n scrollRight() {\n const parentWidth = this.$refs.items.offsetWidth;\n const offset = parentWidth \u003E= 250 ? 250 : 125;\n this.$refs.items.scrollLeft += offset;\n }\n },\n components: {\n FontAwesomeIcon\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .carousel {\n display: flex;\n flex-flow: row nowrap;\n position: relative;\n width: 100%;\n height: 80px;\n }\n\n .items {\n display: flex;\n flex-flow: row nowrap;\n flex: 2 0;\n overflow-x: hidden;\n }\n\n button {\n height: 100%;\n display: block;\n margin: 0 3px;\n color: #efefef;\n background: #8a2b33;\n border: 1px solid rgba(255,255,255,0.5);\n }\n\u003C\u002Fstyle\u003E\n","id":"9bac0d87-50f5-4e55-bacb-74f87cef054b","is_binary":false,"title":"Carousel.vue","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"Syj-ei61kGH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"HkBxiaJJfS"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='featuring'\u003E\n \u003Cdiv class='fake-video'\u003E\u003C\u002Fdiv\u003E\n \u003Cdiv class='info'\u003E\n \u003Cdiv class='user'\u003E\n \u003CThumbnail\n width='50'\n height='50'\n v-bind='stream.colors'\n \u002F\u003E\n \u003Cdiv class='user-container'\u003E\n \u003Ch2\u003E\n {{stream.username}}\n \u003C\u002Fh2\u003E\n \u003Ch3\u003E\n Playing \u003Ccuri-link name='Game' :params='{ game: stream.playing.name }'\u003E\n {{stream.playing.name}}\n \u003C\u002Fcuri-link\u003E\n \u003C\u002Fh3\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003Cp\u003E\n {{stream.description}}\n \u003Ccuri-link name='Stream' :params='{ username: stream.username }'\u003E\n Start watching!\n \u003C\u002Fcuri-link\u003E\n \u003C\u002Fp\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import Thumbnail from '..\u002FThumbnail';\n\n export default {\n name: 'Feature',\n props: ['stream'],\n components: {\n Thumbnail\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .featuring {\n display: flex;\n flex-flow: row nowrap;\n margin-bottom: 10px;\n }\n\n .fake-video {\n width: 600px;\n height: 350px;\n background: #8a2b33;\n flex-shrink: 0;\n }\n .info {\n color: #efefef;\n padding: 0 15px;\n min-width: 0;\n }\n\n .user {\n display: flex;\n align-items: flex-start;\n margin-bottom: 15px;\n }\n\n .thumbnail {\n margin-right: 5px;\n }\n\n .user-container {\n min-width: 0;\n }\n\n .user-container h2 {\n font-size: 1.1em;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .user h3 {\n font-size: 1em;\n }\n\n a {\n color: #ff6868\n }\n\n @media screen and (max-width: 1080px) {\n .featuring {\n flex-flow: column nowrap;\n }\n\n .fake-video {\n width: 100%;\n margin-bottom: 5px;\n }\n }\n\u003C\u002Fstyle\u003E\n","id":"c9f61a69-83d6-4934-be3f-4ec988e5715a","is_binary":false,"title":"Featuring.vue","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"HynWloT11GS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"HkBxiaJJfS"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='featured'\u003E\n \u003CFeaturing :stream='activeFeatured' \u002F\u003E\n \u003CCarousel\u003E\n \u003Cdiv\n v-for=\"(stream, index) in streams\"\n :key=\"stream.id\"\n :class=\"{ 'featured-stream': true, 'active': index === active }\"\n v-on:click=\"active = index\"\n \u003E\n \u003Cdiv class='thumb-holder'\u003E\n \u003Cdiv class='overlay'\u003E\u003C\u002Fdiv\u003E\n \u003CThumbnail width='118' height='73' v-bind='stream.colors' \u002F\u003E\n \u003Cdiv class='viewers'\u003E{{stream.watching}}\u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='underbar'\u003E\u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002FCarousel\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import Featuring from '.\u002FFeaturing';\n import Carousel from '.\u002FCarousel';\n import Thumbnail from '..\u002FThumbnail';\n\n export default {\n name: 'Featured',\n props: ['streams'],\n data() {\n return {\n active: 0\n };\n },\n computed: {\n activeFeatured() {\n return this.streams[this.active];\n }\n },\n components: {\n Featuring,\n Carousel,\n Thumbnail\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .featured {\n background: #222233;\n padding: 10px;\n }\n\n .featured-stream {\n width: 120px;\n height: 75px;\n flex-shrink: 0;\n background: transparent;\n margin: 0 5px 0 0;\n }\n\n .thumb-holder {\n position: relative;\n width: 120px;\n height: 75px;\n border: 1px solid transparent;\n }\n\n .active .thumb-holder{\n border-color: #e13333;\n }\n\n .overlay {\n position: absolute;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.25);\n }\n\n .viewers {\n position: absolute;\n left: 0;\n bottom: 0;\n padding: 3px 3px 0 0;\n color: #fff;\n font-size: 12px;\n }\n .viewers::before {\n content: '';\n display: inline-block;\n background: #e13333;\n width: 10px;\n height: 10px;\n border-radius: 10px;\n margin: 0 3px;\n }\n\n .underbar {\n width: 118px;\n margin: 2px 2px 0;\n height: 2px;\n background: #8a2b33;\n }\n\n .active .underbar {\n background: #e13333;\n width: 120px;\n margin: 2px 0 0;\n }\n\u003C\u002Fstyle\u003E\n","id":"2a20725c-29f3-4bfd-ae74-fab0989b86cc","is_binary":false,"title":"index.vue","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"B16Weja1kzH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"HkBxiaJJfS"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='games-list'\u003E\n \u003Cdiv\n v-for=\"game in games\"\n :key=\"game.id\"\n class='game'\n \u003E\n \u003Cdiv\u003E\n \u003Ccuri-link name='Game' :params=\"{ game: game.name }\"\u003E\n \u003CThumbnail\n width='150'\n height='200'\n v-bind=\"game.colors\"\n \u002F\u003E\n \u003C\u002Fcuri-link\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv\u003E\n \u003Ccuri-link class='title' name='Game' :params=\"{ game: game.name }\"\u003E\n {{game.name}}\n \u003C\u002Fcuri-link\u003E\n \u003Cp\u003E{{fmt(game.watching)}} Viewers\u003C\u002Fp\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import Thumbnail from '..\u002Fcomponents\u002FThumbnail';\n import fmt from '..\u002Futils\u002FnumberFormat';\n\n export default {\n name: 'GamesList',\n props: ['games'],\n components: {\n Thumbnail\n },\n methods: {\n fmt\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .games-list {\n display: flex;\n flex-flow: row wrap;\n }\n .game {\n width: 150px;\n margin: 0 10px 10px 0;\n }\n\n a.title {\n color: #2c3e50;\n display: block;\n text-decoration: none;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n p {\n color: #999;\n font-size: 0.9em;\n }\n\u003C\u002Fstyle\u003E\n","id":"394e3b63-0fd6-4324-bda8-4de175fe7cea","is_binary":false,"title":"GamesList.vue","sha":null,"inserted_at":"2019-07-19T07:13:27","updated_at":"2019-07-19T07:13:27","upload_id":null,"shortid":"BJ0bloak1fr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"import { game } from '@\u002Futils\u002FgameGenerator'\n\ndescribe('game generator', () =\u003E {\n it('returns a game object', () =\u003E {\n const g = game();\n expect(g).toMatchObject(\n expect.objectContaining({\n name: expect.any(String),\n watching: 0,\n colors: expect.objectContaining({\n top: expect.any(String),\n right: expect.any(String),\n bottom: expect.any(String),\n left: expect.any(String)\n })\n })\n )\n });\n});\n","id":"b9a7c3d3-bb97-4e3a-904a-ec8106610754","is_binary":false,"title":"gameGenerator.spec.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"ByJ4gs6ykfr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"S1yggs6JJMH"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv :class=\"{ 'left-sidebar': true, hidden }\"\u003E\n \u003Cdiv class='toggle' v-on:click=\"hidden = !hidden\"\u003E\n {{hidden ? '→' : '←'}}\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='content'\u003E\n \u003Cdiv class='featured'\u003E\n \u003Ch3 v-if=\"!hidden\"\u003EFeatured Streamers\u003C\u002Fh3\u003E\n \u003Ch3 v-else\u003E\n \u003Cfont-awesome-icon :icon=\"camera\" \u002F\u003E\n \u003C\u002Fh3\u003E\n \u003CStreamBadge\n v-for=\"stream in featured\"\n :key=\"stream.id\"\n :stream=\"stream\"\n :hidden=\"hidden\"\n \u002F\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import FontAwesomeIcon from '@fortawesome\u002Fvue-fontawesome';\n import { faCamera } from '@fortawesome\u002Ffontawesome-free-solid';\n\n import API from '..\u002F..\u002Futils\u002FstreamState';\n import StreamBadge from '.\u002FStreamBadge';\n\n export default {\n name: 'LeftSideBar',\n data() {\n return {\n featured: API.featuredStreams(5),\n hidden: false\n };\n },\n computed: {\n camera: () =\u003E faCamera\n },\n components: {\n StreamBadge,\n FontAwesomeIcon\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .left-sidebar {\n background: #222233;\n width: 225px;\n flex-shrink: 0;\n height: calc(100vh - 50px);\n position: relative;\n margin-right: 25px;\n color: #ff6868;\n }\n\n .left-sidebar.hidden {\n width: 45px;\n }\n\n .toggle {\n position: absolute;\n right: -25px;\n width: 25px;\n height: 35px;\n background: #efefef;\n color: #e13333;\n font-size: 20px;\n line-height: 1.5em;\n cursor: pointer;\n }\n .content {\n padding: 15px 15px 0;\n }\n .hidden .content {\n padding: 15px 5px 0;\n }\n h3 {\n text-align: center;\n }\n\u003C\u002Fstyle\u003E\n","id":"b94b95e7-1404-4c2f-86b7-fee70ab68980","is_binary":false,"title":"index.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"r1efeoTy1GB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"BkUgjakJfB"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv\n class=\"stream\"\n \u003E\n \u003Cdiv\u003E\n \u003Ccuri-link name='Stream' :params=\"{ username: stream.username}\"\u003E\n \u003CThumbnail\n width='150'\n height='200'\n v-bind=\"stream.colors\"\n \u002F\u003E\n \u003C\u002Fcuri-link\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv\u003E\n \u003Ccuri-link class='title' name='Stream' :params=\"{ username: stream.username}\"\u003E\n {{stream.username}}\n \u003C\u002Fcuri-link\u003E\n \u003Cp\u003E{{fmt(stream.watching)}} Viewers\u003C\u002Fp\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import Thumbnail from '..\u002Fcomponents\u002FThumbnail';\n import fmt from '..\u002Futils\u002FnumberFormat';\n\n export default {\n name: 'StreamsList',\n props: ['stream'],\n components: {\n Thumbnail\n },\n methods: {\n fmt\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .stream {\n width: 150px;\n margin: 0 10px 10px 0;\n }\n\n a.title {\n color: #2c3e50;\n display: block;\n text-decoration: none;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n p {\n color: #999;\n font-size: 0.9em;\n }\n\u003C\u002Fstyle\u003E\n","id":"ba5252b8-5b63-4982-8f0d-056e9e27831e","is_binary":false,"title":"StreamsList.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"By-fgsp1JMr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='thumbnail' :style=\"style\"\u003E\u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n export default {\n name: 'Thumbnail',\n props: ['width', 'height', 'top', 'right', 'bottom', 'left'],\n computed: {\n style() {\n return {\n width: `${this.width}px`,\n height: `${this.height}px`,\n 'border-width': `${this.height\u002F2}px ${this.width\u002F2}px`,\n 'border-style': 'solid',\n 'border-color': `${this.top} ${this.right} ${this.bottom} ${this.left}`\n };\n }\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .thumbnail {\n display: inline-block;\n color: #ccc;\n }\n\u003C\u002Fstyle\u003E\n","id":"4a9a94c9-7642-4859-b6fd-f7d396d1bad2","is_binary":false,"title":"Thumbnail.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"HyfGgip11Gr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='topbar'\u003E\n \u003Cnav\u003E\n \u003Ccuri-link name='Home' class='home'\u003EGlitch!\u003C\u002Fcuri-link\u003E\n \u003Ccuri-link name='Browse'\u003EBrowse\u003C\u002Fcuri-link\u003E\n \u003C\u002Fnav\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n export default {\n name: 'TopBar'\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .topbar {\n background: #e13333;\n height: 50px;\n width: 100vw;\n text-align: left;\n padding-left: 15px;\n }\n nav {\n padding: 10px 0;\n }\n\n nav a {\n color: #fff;\n text-decoration: none;\n margin-right: 15px;\n }\n nav a.home {\n font-size: 2em;\n }\n\u003C\u002Fstyle\u003E\n","id":"ab6421f4-9cfa-4f8e-840d-d12ebdabe369","is_binary":false,"title":"TopBar.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"SkQGliayyMr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='user-topbar'\u003E\n \u003Cdiv class='info'\u003E\n \u003Ccuri-link name='Stream' :params=\"{ username: user.username }\"\u003E\n {{user.username}}\n \u003C\u002Fcuri-link\u003E\n \u003Cp class='full'\u003EVideos\u003C\u002Fp\u003E\n \u003Cp class='full'\u003EClips\u003C\u002Fp\u003E\n \u003Cp class='full'\u003ECollections\u003C\u002Fp\u003E\n \u003Cp class='full'\u003EEvents\u003C\u002Fp\u003E\n \u003Cp class='partial'\u003EFollowers {{fmt(user.followers)}}\u003C\u002Fp\u003E\n \u003Cp class='full'\u003EFollowing\u003C\u002Fp\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='love'\u003E\n \u003Cbutton\u003EFollow\u003C\u002Fbutton\u003E\n \u003Cbutton\u003ESubscribe\u003C\u002Fbutton\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import fmt from '..\u002Futils\u002FnumberFormat';\n\n export default {\n name: 'UserTopBar',\n props: ['user'],\n methods: {\n fmt\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .user-topbar {\n display: flex;\n flex-flow: row nowrap;\n justify-content: space-between;\n width: 100%;\n height: 35px;\n align-items: center;\n border-bottom: 1px solid #efefef;\n }\n\n .info {\n display: flex;\n flex-flow: row nowrap;\n height: 100%;\n max-width: 70%;\n overflow-x: hidden;\n }\n\n .info \u003E * {\n padding: 10px;\n }\n\n .info \u003E *:hover {\n border-bottom: 3px solid #e13333;\n }\n\n a {\n color: #2c3e50;\n text-decoration: none;\n }\n\n .love {\n display: flex;\n flex-flow: row nowrap;\n }\n\n .love button {\n background: #222233;\n color: #fff;\n border: 0;\n padding: 5px 10px;\n margin-right: 10px;\n }\n\n @media screen and (max-width: 1500px) {\n .full {\n display: none;\n }\n }\n\n @media screen and (max-width: 1100px) {\n .partial {\n display: none;\n }\n }\n\u003C\u002Fstyle\u003E\n","id":"4dbbd87c-ab7d-4beb-804f-4770a5c380f6","is_binary":false,"title":"UserTopBar.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"ByVGloTk1Gr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='stream'\u003E\n \u003Cdiv class='player'\u003E\n \u003Cdiv class='controls'\u003E\n \u003Cdiv class='left'\u003E\n \u003Cfont-awesome-icon :icon=\"play\" \u002F\u003E\n \u003Cfont-awesome-icon :icon=\"volume\" \u002F\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='right'\u003E\n \u003Cfont-awesome-icon :icon=\"cog\" \u002F\u003E\n \u003Cfont-awesome-icon :icon=\"expand\" \u002F\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='info'\u003E\n \u003Cdiv class='stream-info'\u003E\n \u003CThumbnail\n width='30'\n height='50'\n v-bind=\"game.colors\"\n \u002F\u003E\n \u003Cdiv\u003E\n \u003Cdiv class='stream-title'\u003E{{stream.title}}\u003C\u002Fdiv\u003E\n \u003Cdiv\u003E\n \u003Ccuri-link name='Game' :params=\"{ game: game.name }\"\u003E\n {{game.name}}\n \u003C\u002Fcuri-link\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003Cdiv class='viewer-info'\u003E\n \u003CWatching :count=\"stream.watching\" \u002F\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import FontAwesomeIcon from '@fortawesome\u002Fvue-fontawesome';\n import {\n faPlay,\n faVolumeUp,\n faExpand,\n faCog\n } from '@fortawesome\u002Ffontawesome-free-solid';\n\n import Thumbnail from '.\u002FThumbnail';\n import Watching from '.\u002FWatching';\n\n export default {\n name: 'VideoPlayer',\n props: ['stream'],\n computed: {\n game() {\n return this.stream.playing;\n },\n \u002F\u002F icons\n play: () =\u003E faPlay,\n volume: () =\u003E faVolumeUp,\n expand: () =\u003E faExpand,\n cog: () =\u003E faCog\n },\n components: {\n Thumbnail,\n FontAwesomeIcon,\n Watching\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .stream {\n width: 100%;\n }\n\n .player {\n width: 100%;\n padding-top: 50%;\n background: #222233;\n position: relative;\n }\n\n .controls {\n position: absolute;\n bottom: 15px;\n width: 100%;\n padding: 0 5px;\n color: #fff;\n }\n .controls svg {\n margin: 0 5px;\n }\n .left {\n float: left;\n }\n .right {\n float: right;\n }\n\n .info {\n display: flex;\n justify-content: space-between;\n margin-top: 5px;\n }\n\n .stream-info {\n display: flex;\n }\n\n .stream-title {\n font-size: 1.5em;\n }\n\n .stream-info a {\n color: #2c3e50;\n text-decoration: none;\n }\n\n .thumbnail {\n margin-right: 10px;\n }\n\u003C\u002Fstyle\u003E\n","id":"497714c0-aedd-4500-911b-5eb8cbd6ff26","is_binary":false,"title":"VideoPlayer.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"SkSGgi6J1fH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"\u003Ctemplate\u003E\n \u003Cdiv class='watching'\u003E\n \u003Cfont-awesome-icon :icon=\"user\" \u002F\u003E {{prettyCount}}\n \u003C\u002Fdiv\u003E\n\u003C\u002Ftemplate\u003E\n\n\u003Cscript\u003E\n import FontAwesomeIcon from '@fortawesome\u002Fvue-fontawesome';\n import { faUser } from '@fortawesome\u002Ffontawesome-free-solid';\n\n import fmt from '..\u002Futils\u002FnumberFormat';\n\n export default {\n name: 'Watching',\n props: ['count'],\n computed: {\n user: () =\u003E faUser,\n prettyCount() {\n return fmt(this.count);\n }\n },\n components: {\n FontAwesomeIcon\n }\n };\n\u003C\u002Fscript\u003E\n\n\u003Cstyle scoped\u003E\n .watching {\n color: #e13333;\n }\n\u003C\u002Fstyle\u003E\n","id":"6eba9778-9d40-40aa-a3a9-d297ad090fa1","is_binary":false,"title":"Watching.vue","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"r1LMeoayyzB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"Sk7xjpykMr"},{"code":"import { rand } from '.\u002Frandom';\nimport { game } from '.\u002FgameGenerator';\nimport { stream } from '.\u002FstreamGenerator';\n\n\u002F* setup *\u002F\nconst GAMES = [];\nfor (let g = 0; g \u003C 20; g++) {\n GAMES.push(game());\n}\n\nconst STREAMS = [];\nfor (let g=0; g\u003C100; g++) {\n const s = stream(g);\n STREAMS.push(s);\n\n const playing = GAMES[rand(GAMES.length)];\n s.playing = playing;\n playing.watching += s.watching;\n}\n\u002F* end setup *\u002F\n\nconst emptyFilter = n =\u003E n;\nconst mostWatchers = (a, b) =\u003E b.watching - a.watching;\n\nexport default {\n \u002F* games *\u002F\n games(filter, sort) {\n const filtered = GAMES.filter(filter);\n if (sort) {\n filtered.sort(sort);\n }\n return filtered;\n },\n topGames(count) {\n return this.games(\n emptyFilter,\n mostWatchers\n ).slice(0, count);\n },\n \u002F* streamers *\u002F\n stream(username) {\n const user = STREAMS.find(u =\u003E u.username === username);\n if (user) {\n return Promise.resolve({ user, error: undefined });\n }\n return Promise.resolve({ user: undefined, error: 'The requested user could not be found.' });\n },\n streams(filter = emptyFilter, sort) {\n const filtered = STREAMS.filter(filter);\n if (sort) {\n filtered.sort(sort);\n }\n return filtered;\n },\n topStream(count) {\n return this.streams(\n emptyFilter,\n mostWatchers\n ).slice(0, count);\n },\n featuredStreams(count) {\n return this.streams(\n emptyFilter,\n () =\u003E (Math.random() \u003E 0.5 ? 1 : -1)\n ).slice(0, count);\n },\n streamersPlaying(name) {\n const streams = this.streams(\n s =\u003E s.playing.name === name,\n mostWatchers\n );\n if (streams.length) {\n return Promise.resolve({ streams, error: undefined });\n }\n return Promise.resolve({ streams: undefined, error: 'Game not found' });\n }\n};\n","id":"2b28ae54-c347-4f13-916f-90bd360f4ce8","is_binary":false,"title":"streamState.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"BJH7eip1kMB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rkOxip11zH"},{"code":"import { rand, weightedRandomNumberGenerator } from '.\u002Frandom';\nimport { sentence } from '.\u002FloremIpsum';\nimport colors from '.\u002FcolorGenerator';\n\nconst adjectives = [\n 'Cool',\n 'Awesome',\n 'Nice',\n 'Happy',\n 'Sad',\n 'Angry',\n 'Red',\n 'Orange',\n 'Yellow',\n 'Green',\n 'Blue',\n 'Indigo',\n 'Violet',\n 'Ace',\n 'Top',\n 'Super',\n 'Evil',\n 'Giant',\n 'Tiny',\n 'Secret',\n 'Mysterious',\n 'Random'\n];\n\nconst nouns = [\n 'Lizard',\n 'Frog',\n 'Toad',\n 'Bear',\n 'Lion',\n 'Tiger',\n 'Wolf',\n 'Dog',\n 'Cat',\n 'Fish',\n 'Octopus',\n 'Monkey',\n 'Gorilla',\n 'Captain',\n 'Noob',\n 'Pro',\n 'Player',\n 'Alien'\n];\n\nfunction randomAdjective() {\n return adjectives[rand(adjectives.length)];\n}\n\nfunction streamName() {\n const adj = randomAdjective();\n const noun = nouns[rand(nouns.length)];\n return `${adj}${noun}${Math.random() \u003E 0.5 ? rand(10000) : ''}`;\n}\n\nconst followerCount = weightedRandomNumberGenerator([\n { w: 15, range: [0, 1000] },\n { w: 25, range: [1000, 25000] },\n { w: 25, range: [25000, 100000] },\n { w: 20, range: [100000, 500000] },\n { w: 15, range: [500000, 2500000] }\n]);\n\nexport const user = (isStreamer = false) =\u003E ({\n username: streamName(),\n followers: isStreamer\n ? followerCount()\n : Math.floor(Math.random()*25),\n description: isStreamer ? sentence() : '',\n colors: colors()\n});\n\n","id":"9f261874-d15e-4ec7-a585-f711383414db","is_binary":false,"title":"userGenerator.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"SyUmgiTyJMS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rkOxip11zH"},{"code":"\u002F\u002F A custom Nightwatch assertion.\n\u002F\u002F The assertion name is the filename.\n\u002F\u002F Example usage:\n\u002F\u002F\n\u002F\u002F browser.assert.elementCount(selector, count)\n\u002F\u002F\n\u002F\u002F For more information on custom assertions see:\n\u002F\u002F http:\u002F\u002Fnightwatchjs.org\u002Fguide#writing-custom-assertions\n\nexports.assertion = function (selector, count) {\n this.message = 'Testing if element \u003C' + selector + '\u003E has count: ' + count\n this.expected = count\n this.pass = function (val) {\n return val === this.expected\n }\n this.value = function (res) {\n return res.value\n }\n this.command = function (cb) {\n var self = this\n return this.api.execute(function (selector) {\n return document.querySelectorAll(selector).length\n }, [selector], function (res) {\n cb.call(self, res)\n })\n }\n}\n","id":"22b5bf5c-15e0-4bfb-a487-1a44cb9d08d1","is_binary":false,"title":"elementCount.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"rkPmgiak1zH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"S1ogoTJyGH"},{"code":"require('babel-register')\nvar config = require('..\u002F..\u002Fconfig')\n\n\u002F\u002F http:\u002F\u002Fnightwatchjs.org\u002Fgettingstarted#settings-file\nmodule.exports = {\n src_folders: ['test\u002Fe2e\u002Fspecs'],\n output_folder: 'test\u002Fe2e\u002Freports',\n custom_assertions_path: ['test\u002Fe2e\u002Fcustom-assertions'],\n\n selenium: {\n start_process: true,\n server_path: require('selenium-server').path,\n host: '127.0.0.1',\n port: 4444,\n cli_args: {\n 'webdriver.chrome.driver': require('chromedriver').path\n }\n },\n\n test_settings: {\n default: {\n selenium_port: 4444,\n selenium_host: 'localhost',\n silent: true,\n globals: {\n devServerURL: 'http:\u002F\u002Flocalhost:' + (process.env.PORT || config.dev.port)\n }\n },\n\n chrome: {\n desiredCapabilities: {\n browserName: 'chrome',\n javascriptEnabled: true,\n acceptSslCerts: true\n }\n },\n\n firefox: {\n desiredCapabilities: {\n browserName: 'firefox',\n javascriptEnabled: true,\n acceptSslCerts: true\n }\n }\n }\n}\n","id":"4561d833-d215-4ae2-9806-b08787a7ba72","is_binary":false,"title":"nightwatch.conf.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"HJd7gjp11GH","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"S1cxiTy1GS"},{"code":"\u002F\u002F 1. start the dev server using production config\nprocess.env.NODE_ENV = 'testing'\n\nconst webpack = require('webpack')\nconst DevServer = require('webpack-dev-server')\n\nconst webpackConfig = require('..\u002F..\u002Fbuild\u002Fwebpack.prod.conf')\nconst devConfigPromise = require('..\u002F..\u002Fbuild\u002Fwebpack.dev.conf')\n\nlet server\n\ndevConfigPromise.then(devConfig =\u003E {\n const devServerOptions = devConfig.devServer\n const compiler = webpack(webpackConfig)\n server = new DevServer(compiler, devServerOptions)\n const port = devServerOptions.port\n const host = devServerOptions.host\n return server.listen(port, host)\n})\n.then(() =\u003E {\n \u002F\u002F 2. run the nightwatch test suite against it\n \u002F\u002F to run in additional browsers:\n \u002F\u002F 1. add an entry in test\u002Fe2e\u002Fnightwatch.conf.json under \"test_settings\"\n \u002F\u002F 2. add it to the --env flag below\n \u002F\u002F or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`\n \u002F\u002F For more information on Nightwatch's config file, see\n \u002F\u002F http:\u002F\u002Fnightwatchjs.org\u002Fguide#settings-file\n let opts = process.argv.slice(2)\n if (opts.indexOf('--config') === -1) {\n opts = opts.concat(['--config', 'test\u002Fe2e\u002Fnightwatch.conf.js'])\n }\n if (opts.indexOf('--env') === -1) {\n opts = opts.concat(['--env', 'chrome'])\n }\n\n const spawn = require('cross-spawn')\n const runner = spawn('.\u002Fnode_modules\u002F.bin\u002Fnightwatch', opts, { stdio: 'inherit' })\n\n runner.on('exit', function (code) {\n server.close()\n process.exit(code)\n })\n\n runner.on('error', function (err) {\n server.close()\n throw err\n })\n})\n","id":"ab6ca86a-2033-4501-86c9-aa601bd4deda","is_binary":false,"title":"runner.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"HkFmeipy1zS","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"S1cxiTy1GS"},{"code":"\u002F\u002F For authoring Nightwatch tests, see\n\u002F\u002F http:\u002F\u002Fnightwatchjs.org\u002Fguide#usage\n\nmodule.exports = {\n 'default e2e tests': function test(browser) {\n \u002F\u002F automatically uses dev Server port from \u002Fconfig.index.js\n \u002F\u002F default: http:\u002F\u002Flocalhost:8080\n \u002F\u002F see nightwatch.conf.js\n const devServer = browser.globals.devServerURL;\n\n browser\n .url(devServer)\n .waitForElementVisible('#app', 5000)\n .assert.elementPresent('.featured')\n .end();\n },\n};\n","id":"c22ca41d-07bb-462b-b5a7-7e17bcc5e454","is_binary":false,"title":"test.js","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"HJq7ejaJ1zr","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rynxiTJkGB"},{"code":"{\n \"env\": { \n \"jest\": true\n },\n \"globals\": { \n }\n}\n","id":"dc8198c5-f353-484a-8977-44bd8f90958b","is_binary":false,"title":".eslintrc","sha":null,"inserted_at":"2019-07-19T07:13:28","updated_at":"2019-07-19T07:13:28","upload_id":null,"shortid":"S1i7gjTJyMB","source_id":"b7660600-deca-4918-97e6-b04dc1919459","directory_shortid":"rJ6xiaJyzH"}],"npm_dependencies":{},"template":"vue-cli","user_liked":false,"screenshot_url":"https:\u002F\u002Fscreenshots.codesandbox.io\u002F69v262mqn\u002F30.png","external_resources":[],"is_frozen":false,"picks":[],"forked_from_sandbox":null,"is_sse":false,"git":{"path":"","branch":"master","repo":"twitch-curi-demo","username":"pshrmn","commit_sha":"f823120279757279f541fd4a7dbff35ad1ebc484"},"npm_registries":[],"tags":[],"author":null,"v2":false,"forked_template":null,"original_git":null,"owned":false,"custom_template":null,"preview_secret":null,"authorization":"read","description":"A Curi demo that clones Twitch.tv","source_id":"b7660600-deca-4918-97e6-b04dc1919459","title":"twitch-curi","privacy":0};