@@ -0,0 +1,18 @@ | |||
{ | |||
"presets": [ | |||
["env", { | |||
"modules": false, | |||
"targets": { | |||
"browsers": ["> 1%", "last 2 versions", "not ie <= 11"] | |||
} | |||
}], | |||
"stage-2" | |||
], | |||
"plugins": ["transform-runtime"], | |||
"env": { | |||
"test": { | |||
"presets": ["env", "stage-2"], | |||
"plugins": [ "istanbul" ] | |||
} | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
root = true | |||
[*] | |||
charset = utf-8 | |||
indent_style = space | |||
indent_size = 4 | |||
end_of_line = lf | |||
insert_final_newline = true | |||
trim_trailing_whitespace = true |
@@ -0,0 +1,4 @@ | |||
/build/ | |||
/config/ | |||
/dist/ | |||
/*.js |
@@ -0,0 +1,27 @@ | |||
// http://eslint.org/docs/user-guide/configuring | |||
module.exports = { | |||
root: true, | |||
parser: 'babel-eslint', | |||
parserOptions: { | |||
sourceType: 'module' | |||
}, | |||
env: { | |||
browser: true, | |||
}, | |||
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style | |||
extends: 'standard', | |||
// required to lint *.vue files | |||
plugins: [ | |||
'html' | |||
], | |||
// add your custom rules here | |||
'rules': { | |||
// allow paren-less arrow functions | |||
'arrow-parens': 0, | |||
// allow async-await | |||
'generator-star-spacing': 0, | |||
// allow debugger during development | |||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
.DS_Store | |||
node_modules/ | |||
/dist/ | |||
npm-debug.log* | |||
yarn-debug.log* | |||
yarn-error.log* | |||
# Editor directories and files | |||
.idea | |||
*.suo | |||
*.ntvs* | |||
*.njsproj | |||
*.sln |
@@ -0,0 +1,8 @@ | |||
// https://github.com/michael-ciniawsky/postcss-load-config | |||
module.exports = { | |||
"plugins": { | |||
// to edit target browsers: use "browserlist" field in package.json | |||
"autoprefixer": {} | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
FROM nginx:latest | |||
COPY config/docker/nginx.conf /etc/nginx/conf.d | |||
@@ -0,0 +1,21 @@ | |||
# nexus-timers | |||
> Timers ans other features for Heroes of the Storm | |||
## Build Setup | |||
``` bash | |||
# install dependencies | |||
yarn | |||
# serve with hot reload at localhost:8080 | |||
yarn dev | |||
# build for production with minification | |||
yarn build | |||
# build for production and view the bundle analyzer report | |||
yarn build --report | |||
``` | |||
For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). |
@@ -0,0 +1,37 @@ | |||
'use strict' | |||
require('./check-versions')() | |||
process.env.NODE_ENV = 'production' | |||
const ora = require('ora') | |||
const rm = require('rimraf') | |||
const path = require('path') | |||
const chalk = require('chalk') | |||
const webpack = require('webpack') | |||
const config = require('../config') | |||
const webpackConfig = require('./webpack.prod.conf') | |||
const spinner = ora('building for production...') | |||
spinner.start() | |||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { | |||
if (err) throw err | |||
webpack(webpackConfig, function (err, stats) { | |||
spinner.stop() | |||
if (err) throw err | |||
process.stdout.write(stats.toString({ | |||
colors: true, | |||
modules: false, | |||
children: false, | |||
chunks: false, | |||
chunkModules: false | |||
}) + '\n\n') | |||
console.log(chalk.cyan(' Build complete.\n')) | |||
console.log(chalk.yellow( | |||
' Tip: built files are meant to be served over an HTTP server.\n' + | |||
' Opening index.html over file:// won\'t work.\n' | |||
)) | |||
}) | |||
}) |
@@ -0,0 +1,50 @@ | |||
'use strict' | |||
const chalk = require('chalk') | |||
const semver = require('semver') | |||
const packageConfig = require('../package.json') | |||
const shell = require('shelljs') | |||
function exec (cmd) { | |||
return require('child_process').execSync(cmd).toString().trim() | |||
} | |||
const versionRequirements = [ | |||
{ | |||
name: 'node', | |||
currentVersion: semver.clean(process.version), | |||
versionRequirement: packageConfig.engines.node | |||
}, | |||
] | |||
if (shell.which('npm')) { | |||
versionRequirements.push({ | |||
name: 'npm', | |||
currentVersion: exec('npm --version'), | |||
versionRequirement: packageConfig.engines.npm | |||
}) | |||
} | |||
module.exports = function () { | |||
const warnings = [] | |||
for (let i = 0; i < versionRequirements.length; i++) { | |||
const mod = versionRequirements[i] | |||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { | |||
warnings.push(mod.name + ': ' + | |||
chalk.red(mod.currentVersion) + ' should be ' + | |||
chalk.green(mod.versionRequirement) | |||
) | |||
} | |||
} | |||
if (warnings.length) { | |||
console.log('') | |||
console.log(chalk.yellow('To use this template, you must update following to modules:')) | |||
console.log() | |||
for (let i = 0; i < warnings.length; i++) { | |||
const warning = warnings[i] | |||
console.log(' ' + warning) | |||
} | |||
console.log() | |||
process.exit(1) | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
'use strict' | |||
/* eslint-disable */ | |||
require('eventsource-polyfill') | |||
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') | |||
hotClient.subscribe(function (event) { | |||
if (event.action === 'reload') { | |||
window.location.reload() | |||
} | |||
}) |
@@ -0,0 +1,91 @@ | |||
'use strict' | |||
require('./check-versions')() | |||
const config = require('../config') | |||
if (!process.env.NODE_ENV) { | |||
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) | |||
} | |||
const opn = require('opn') | |||
const path = require('path') | |||
const express = require('express') | |||
const webpack = require('webpack') | |||
const proxyMiddleware = require('http-proxy-middleware') | |||
const webpackConfig = require('./webpack.dev.conf') | |||
// default port where dev server listens for incoming traffic | |||
const port = process.env.PORT || config.dev.port | |||
// automatically open browser, if not set will be false | |||
const autoOpenBrowser = !!config.dev.autoOpenBrowser | |||
// Define HTTP proxies to your custom API backend | |||
// https://github.com/chimurai/http-proxy-middleware | |||
const proxyTable = config.dev.proxyTable | |||
const app = express() | |||
const compiler = webpack(webpackConfig) | |||
const devMiddleware = require('webpack-dev-middleware')(compiler, { | |||
publicPath: webpackConfig.output.publicPath, | |||
quiet: true | |||
}) | |||
const hotMiddleware = require('webpack-hot-middleware')(compiler, { | |||
log: false | |||
}) | |||
// force page reload when html-webpack-plugin template changes | |||
compiler.plugin('compilation', function (compilation) { | |||
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { | |||
hotMiddleware.publish({ action: 'reload' }) | |||
cb() | |||
}) | |||
}) | |||
// enable hot-reload and state-preserving | |||
// compilation error display | |||
app.use(hotMiddleware) | |||
// proxy api requests | |||
Object.keys(proxyTable).forEach(function (context) { | |||
let options = proxyTable[context] | |||
if (typeof options === 'string') { | |||
options = { target: options } | |||
} | |||
app.use(proxyMiddleware(options.filter || context, options)) | |||
}) | |||
// handle fallback for HTML5 history API | |||
app.use(require('connect-history-api-fallback')()) | |||
// serve webpack bundle output | |||
app.use(devMiddleware) | |||
// serve pure static assets | |||
const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) | |||
app.use(staticPath, express.static('./static')) | |||
const uri = 'http://localhost:' + port | |||
let _resolve | |||
const readyPromise = new Promise(resolve => { | |||
_resolve = resolve | |||
}) | |||
console.log('> Starting dev server...') | |||
devMiddleware.waitUntilValid(() => { | |||
console.log('> Listening at ' + uri + '\n') | |||
// when env is testing, don't need open it | |||
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { | |||
opn(uri) | |||
} | |||
_resolve() | |||
}) | |||
const server = app.listen(port) | |||
module.exports = { | |||
ready: readyPromise, | |||
close: () => { | |||
server.close() | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
'use strict' | |||
const fs = require('fs') | |||
const UglifyJS = require('uglify-es') | |||
module.exports = function(filePath) { | |||
const code = fs.readFileSync(filePath, 'utf-8') | |||
const result = UglifyJS.minify(code) | |||
if (result.error) return '' | |||
return result.code | |||
} |
@@ -0,0 +1,17 @@ | |||
// This service worker file is effectively a 'no-op' that will reset any | |||
// previous service worker registered for the same host:port combination. | |||
// In the production build, this file is replaced with an actual service worker | |||
// file that will precache your site's local assets. | |||
// See https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432 | |||
self.addEventListener('install', () => self.skipWaiting()); | |||
self.addEventListener('activate', () => { | |||
self.clients.matchAll({ type: 'window' }).then(windowClients => { | |||
for (let windowClient of windowClients) { | |||
// Force open pages to refresh, so that they have a chance to load the | |||
// fresh navigation response from the local dev server. | |||
windowClient.navigate(windowClient.url); | |||
} | |||
}); | |||
}); |
@@ -0,0 +1,55 @@ | |||
(function() { | |||
'use strict'; | |||
// Check to make sure service workers are supported in the current browser, | |||
// and that the current page is accessed from a secure origin. Using a | |||
// service worker from an insecure origin will trigger JS console errors. | |||
var isLocalhost = Boolean(window.location.hostname === 'localhost' || | |||
// [::1] is the IPv6 localhost address. | |||
window.location.hostname === '[::1]' || | |||
// 127.0.0.1/8 is considered localhost for IPv4. | |||
window.location.hostname.match( | |||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ | |||
) | |||
); | |||
window.addEventListener('load', function() { | |||
if ('serviceWorker' in navigator && | |||
(window.location.protocol === 'https:' || isLocalhost)) { | |||
navigator.serviceWorker.register('service-worker.js') | |||
.then(function(registration) { | |||
// updatefound is fired if service-worker.js changes. | |||
registration.onupdatefound = function() { | |||
// updatefound is also fired the very first time the SW is installed, | |||
// and there's no need to prompt for a reload at that point. | |||
// So check here to see if the page is already controlled, | |||
// i.e. whether there's an existing service worker. | |||
if (navigator.serviceWorker.controller) { | |||
// The updatefound event implies that registration.installing is set | |||
var installingWorker = registration.installing; | |||
installingWorker.onstatechange = function() { | |||
switch (installingWorker.state) { | |||
case 'installed': | |||
// At this point, the old content will have been purged and the | |||
// fresh content will have been added to the cache. | |||
// It's the perfect time to display a "New content is | |||
// available; please refresh." message in the page's interface. | |||
break; | |||
case 'redundant': | |||
throw new Error('The installing ' + | |||
'service worker became redundant.'); | |||
default: | |||
// Ignore | |||
} | |||
}; | |||
} | |||
}; | |||
}).catch(function(e) { | |||
console.error('Error during service worker registration:', e); | |||
}); | |||
} | |||
}); | |||
})(); |
@@ -0,0 +1,73 @@ | |||
'use strict' | |||
const path = require('path') | |||
const config = require('../config') | |||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | |||
exports.assetsPath = function (_path) { | |||
const assetsSubDirectory = process.env.NODE_ENV === 'production' | |||
? config.build.assetsSubDirectory | |||
: config.dev.assetsSubDirectory | |||
return path.posix.join(assetsSubDirectory, _path) | |||
} | |||
exports.cssLoaders = function (options) { | |||
options = options || {} | |||
const cssLoader = { | |||
loader: 'css-loader', | |||
options: { | |||
minimize: process.env.NODE_ENV === 'production', | |||
sourceMap: options.sourceMap | |||
} | |||
} | |||
// generate loader string to be used with extract text plugin | |||
function generateLoaders (loader, loaderOptions) { | |||
const loaders = [cssLoader] | |||
if (loader) { | |||
loaders.push({ | |||
loader: loader + '-loader', | |||
options: Object.assign({}, loaderOptions, { | |||
sourceMap: options.sourceMap | |||
}) | |||
}) | |||
} | |||
// Extract CSS when that option is specified | |||
// (which is the case during production build) | |||
if (options.extract) { | |||
return ExtractTextPlugin.extract({ | |||
use: loaders, | |||
fallback: 'vue-style-loader' | |||
}) | |||
} else { | |||
return ['vue-style-loader'].concat(loaders) | |||
} | |||
} | |||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html | |||
return { | |||
css: generateLoaders(), | |||
postcss: generateLoaders(), | |||
less: generateLoaders('less'), | |||
sass: generateLoaders('sass', { indentedSyntax: true }), | |||
scss: generateLoaders('sass'), | |||
stylus: generateLoaders('stylus'), | |||
styl: generateLoaders('stylus') | |||
} | |||
} | |||
// Generate loaders for standalone style files (outside of .vue) | |||
exports.styleLoaders = function (options) { | |||
const output = [] | |||
const loaders = exports.cssLoaders(options) | |||
for (const extension in loaders) { | |||
const loader = loaders[extension] | |||
output.push({ | |||
test: new RegExp('\\.' + extension + '$'), | |||
use: loader | |||
}) | |||
} | |||
return output | |||
} |
@@ -0,0 +1,20 @@ | |||
'use strict' | |||
const utils = require('./utils') | |||
const config = require('../config') | |||
const isProduction = process.env.NODE_ENV === 'production' | |||
module.exports = { | |||
loaders: utils.cssLoaders({ | |||
sourceMap: isProduction | |||
? config.build.productionSourceMap | |||
: config.dev.cssSourceMap, | |||
extract: isProduction | |||
}), | |||
transformToRequire: { | |||
video: ['src', 'poster'], | |||
source: 'src', | |||
img: 'src', | |||
image: 'xlink:href' | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
'use strict' | |||
const path = require('path') | |||
const utils = require('./utils') | |||
const config = require('../config') | |||
const vueLoaderConfig = require('./vue-loader.conf') | |||
function resolve (dir) { | |||
return path.join(__dirname, '..', dir) | |||
} | |||
module.exports = { | |||
entry: { | |||
app: './src/main.js' | |||
}, | |||
output: { | |||
path: config.build.assetsRoot, | |||
filename: '[name].js', | |||
publicPath: process.env.NODE_ENV === 'production' | |||
? config.build.assetsPublicPath | |||
: config.dev.assetsPublicPath | |||
}, | |||
resolve: { | |||
extensions: ['.js', '.vue', '.json'], | |||
alias: { | |||
'vue$': 'vue/dist/vue.esm.js', | |||
'@': resolve('src') | |||
} | |||
}, | |||
module: { | |||
rules: [ | |||
{ | |||
test: /\.(js|vue)$/, | |||
loader: 'eslint-loader', | |||
enforce: 'pre', | |||
include: [resolve('src'), resolve('test')], | |||
options: { | |||
formatter: require('eslint-friendly-formatter') | |||
} | |||
}, | |||
{ | |||
test: /\.vue$/, | |||
loader: 'vue-loader', | |||
options: vueLoaderConfig | |||
}, | |||
{ | |||
test: /\.js$/, | |||
loader: 'babel-loader', | |||
include: [resolve('src'), resolve('test')] | |||
}, | |||
{ | |||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, | |||
loader: 'url-loader', | |||
options: { | |||
limit: 10000, | |||
name: utils.assetsPath('img/[name].[hash:7].[ext]') | |||
} | |||
}, | |||
{ | |||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, | |||
loader: 'url-loader', | |||
options: { | |||
limit: 10000, | |||
name: utils.assetsPath('media/[name].[hash:7].[ext]') | |||
} | |||
}, | |||
{ | |||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, | |||
loader: 'url-loader', | |||
options: { | |||
limit: 10000, | |||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]') | |||
} | |||
} | |||
] | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
'use strict' | |||
const fs = require('fs') | |||
const path = require('path') | |||
const utils = require('./utils') | |||
const webpack = require('webpack') | |||
const config = require('../config') | |||
const merge = require('webpack-merge') | |||
const baseWebpackConfig = require('./webpack.base.conf') | |||
const HtmlWebpackPlugin = require('html-webpack-plugin') | |||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') | |||
// add hot-reload related code to entry chunks | |||
Object.keys(baseWebpackConfig.entry).forEach(function (name) { | |||
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) | |||
}) | |||
module.exports = merge(baseWebpackConfig, { | |||
module: { | |||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) | |||
}, | |||
// cheap-module-eval-source-map is faster for development | |||
devtool: '#cheap-module-eval-source-map', | |||
plugins: [ | |||
new webpack.DefinePlugin({ | |||
'process.env': config.dev.env | |||
}), | |||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage | |||
new webpack.HotModuleReplacementPlugin(), | |||
new webpack.NoEmitOnErrorsPlugin(), | |||
// https://github.com/ampedandwired/html-webpack-plugin | |||
new HtmlWebpackPlugin({ | |||
filename: 'index.html', | |||
template: 'index.html', | |||
inject: true, | |||
serviceWorkerLoader: `<script>${fs.readFileSync(path.join(__dirname, | |||
'./service-worker-dev.js'), 'utf-8')}</script>` | |||
}), | |||
new FriendlyErrorsPlugin() | |||
] | |||
}) |
@@ -0,0 +1,135 @@ | |||
'use strict' | |||
const fs = require('fs') | |||
const path = require('path') | |||
const utils = require('./utils') | |||
const webpack = require('webpack') | |||
const config = require('../config') | |||
const merge = require('webpack-merge') | |||
const baseWebpackConfig = require('./webpack.base.conf') | |||
const CopyWebpackPlugin = require('copy-webpack-plugin') | |||
const HtmlWebpackPlugin = require('html-webpack-plugin') | |||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | |||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') | |||
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin') | |||
const loadMinified = require('./load-minified') | |||
const env = config.build.env | |||
const webpackConfig = merge(baseWebpackConfig, { | |||
module: { | |||
rules: utils.styleLoaders({ | |||
sourceMap: config.build.productionSourceMap, | |||
extract: true | |||
}) | |||
}, | |||
devtool: config.build.productionSourceMap ? '#source-map' : false, | |||
output: { | |||
path: config.build.assetsRoot, | |||
filename: utils.assetsPath('js/[name].[chunkhash].js'), | |||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') | |||
}, | |||
plugins: [ | |||
// http://vuejs.github.io/vue-loader/en/workflow/production.html | |||
new webpack.DefinePlugin({ | |||
'process.env': env | |||
}), | |||
new webpack.optimize.UglifyJsPlugin({ | |||
compress: { | |||
warnings: false | |||
}, | |||
sourceMap: true | |||
}), | |||
// extract css into its own file | |||
new ExtractTextPlugin({ | |||
filename: utils.assetsPath('css/[name].[contenthash].css') | |||
}), | |||
// Compress extracted CSS. We are using this plugin so that possible | |||
// duplicated CSS from different components can be deduped. | |||
new OptimizeCSSPlugin({ | |||
cssProcessorOptions: { | |||
safe: true | |||
} | |||
}), | |||
// generate dist index.html with correct asset hash for caching. | |||
// you can customize output by editing /index.html | |||
// see https://github.com/ampedandwired/html-webpack-plugin | |||
new HtmlWebpackPlugin({ | |||
filename: config.build.index, | |||
template: 'index.html', | |||
inject: true, | |||
minify: { | |||
removeComments: true, | |||
collapseWhitespace: true, | |||
removeAttributeQuotes: true | |||
// more options: | |||
// https://github.com/kangax/html-minifier#options-quick-reference | |||
}, | |||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin | |||
chunksSortMode: 'dependency', | |||
serviceWorkerLoader: `<script>${loadMinified(path.join(__dirname, | |||
'./service-worker-prod.js'))}</script>` | |||
}), | |||
// split vendor js into its own file | |||
new webpack.optimize.CommonsChunkPlugin({ | |||
name: 'vendor', | |||
minChunks: function (module, count) { | |||
// any required modules inside node_modules are extracted to vendor | |||
return ( | |||
module.resource && | |||
/\.js$/.test(module.resource) && | |||
module.resource.indexOf( | |||
path.join(__dirname, '../node_modules') | |||
) === 0 | |||
) | |||
} | |||
}), | |||
// extract webpack runtime and module manifest to its own file in order to | |||
// prevent vendor hash from being updated whenever app bundle is updated | |||
new webpack.optimize.CommonsChunkPlugin({ | |||
name: 'manifest', | |||
chunks: ['vendor'] | |||
}), | |||
// copy custom static assets | |||
new CopyWebpackPlugin([ | |||
{ | |||
from: path.resolve(__dirname, '../static'), | |||
to: config.build.assetsSubDirectory, | |||
ignore: ['.*'] | |||
} | |||
]), | |||
// service worker caching | |||
new SWPrecacheWebpackPlugin({ | |||
cacheId: 'nexus-timers', | |||
filename: 'service-worker.js', | |||
staticFileGlobs: ['dist/**/*.{js,html,css}'], | |||
minify: true, | |||
stripPrefix: 'dist/' | |||
}) | |||
] | |||
}) | |||
if (config.build.productionGzip) { | |||
const CompressionWebpackPlugin = require('compression-webpack-plugin') | |||
webpackConfig.plugins.push( | |||
new CompressionWebpackPlugin({ | |||
asset: '[path].gz[query]', | |||
algorithm: 'gzip', | |||
test: new RegExp( | |||
'\\.(' + | |||
config.build.productionGzipExtensions.join('|') + | |||
')$' | |||
), | |||
threshold: 10240, | |||
minRatio: 0.8 | |||
}) | |||
) | |||
} | |||
if (config.build.bundleAnalyzerReport) { | |||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin | |||
webpackConfig.plugins.push(new BundleAnalyzerPlugin()) | |||
} | |||
module.exports = webpackConfig |
@@ -0,0 +1,8 @@ | |||
'use strict' | |||
const merge = require('webpack-merge') | |||
const prodEnv = require('./prod.env') | |||
module.exports = merge(prodEnv, { | |||
NODE_ENV: '"development"' | |||
}) |
@@ -0,0 +1,10 @@ | |||
server { | |||
listen 80; | |||
server_name nexus-timers.local.tld; | |||
root /usr/share/nginx/html/dist; | |||
access_log /var/log/nginx/nexus-timers.access.log; | |||
error_log /var/log/nginx/nexus-timers.error.log; | |||
} |
@@ -0,0 +1,40 @@ | |||
'use strict' | |||
// see http://vuejs-templates.github.io/webpack for documentation. | |||
const path = require('path') | |||
module.exports = { | |||
build: { | |||
env: require('./prod.env'), | |||
index: path.resolve(__dirname, '../dist/index.html'), | |||
assetsRoot: path.resolve(__dirname, '../dist'), | |||
assetsSubDirectory: 'static', | |||
assetsPublicPath: '/', | |||
productionSourceMap: true, | |||
// Gzip off by default as many popular static hosts such as | |||
// Surge or Netlify already gzip all static assets for you. | |||
// Before setting to `true`, make sure to: | |||
// npm install --save-dev compression-webpack-plugin | |||
productionGzip: false, | |||
productionGzipExtensions: ['js', 'css'], | |||
// Run the build command with an extra argument to | |||
// View the bundle analyzer report after build finishes: | |||
// `npm run build --report` | |||
// Set to `true` or `false` to always turn it on or off | |||
bundleAnalyzerReport: process.env.npm_config_report | |||
}, | |||
dev: { | |||
env: require('./dev.env'), | |||
port: 8080, | |||
autoOpenBrowser: true, | |||
assetsSubDirectory: 'static', | |||
assetsPublicPath: '/', | |||
proxyTable: {}, | |||
// CSS Sourcemaps off by default because relative paths are "buggy" | |||
// with this option, according to the CSS-Loader README | |||
// (https://github.com/webpack/css-loader#sourcemaps) | |||
// In our experience, they generally work as expected, | |||
// just be aware of this issue when enabling this option. | |||
cssSourceMap: true | |||
} | |||
} |
@@ -0,0 +1,3 @@ | |||
module.exports = { | |||
NODE_ENV: '"production"' | |||
} |
@@ -0,0 +1,6 @@ | |||
nexus-timers: | |||
build: . | |||
volumes: | |||
- .:/usr/share/nginx/html | |||
ports: | |||
- 80:80 |
@@ -0,0 +1,39 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||
<title>nexus-timers</title> | |||
<link rel="icon" type="image/png" sizes="32x32" href="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/favicon-32x32.png"> | |||
<link rel="icon" type="image/png" sizes="16x16" href="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/favicon-16x16.png"> | |||
<!--[if IE]><link rel="shortcut icon" href="/static/img/icons/favicon.ico"><![endif]--> | |||
<!-- Add to home screen for Android and modern mobile browsers --> | |||
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>static/manifest.json"> | |||
<meta name="theme-color" content="#4DBA87"> | |||
<!-- Add to home screen for Safari on iOS --> | |||
<meta name="apple-mobile-web-app-capable" content="yes"> | |||
<meta name="apple-mobile-web-app-status-bar-style" content="black"> | |||
<meta name="apple-mobile-web-app-title" content="nexus-timers"> | |||
<link rel="apple-touch-icon" href="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/apple-touch-icon-152x152.png"> | |||
<link rel="mask-icon" href="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/safari-pinned-tab.svg" color="#4DBA87"> | |||
<!-- Add to home screen for Windows --> | |||
<meta name="msapplication-TileImage" content="<%= htmlWebpackPlugin.files.publicPath %>static/img/icons/msapplication-icon-144x144.png"> | |||
<meta name="msapplication-TileColor" content="#000000"> | |||
<% for (var chunk of webpack.chunks) { | |||
for (var file of chunk.files) { | |||
if (file.match(/\.(js|css)$/)) { %> | |||
<link rel="<%= chunk.initial?'preload':'prefetch' %>" href="<%= htmlWebpackPlugin.files.publicPath + file %>" as="<%= file.match(/\.css$/)?'style':'script' %>"><% }}} %> | |||
</head> | |||
<body> | |||
<noscript> | |||
This application can only work with JavaScript enabled. <br /> | |||
Please enable JavaScript on your browser. | |||
</noscript> | |||
<div id="app"></div> | |||
<!-- Todo: only include in production --> | |||
<%= htmlWebpackPlugin.options.serviceWorkerLoader %> | |||
<!-- built files will be auto injected --> | |||
</body> | |||
</html> |
@@ -0,0 +1,74 @@ | |||
{ | |||
"name": "nexus-timers", | |||
"version": "1.0.0", | |||
"description": "Timers ans other features for Heroes of the Storm", | |||
"author": "Adrien Agez <adrien.agez@hotmail.fr>", | |||
"private": true, | |||
"scripts": { | |||
"dev": "node build/dev-server.js", | |||
"start": "node build/dev-server.js", | |||
"build": "node build/build.js", | |||
"lint": "eslint --ext .js,.vue src" | |||
}, | |||
"dependencies": { | |||
"vue": "^2.5.2", | |||
"vue-router": "^3.0.1" | |||
}, | |||
"devDependencies": { | |||
"autoprefixer": "^7.1.5", | |||
"babel-core": "^6.26.0", | |||
"sw-precache-webpack-plugin": "^0.11.4", | |||
"babel-eslint": "^8.0.1", | |||
"babel-loader": "^7.1.2", | |||
"babel-plugin-transform-runtime": "^6.23.0", | |||
"babel-preset-env": "^1.6.0", | |||
"babel-preset-stage-2": "^6.24.1", | |||
"babel-register": "^6.26.0", | |||
"chalk": "^2.1.0", | |||
"connect-history-api-fallback": "^1.4.0", | |||
"copy-webpack-plugin": "^4.1.1", | |||
"css-loader": "^0.28.7", | |||
"cssnano": "^3.10.0", | |||
"eslint": "^4.9.0", | |||
"eslint-friendly-formatter": "^3.0.0", | |||
"eslint-loader": "^1.9.0", | |||
"eslint-plugin-html": "^3.2.2", | |||
"eslint-plugin-import": "^2.7.0", | |||
"eslint-plugin-node": "^5.2.0", | |||
"eslint-config-standard": "^10.2.1", | |||
"eslint-plugin-promise": "^3.6.0", | |||
"eslint-plugin-standard": "^3.0.1", | |||
"eventsource-polyfill": "^0.9.6", | |||
"express": "^4.16.2", | |||
"extract-text-webpack-plugin": "^3.0.0", | |||
"file-loader": "^1.1.5", | |||
"friendly-errors-webpack-plugin": "^1.6.1", | |||
"html-webpack-plugin": "^2.30.1", | |||
"http-proxy-middleware": "^0.17.4", | |||
"webpack-bundle-analyzer": "^2.9.0", | |||
"semver": "^5.4.1", | |||
"shelljs": "^0.7.8", | |||
"opn": "^5.1.0", | |||
"optimize-css-assets-webpack-plugin": "^3.2.0", | |||
"ora": "^1.3.0", | |||
"rimraf": "^2.6.2", | |||
"url-loader": "^0.6.2", | |||
"vue-loader": "^13.3.0", | |||
"vue-style-loader": "^3.0.3", | |||
"vue-template-compiler": "^2.5.2", | |||
"webpack": "^3.7.1", | |||
"webpack-dev-middleware": "^1.12.0", | |||
"webpack-hot-middleware": "^2.19.1", | |||
"webpack-merge": "^4.1.0", | |||
"uglify-es": "^3.1.3" | |||
}, | |||
"engines": { | |||
"node": ">= 4.0.0", | |||
"npm": ">= 3.0.0" | |||
}, | |||
"browserslist": [ | |||
"> 1%", | |||
"last 2 versions", | |||
"not IE <= 11" | |||
] | |||
} |
@@ -0,0 +1,54 @@ | |||
<template> | |||
<div id="app"> | |||
<header> | |||
<span>Vue.js PWA</span> | |||
</header> | |||
<main> | |||
<img src="./assets/logo.png" alt="Vue.js PWA"> | |||
<router-view></router-view> | |||
</main> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'app' | |||
} | |||
</script> | |||
<style> | |||
body { | |||
margin: 0; | |||
} | |||
#app { | |||
font-family: 'Avenir', Helvetica, Arial, sans-serif; | |||
-webkit-font-smoothing: antialiased; | |||
-moz-osx-font-smoothing: grayscale; | |||
color: #2c3e50; | |||
} | |||
main { | |||
text-align: center; | |||
margin-top: 40px; | |||
} | |||
header { | |||
margin: 0; | |||
height: 56px; | |||
padding: 0 16px 0 24px; | |||
background-color: #35495E; | |||
color: #ffffff; | |||
} | |||
header span { | |||
display: block; | |||
position: relative; | |||
font-size: 20px; | |||
line-height: 1; | |||
letter-spacing: .02em; | |||
font-weight: 400; | |||
box-sizing: border-box; | |||
padding-top: 16px; | |||
} | |||
</style> |
@@ -0,0 +1,52 @@ | |||
<template> | |||
<div class="hello"> | |||
<h1>{{ msg }}</h1> | |||
<h2>Essential Links</h2> | |||
<ul> | |||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li> | |||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li> | |||
<li><a href="http://chat.vuejs.org/" target="_blank" rel="noopener">Vue Community Chat</a></li> | |||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li> | |||
<li><a href="http://vuejs-templates.github.io/webpack/" target="_blank" rel="noopener">Docs for This Template</a></li> | |||
</ul> | |||
<h2>Ecosystem</h2> | |||
<ul> | |||
<li><a href="http://router.vuejs.org/" target="_blank" rel="noopener">vue-router</a></li> | |||
<li><a href="http://vuex.vuejs.org/" target="_blank" rel="noopener">vuex</a></li> | |||
<li><a href="http://vue-loader.vuejs.org/" target="_blank" rel="noopener">vue-loader</a></li> | |||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> | |||
</ul> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'hello', | |||
data () { | |||
return { | |||
msg: 'Welcome to Your Vue.js PWA' | |||
} | |||
} | |||
} | |||
</script> | |||
<!-- Add "scoped" attribute to limit CSS to this component only --> | |||
<style> | |||
h1, h2 { | |||
font-weight: normal; | |||
} | |||
ul { | |||
list-style-type: none; | |||
padding: 0; | |||
} | |||
li { | |||
display: inline-block; | |||
margin: 0 10px; | |||
} | |||
a { | |||
color: #35495E; | |||
} | |||
</style> |
@@ -0,0 +1,15 @@ | |||
// The Vue build version to load with the `import` command | |||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias. | |||
import Vue from 'vue' | |||
import App from './App' | |||
import router from './router' | |||
Vue.config.productionTip = false | |||
/* eslint-disable no-new */ | |||
new Vue({ | |||
el: '#app', | |||
router, | |||
template: '<App/>', | |||
components: { App } | |||
}) |
@@ -0,0 +1,15 @@ | |||
import Vue from 'vue' | |||
import Router from 'vue-router' | |||
import Hello from '@/components/Hello' | |||
Vue.use(Router) | |||
export default new Router({ | |||
routes: [ | |||
{ | |||
path: '/', | |||
name: 'Hello', | |||
component: Hello | |||
} | |||
] | |||
}) |
@@ -0,0 +1,149 @@ | |||
<?xml version="1.0" standalone="no"?> | |||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" | |||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> | |||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" | |||
width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000" | |||
preserveAspectRatio="xMidYMid meet"> | |||
<metadata> | |||
Created by potrace 1.11, written by Peter Selinger 2001-2013 | |||
</metadata> | |||
<g transform="translate(0.000000,16.000000) scale(0.000320,-0.000320)" | |||
fill="#000000" stroke="none"> | |||
<path d="M18 46618 c45 -75 122 -207 122 -211 0 -2 25 -45 55 -95 30 -50 55 | |||
-96 55 -102 0 -5 5 -10 10 -10 6 0 10 -4 10 -9 0 -5 73 -135 161 -288 89 -153 | |||
173 -298 187 -323 14 -25 32 -57 41 -72 88 -149 187 -324 189 -335 2 -7 8 -13 | |||
13 -13 5 0 9 -4 9 -10 0 -5 46 -89 103 -187 175 -302 490 -846 507 -876 8 -16 | |||
20 -36 25 -45 28 -46 290 -498 339 -585 13 -23 74 -129 136 -236 61 -107 123 | |||
-215 137 -240 14 -25 29 -50 33 -56 5 -5 23 -37 40 -70 18 -33 38 -67 44 -75 | |||
11 -16 21 -33 63 -109 14 -25 29 -50 33 -56 4 -5 21 -35 38 -65 55 -100 261 | |||
-455 269 -465 4 -5 14 -21 20 -35 15 -29 41 -75 103 -180 24 -41 52 -88 60 | |||
-105 9 -16 57 -100 107 -185 112 -193 362 -626 380 -660 8 -14 23 -38 33 -55 | |||
11 -16 23 -37 27 -45 4 -8 26 -46 48 -85 23 -38 53 -90 67 -115 46 -81 64 | |||
-113 178 -310 62 -107 121 -210 132 -227 37 -67 56 -99 85 -148 16 -27 32 -57 | |||
36 -65 4 -8 15 -27 25 -42 9 -15 53 -89 96 -165 44 -76 177 -307 296 -513 120 | |||
-206 268 -463 330 -570 131 -227 117 -203 200 -348 36 -62 73 -125 82 -140 10 | |||
-15 21 -34 25 -42 4 -8 20 -37 36 -65 17 -27 38 -65 48 -82 49 -85 64 -111 87 | |||
-153 13 -25 28 -49 32 -55 4 -5 78 -134 165 -285 87 -151 166 -288 176 -305 | |||
10 -16 26 -43 35 -59 9 -17 125 -217 257 -445 132 -229 253 -441 270 -471 17 | |||
-30 45 -79 64 -108 18 -29 33 -54 33 -57 0 -2 20 -37 44 -77 24 -40 123 -212 | |||
221 -383 97 -170 190 -330 205 -355 16 -25 39 -65 53 -90 13 -25 81 -144 152 | |||
-265 70 -121 137 -238 150 -260 12 -22 37 -65 55 -95 18 -30 43 -73 55 -95 12 | |||
-22 48 -85 80 -140 77 -132 163 -280 190 -330 13 -22 71 -123 130 -225 59 | |||
-102 116 -199 126 -217 10 -17 29 -50 43 -72 15 -22 26 -43 26 -45 0 -2 27 | |||
-50 60 -106 33 -56 60 -103 60 -105 0 -2 55 -98 90 -155 8 -14 182 -316 239 | |||
-414 13 -22 45 -79 72 -124 27 -46 49 -86 49 -89 0 -2 14 -24 30 -48 16 -24 | |||
30 -46 30 -49 0 -5 74 -135 100 -176 5 -8 24 -42 43 -75 50 -88 58 -101 262 | |||
-455 104 -179 199 -345 213 -370 14 -25 28 -49 32 -55 4 -5 17 -26 28 -45 10 | |||
-19 62 -109 114 -200 114 -197 133 -230 170 -295 16 -27 33 -57 38 -65 17 -28 | |||
96 -165 103 -180 4 -8 16 -28 26 -45 10 -16 77 -131 148 -255 72 -124 181 | |||
-313 243 -420 62 -107 121 -209 131 -227 35 -62 323 -560 392 -678 38 -66 83 | |||
-145 100 -175 16 -30 33 -59 37 -65 4 -5 17 -27 29 -47 34 -61 56 -100 90 | |||
-156 17 -29 31 -55 31 -57 0 -2 17 -32 39 -67 21 -35 134 -229 251 -433 117 | |||
-203 235 -407 261 -451 27 -45 49 -85 49 -88 0 -4 8 -19 19 -34 15 -21 200 | |||
-341 309 -533 10 -19 33 -58 51 -87 17 -29 31 -54 31 -56 0 -2 25 -44 55 -94 | |||
30 -50 55 -95 55 -98 0 -4 6 -15 14 -23 7 -9 27 -41 43 -71 17 -30 170 -297 | |||
342 -594 171 -296 311 -542 311 -547 0 -5 5 -9 10 -9 6 0 10 -4 10 -10 0 -5 | |||
22 -47 49 -92 27 -46 58 -99 68 -118 24 -43 81 -140 93 -160 5 -8 66 -114 135 | |||
-235 69 -121 130 -227 135 -235 12 -21 259 -447 283 -490 10 -19 28 -47 38 | |||
-62 11 -14 19 -29 19 -32 0 -3 37 -69 83 -148 99 -170 305 -526 337 -583 13 | |||
-22 31 -53 41 -70 11 -16 22 -37 26 -45 7 -14 82 -146 103 -180 14 -24 181 | |||
-311 205 -355 13 -22 46 -80 75 -130 29 -49 64 -110 78 -135 14 -25 51 -88 82 | |||
-140 31 -52 59 -102 63 -110 4 -8 18 -33 31 -55 205 -353 284 -489 309 -535 | |||
17 -30 45 -78 62 -106 18 -28 36 -60 39 -72 4 -12 12 -22 17 -22 5 0 9 -4 9 | |||
-10 0 -5 109 -197 241 -427 133 -230 250 -431 259 -448 51 -90 222 -385 280 | |||
-485 37 -63 78 -135 92 -160 14 -25 67 -117 118 -205 51 -88 101 -175 111 | |||
-193 34 -58 55 -95 149 -257 51 -88 101 -173 110 -190 9 -16 76 -131 147 -255 | |||
72 -124 140 -241 151 -260 61 -108 281 -489 355 -615 38 -66 77 -133 87 -150 | |||
35 -63 91 -161 100 -175 14 -23 99 -169 128 -220 54 -97 135 -235 142 -245 4 | |||
-5 20 -32 35 -60 26 -48 238 -416 276 -480 10 -16 26 -46 37 -65 30 -53 382 | |||
-661 403 -695 10 -16 22 -37 26 -45 4 -8 26 -48 50 -88 24 -41 43 -75 43 -77 | |||
0 -2 22 -40 50 -85 27 -45 50 -84 50 -86 0 -3 38 -69 83 -147 84 -142 302 | |||
-520 340 -587 10 -19 34 -60 52 -90 18 -30 44 -75 57 -100 14 -25 45 -79 70 | |||
-120 25 -41 56 -96 70 -121 14 -25 77 -133 138 -240 62 -107 122 -210 132 | |||
-229 25 -43 310 -535 337 -581 11 -19 26 -45 34 -59 17 -32 238 -414 266 -460 | |||
11 -19 24 -41 28 -49 3 -7 75 -133 160 -278 84 -146 153 -269 153 -274 0 -5 5 | |||
-9 10 -9 6 0 10 -4 10 -10 0 -5 82 -150 181 -322 182 -314 201 -346 240 -415 | |||
12 -21 80 -139 152 -263 71 -124 141 -245 155 -270 14 -25 28 -49 32 -55 6 -8 | |||
145 -248 220 -380 37 -66 209 -362 229 -395 11 -19 24 -42 28 -49 4 -8 67 | |||
-118 140 -243 73 -125 133 -230 133 -233 0 -2 15 -28 33 -57 19 -29 47 -78 64 | |||
-108 17 -30 53 -93 79 -139 53 -90 82 -141 157 -272 82 -142 115 -199 381 | |||
-659 142 -245 268 -463 281 -485 12 -22 71 -125 132 -230 60 -104 172 -298 | |||
248 -430 76 -132 146 -253 156 -270 11 -16 22 -36 26 -44 3 -8 30 -54 60 -103 | |||
29 -49 53 -91 53 -93 0 -3 18 -34 40 -70 22 -36 40 -67 40 -69 0 -2 37 -66 81 | |||
-142 45 -77 98 -168 119 -204 20 -36 47 -81 58 -100 12 -19 27 -47 33 -62 6 | |||
-16 15 -28 20 -28 5 0 9 -4 9 -9 0 -6 63 -118 140 -251 77 -133 140 -243 140 | |||
-245 0 -2 18 -33 41 -70 22 -37 49 -83 60 -101 10 -19 29 -51 40 -71 25 -45 | |||
109 -189 126 -218 7 -11 17 -29 22 -40 6 -11 22 -38 35 -60 14 -22 37 -62 52 | |||
-90 14 -27 35 -62 45 -77 11 -14 19 -29 19 -32 0 -3 18 -35 40 -71 22 -36 40 | |||
-67 40 -69 0 -2 19 -35 42 -72 23 -38 55 -94 72 -124 26 -47 139 -244 171 | |||
-298 6 -9 21 -36 34 -60 28 -48 37 -51 51 -19 6 12 19 36 29 52 10 17 27 46 | |||
38 65 11 19 104 181 208 360 103 179 199 345 213 370 14 25 42 74 64 109 21 | |||
34 38 65 38 67 0 2 18 33 40 69 22 36 40 67 40 69 0 3 177 310 199 346 16 26 | |||
136 234 140 244 2 5 25 44 52 88 27 44 49 81 49 84 0 2 18 34 40 70 22 36 40 | |||
67 40 69 0 2 20 36 43 77 35 58 169 289 297 513 9 17 50 86 90 155 40 69 86 | |||
150 103 180 16 30 35 62 41 70 6 8 16 24 22 35 35 64 72 129 167 293 59 100 | |||
116 199 127 220 11 20 30 53 41 72 43 72 1070 1850 1121 1940 14 25 65 113 | |||
113 195 48 83 96 166 107 185 10 19 28 50 38 68 11 18 73 124 137 235 64 111 | |||
175 303 246 427 71 124 173 299 225 390 52 91 116 202 143 248 27 45 49 85 49 | |||
89 0 4 6 14 14 22 7 9 28 43 46 76 26 47 251 436 378 655 11 19 29 51 40 70 | |||
11 19 101 176 201 348 99 172 181 317 181 323 0 5 5 9 10 9 6 0 10 5 10 11 0 | |||
6 8 23 18 37 11 15 32 52 49 82 16 30 130 228 253 440 122 212 234 405 248 | |||
430 13 25 39 70 57 100 39 65 69 117 130 225 25 44 50 87 55 95 12 19 78 134 | |||
220 380 61 107 129 224 150 260 161 277 222 382 246 425 15 28 47 83 71 123 | |||
24 41 43 78 43 83 0 5 4 9 8 9 4 0 13 12 19 28 7 15 23 45 36 67 66 110 277 | |||
478 277 483 0 3 6 13 14 21 7 9 27 41 43 71 17 30 45 80 63 110 34 57 375 649 | |||
394 685 6 11 16 27 22 35 6 8 26 42 44 75 18 33 41 74 51 90 10 17 24 41 32 | |||
55 54 97 72 128 88 152 11 14 19 28 19 30 0 3 79 141 175 308 96 167 175 305 | |||
175 308 0 3 6 13 14 21 7 9 26 39 41 66 33 60 276 483 338 587 24 40 46 80 50 | |||
88 4 8 13 24 20 35 14 23 95 163 125 215 11 19 52 91 92 160 40 69 80 139 90 | |||
155 9 17 103 179 207 360 105 182 200 346 211 365 103 181 463 802 489 845 7 | |||
11 15 27 19 35 4 8 29 51 55 95 64 110 828 1433 848 1470 9 17 24 41 33 55 9 | |||
14 29 48 45 77 15 28 52 93 82 145 30 51 62 107 71 123 17 30 231 398 400 690 | |||
51 88 103 179 115 202 12 23 26 48 32 55 6 7 24 38 40 68 17 30 61 107 98 170 | |||
37 63 84 144 103 180 19 36 41 72 48 81 8 8 14 18 14 21 0 4 27 51 59 106 32 | |||
55 72 124 89 154 16 29 71 125 122 213 51 88 104 180 118 205 13 25 28 50 32 | |||
55 4 6 17 26 28 45 11 19 45 80 77 135 31 55 66 116 77 135 11 19 88 152 171 | |||
295 401 694 620 1072 650 1125 11 19 87 152 170 295 83 143 158 273 166 288 9 | |||
16 21 36 26 45 6 9 31 52 55 96 25 43 54 94 66 115 11 20 95 164 186 321 91 | |||
157 173 299 182 315 9 17 26 46 37 65 12 19 66 114 121 210 56 96 108 186 117 | |||
200 8 14 24 40 34 59 24 45 383 664 412 713 5 9 17 29 26 45 15 28 120 210 | |||
241 419 36 61 68 117 72 125 4 8 12 23 19 34 35 57 245 420 262 453 11 20 35 | |||
61 53 90 17 29 32 54 32 56 0 3 28 51 62 108 33 57 70 119 80 138 10 19 23 42 | |||
28 50 5 8 32 53 59 100 27 47 149 258 271 470 122 212 234 405 248 430 30 53 | |||
62 108 80 135 6 11 15 27 19 35 4 8 85 150 181 315 96 165 187 323 202 350 31 | |||
56 116 202 130 225 5 8 25 42 43 75 19 33 92 159 162 280 149 257 157 271 202 | |||
350 19 33 38 67 43 75 9 14 228 392 275 475 12 22 55 96 95 165 40 69 80 139 | |||
90 155 24 42 202 350 221 383 9 15 27 47 41 72 14 25 75 131 136 236 61 106 | |||
121 210 134 232 99 172 271 470 279 482 5 8 23 40 40 70 18 30 81 141 142 245 | |||
60 105 121 210 135 235 14 25 71 124 127 220 56 96 143 247 194 335 51 88 96 | |||
167 102 175 14 24 180 311 204 355 23 43 340 590 356 615 5 8 50 87 101 175 | |||
171 301 517 898 582 1008 25 43 46 81 46 83 0 2 12 23 27 47 14 23 40 67 56 | |||
97 16 30 35 62 42 70 7 8 15 22 18 30 4 8 20 38 37 65 16 28 33 57 37 65 6 12 | |||
111 196 143 250 5 8 55 95 112 193 57 98 113 195 126 215 12 20 27 46 32 57 6 | |||
11 14 27 20 35 5 8 76 130 156 270 80 140 165 287 187 325 23 39 52 90 66 115 | |||
13 25 30 52 37 61 8 8 14 18 14 21 0 4 41 77 92 165 50 87 175 302 276 478 | |||
101 176 208 360 236 408 28 49 67 117 86 152 19 35 41 70 48 77 6 6 12 15 12 | |||
19 0 7 124 224 167 291 12 21 23 40 23 42 0 2 21 40 46 83 26 43 55 92 64 109 | |||
54 95 327 568 354 614 19 30 45 75 59 100 71 128 82 145 89 148 4 2 8 8 8 13 | |||
0 5 42 82 94 172 311 538 496 858 518 897 14 25 40 70 58 100 18 30 42 71 53 | |||
90 10 19 79 139 152 265 73 127 142 246 153 265 10 19 43 76 72 125 29 50 63 | |||
108 75 130 65 116 80 140 87 143 4 2 8 8 8 12 0 8 114 212 140 250 6 8 14 24 | |||
20 35 5 11 54 97 108 190 l100 170 -9611 3 c-5286 1 -9614 -1 -9618 -5 -5 -6 | |||
-419 -719 -619 -1068 -89 -155 -267 -463 -323 -560 -38 -66 -81 -140 -95 -165 | |||
-31 -56 -263 -457 -526 -910 -110 -190 -224 -388 -254 -440 -29 -52 -61 -109 | |||
-71 -125 -23 -39 -243 -420 -268 -465 -11 -19 -204 -352 -428 -740 -224 -388 | |||
-477 -826 -563 -975 -85 -148 -185 -322 -222 -385 -37 -63 -120 -207 -185 | |||
-320 -65 -113 -177 -306 -248 -430 -72 -124 -172 -297 -222 -385 -51 -88 -142 | |||
-245 -202 -350 -131 -226 -247 -427 -408 -705 -65 -113 -249 -432 -410 -710 | |||
-160 -278 -388 -673 -506 -877 -118 -205 -216 -373 -219 -373 -3 0 -52 82 | |||
-109 183 -58 100 -144 250 -192 332 -95 164 -402 696 -647 1120 -85 149 -228 | |||
396 -317 550 -212 365 -982 1700 -1008 1745 -10 19 -43 76 -72 125 -29 50 -64 | |||
110 -77 135 -14 25 -63 110 -110 190 -47 80 -96 165 -110 190 -14 25 -99 171 | |||
-188 325 -89 154 -174 300 -188 325 -13 25 -64 113 -112 195 -48 83 -140 242 | |||
-205 355 -65 113 -183 317 -263 454 -79 137 -152 264 -163 282 -50 89 -335 | |||
583 -354 614 -12 19 -34 58 -50 85 -15 28 -129 226 -253 440 -124 215 -235 | |||
408 -247 430 -12 22 -69 121 -127 220 -58 99 -226 389 -373 645 -148 256 -324 | |||
561 -392 678 -67 117 -134 232 -147 255 -13 23 -33 59 -46 80 l-22 37 -9615 0 | |||
-9615 0 20 -32z"/> | |||
</g> | |||
</svg> |
@@ -0,0 +1,20 @@ | |||
{ | |||
"name": "nexus-timers", | |||
"short_name": "nexus-timers", | |||
"icons": [ | |||
{ | |||
"src": "/static/img/icons/android-chrome-192x192.png", | |||
"sizes": "192x192", | |||
"type": "image/png" | |||
}, | |||
{ | |||
"src": "/static/img/icons/android-chrome-512x512.png", | |||
"sizes": "512x512", | |||
"type": "image/png" | |||
} | |||
], | |||
"start_url": "/index.html", | |||
"display": "standalone", | |||
"background_color": "#000000", | |||
"theme_color": "#4DBA87" | |||
} |