From 3ba8d0827b872287461aa036821d5ab99ce823de Mon Sep 17 00:00:00 2001 From: Meeeeow Date: Mon, 26 Jun 2017 02:13:39 +0800 Subject: [PATCH] refactor: modify webui dependencies & add some code --- .babelrc | 20 - .gitignore | 4 + package.json | 98 ++- src/api/endpoint/api/dist-tags.js | 14 +- src/api/endpoint/api/publish.js | 6 +- src/api/web/index.js | 16 +- src/config/env.js | 7 +- src/webui/.babelrc | 25 + src/webui/{src => }/.eslintrc.yml | 9 +- src/webui/scripts/dev.server.js | 37 + src/webui/scripts/webpack.config.js | 66 ++ src/webui/scripts/webpack.dev.config.babel.js | 40 + .../scripts/webpack.prod.config.babel.js | 51 ++ src/webui/src/App.jsx | 9 + src/webui/src/components/App.js | 93 --- src/webui/src/css/fontello.less | 56 -- src/webui/src/css/helpers.less | 136 ---- src/webui/src/css/highlight.js.less | 153 ---- src/webui/src/css/main.less | 7 - src/webui/src/css/markdown.less | 700 ------------------ src/webui/src/css/responsive.less | 38 - src/webui/src/css/styles.less | 197 ----- src/webui/src/entry.hbs | 23 - src/webui/src/index.js | 8 - src/webui/src/index.jsx | 24 + src/webui/src/style.css | 0 src/webui/src/test.scss | 3 + src/webui/template.html | 15 + src/webui/utils/const.js | 5 - tools/.eslintrc.yml | 15 - tools/webpack.config.js | 56 -- yarn.lock | Bin 227256 -> 212244 bytes 32 files changed, 343 insertions(+), 1588 deletions(-) delete mode 100644 .babelrc create mode 100644 src/webui/.babelrc rename src/webui/{src => }/.eslintrc.yml (60%) create mode 100644 src/webui/scripts/dev.server.js create mode 100644 src/webui/scripts/webpack.config.js create mode 100644 src/webui/scripts/webpack.dev.config.babel.js create mode 100644 src/webui/scripts/webpack.prod.config.babel.js create mode 100644 src/webui/src/App.jsx delete mode 100644 src/webui/src/components/App.js delete mode 100644 src/webui/src/css/fontello.less delete mode 100644 src/webui/src/css/helpers.less delete mode 100644 src/webui/src/css/highlight.js.less delete mode 100644 src/webui/src/css/main.less delete mode 100644 src/webui/src/css/markdown.less delete mode 100644 src/webui/src/css/responsive.less delete mode 100644 src/webui/src/css/styles.less delete mode 100644 src/webui/src/entry.hbs delete mode 100644 src/webui/src/index.js create mode 100644 src/webui/src/index.jsx delete mode 100644 src/webui/src/style.css create mode 100644 src/webui/src/test.scss create mode 100644 src/webui/template.html delete mode 100644 src/webui/utils/const.js delete mode 100644 tools/.eslintrc.yml delete mode 100644 tools/webpack.config.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index fc0fddffc..000000000 --- a/.babelrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "presets": [ - "react", - ["env", { - "targets": { - "browsers": "last 2 versions" - }, - "loose": true, - "modules": false - }] - ], - "env": { - "test": { - "plugins": [ - "transform-es2015-modules-commonjs" - ] - } - } -} - diff --git a/.gitignore b/.gitignore index f9d77d1dc..55a84730c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ bundle.js bundle.js.map __tests__ __snapshots__ + +# Compiled script +static +!static/favicon.png diff --git a/package.json b/package.json index 16f4a6b7d..22516e253 100644 --- a/package.json +++ b/package.json @@ -38,75 +38,66 @@ "lodash": "4.17.4", "lunr": "^0.7.0", "marked": "0.3.6", + "mime": "^1.3.6", "minimatch": "^3.0.2", "mkdirp": "^0.5.1", "pkginfo": "^0.4.0", - "prop-types": "15.5.10", "request": "^2.72.0", "semver": "^5.1.0", "unix-crypt-td-js": "^1.0.0" }, "devDependencies": { - "babel-cli": "6.22.2", - "babel-core": "6.22.1", - "babel-eslint": "7.2.3", - "babel-loader": "6.2.4", - "babel-plugin-dynamic-import-node": "1.0.2", - "babel-plugin-dynamic-import-webpack": "1.0.1", - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators-legacy": "1.3.4", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-polyfill": "6.23.0", - "babel-preset-env": "1.5.1", - "babel-preset-es2015": "6.22.0", - "babel-preset-es2016": "6.22.0", - "babel-preset-es2017": "6.22.0", - "babel-preset-react": "6.24.1", - "babel-register": "6.24.1", + "axios": "^0.16.2", + "babel-cli": "^6.24.1", + "babel-core": "^6.25.0", + "babel-eslint": "^7.2.3", + "babel-loader": "^7.1.0", + "babel-plugin-flow-runtime": "^0.11.1", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-plugin-transform-runtime": "^6.23.0", + "babel-preset-env": "^1.5.2", + "babel-preset-flow": "^6.23.0", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-2": "^6.24.1", + "babel-preset-stage-3": "^6.24.1", + "babel-runtime": "^6.23.0", "codacy-coverage": "2.0.2", "codecov": "2.2.0", "coveralls": "2.13.0", "css-loader": "0.23.1", - "enzyme": "2.8.2", - "eslint": "3.19.0", - "eslint-config-google": "0.7.1", - "eslint-config-prettier": "2.1.1", - "eslint-loader": "1.7.1", - "eslint-plugin-flow": "2.29.1", - "eslint-plugin-flowtype": "2.33.0", + "element-react": "^1.0.14", + "element-theme-default": "^1.3.7", + "eslint": "^4.1.0", + "eslint-config-google": "^0.8.0", + "eslint-loader": "^1.8.0", + "eslint-plugin-babel": "^4.1.1", + "eslint-plugin-flowtype": "^2.34.0", "eslint-plugin-import": "2.3.0", - "eslint-plugin-jsx-a11y": "5.0.3", - "eslint-plugin-prettier": "2.1.1", - "eslint-plugin-react": "7.0.1", - "extract-text-webpack-plugin": "2.1.2", - "file-loader": "0.10.1", - "flow-bin": "0.47.0", + "eslint-plugin-react": "^7.1.0", + "extract-text-webpack-plugin": "^2.1.2", + "file-loader": "^0.10.1", + "flow-runtime": "^0.12.0", + "friendly-errors-webpack-plugin": "^1.6.1", + "history": "^4.6.3", + "html-webpack-plugin": "^2.29.0", "in-publish": "2.0.0", - "jest": "20.0.4", - "jest-serializer-enzyme": "1.0.0", - "material-ui": "0.17.1", - "mocha": "3.2.0", + "localstorage-memory": "^1.0.2", "mocha-lcov-reporter": "1.3.0", - "normalize.css": "5.0.0", "nyc": "10.1.2", - "onclick": "0.1.0", - "prettier": "1.3.1", - "react": "15.6.0", - "react-dom": "15.6.0", - "react-hot-loader": "3.0.0-beta.6", - "react-router": "3.0.2", - "react-tap-event-plugin": "2.0.1", - "react-test-renderer": "15.5.4", + "ora": "^1.3.0", + "prop-types": "^15.5.10", + "react": "^15.6.1", + "react-dom": "^15.6.1", + "react-hot-loader": "^3.0.0-beta.7", + "react-router-dom": "^4.1.1", "rimraf": "2.5.2", - "sinon": "^2.3.4", - "style-loader": "0.13.1", + "ruby-sass-loader": "^0.4.0", + "source-map-loader": "^0.2.1", + "style-loader": "^0.13.1", "styled-components": "1.4.6", - "superagent": "2.0.0", - "transition-complete": "0.0.2", - "unopinionate": "0.0.4", - "url-loader": "0.5.8", - "webpack": "2.6.1" + "url-loader": "^0.5.8", + "webpack": "^3.0.0", + "webpack-dev-server": "^2.5.0" }, "keywords": [ "private", @@ -129,8 +120,9 @@ "test-only": "mocha ./test/functional ./test/unit", "lint": "eslint .", "build-docker": "docker build -t verdaccio .", - "build:webpack": "webpack --config tools/webpack.config.js", - "prepublish": "in-publish && thing-I-dont-want-on-dev-install || not-in-publish", + "build:webui": "rimraf scripts/*.js && rimraf scripts/*.js && webpack --config src/webui/scripts/webpack.prod.config.babel.js", + "dev:webui": "babel-node src/webui/scripts/dev.server.js", + "prepublish": "in-publish && npm run build:webpack || not-in-publish", "build-docker:rpi": "docker build -f Dockerfile.rpi -t verdaccio:rpi ." }, "jest": { diff --git a/src/api/endpoint/api/dist-tags.js b/src/api/endpoint/api/dist-tags.js index 10eaf730d..3d5811907 100644 --- a/src/api/endpoint/api/dist-tags.js +++ b/src/api/endpoint/api/dist-tags.js @@ -1,7 +1,7 @@ 'use strict'; const Middleware = require('../../web/middleware'); -const constant = require('../../../webui/utils/const'); +const mime = require('mime'); const media = Middleware.media; const expect_json = Middleware.expect_json; @@ -24,13 +24,13 @@ module.exports = function(route, auth, storage) { // tagging a package route.put('/:package/:tag', - can('publish'), media(constant.CONTENT_JSON), tag_package_version); + can('publish'), media(mime.lookup('json')), tag_package_version); route.post('/-/package/:package/dist-tags/:tag', - can('publish'), media(constant.CONTENT_JSON), tag_package_version); + can('publish'), media(mime.lookup('json')), tag_package_version); route.put('/-/package/:package/dist-tags/:tag', - can('publish'), media(constant.CONTENT_JSON), tag_package_version); + can('publish'), media(mime.lookup('json')), tag_package_version); route.delete('/-/package/:package/dist-tags/:tag', can('publish'), function(req, res, next) { let tags = {}; @@ -54,7 +54,7 @@ module.exports = function(route, auth, storage) { }); }); - route.post('/-/package/:package/dist-tags', can('publish'), media(constant.CONTENT_JSON), expect_json, + route.post('/-/package/:package/dist-tags', can('publish'), media(mime.lookup('json')), expect_json, function(req, res, next) { storage.merge_tags(req.params.package, req.body, function(err) { if (err) return next(err); @@ -63,7 +63,7 @@ module.exports = function(route, auth, storage) { }); }); - route.put('/-/package/:package/dist-tags', can('publish'), media(constant.CONTENT_JSON), expect_json, + route.put('/-/package/:package/dist-tags', can('publish'), media(mime.lookup('json')), expect_json, function(req, res, next) { storage.replace_tags(req.params.package, req.body, function(err) { if (err) return next(err); @@ -72,7 +72,7 @@ module.exports = function(route, auth, storage) { }); }); - route.delete('/-/package/:package/dist-tags', can('publish'), media(constant.CONTENT_JSON), + route.delete('/-/package/:package/dist-tags', can('publish'), media(mime.lookup('json')), function(req, res, next) { storage.replace_tags(req.params.package, {}, function(err) { if (err) return next(err); diff --git a/src/api/endpoint/api/publish.js b/src/api/endpoint/api/publish.js index 5239645f0..37bc0ac9b 100644 --- a/src/api/endpoint/api/publish.js +++ b/src/api/endpoint/api/publish.js @@ -7,7 +7,7 @@ const createError = require('http-errors'); const Middleware = require('../../web/middleware'); const Notify = require('../../../lib/notify'); const Utils = require('../../../lib/utils'); -const constant = require('../../../webui/utils/const'); +const mime = require('mime'); const media = Middleware.media; const expect_json = Middleware.expect_json; @@ -17,7 +17,7 @@ module.exports = function(router, auth, storage, config) { const can = Middleware.allow(auth); // publishing a package - router.put('/:package/:_rev?/:revision?', can('publish'), media(constant.CONTENT_JSON), expect_json, function(req, res, next) { + router.put('/:package/:_rev?/:revision?', can('publish'), media(mime.lookup('json')), expect_json, function(req, res, next) { const name = req.params.package; let metadata; const create_tarball = function(filename, data, cb) { @@ -170,7 +170,7 @@ module.exports = function(router, auth, storage, config) { }); // adding a version - router.put('/:package/:version/-tag/:tag', can('publish'), media(constant.CONTENT_JSON), expect_json, function(req, res, next) { + router.put('/:package/:version/-tag/:tag', can('publish'), media(mime.lookup('json')), expect_json, function(req, res, next) { let name = req.params.package; let version = req.params.version; let tag = req.params.tag; diff --git a/src/api/web/index.js b/src/api/web/index.js index 6684bf742..cebed007e 100644 --- a/src/api/web/index.js +++ b/src/api/web/index.js @@ -20,16 +20,6 @@ module.exports = function(config, auth, storage) { router.use(auth.jwtMiddleware()); router.use(securityIframe); - Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('../../webui/src/entry.hbs'), 'utf8')); - - let template; - - if (config.web && config.web.template) { - template = Handlebars.compile(fs.readFileSync(config.web.template, 'utf8')); - } else { - template = Handlebars.compile(fs.readFileSync(require.resolve('../../webui/src/index.hbs'), 'utf8')); - } - // Static router.get('/-/static/:filename', function(req, res, next) { let file = `${env.APP_ROOT}/static/${req.params.filename}`; @@ -87,10 +77,8 @@ module.exports = function(config, auth, storage) { baseUrl: base, username: req.remote_user.name, }; - next(template({ - name: config.web && config.web.title ? config.web.title : 'Verdaccio', - data: escape(JSON.stringify(json)), - })); + + next(json) } ); }); diff --git a/src/config/env.js b/src/config/env.js index b928667d4..6ce0c13ae 100644 --- a/src/config/env.js +++ b/src/config/env.js @@ -1,6 +1,9 @@ const path = require('path'); +const APP_ROOT = path.resolve(__dirname, '../../'); + module.exports = { - APP_ROOT: path.resolve(__dirname, '../../'), - SRC_ROOT: path.resolve(__dirname, '../'), + APP_ROOT, + SRC_ROOT: path.resolve(APP_ROOT, 'src/'), + DIST_PATH: path.resolve(APP_ROOT, 'static/'), }; diff --git a/src/webui/.babelrc b/src/webui/.babelrc new file mode 100644 index 000000000..be6c8e773 --- /dev/null +++ b/src/webui/.babelrc @@ -0,0 +1,25 @@ +{ + "presets": [ + "react", + ["env",{ + "targets": { + "browsers": ["last 5 versions", "safari >= 11"], + "loose": true + } + }] + ], + "plugins": [ + "react-hot-loader/babel", + "transform-runtime", + "transform-object-rest-spread", + "transform-decorators-legacy" + ], + "env": { + "development": { + "presets": ["flow"], + "plugins": [ + "flow-runtime" + ] + } + } +} diff --git a/src/webui/src/.eslintrc.yml b/src/webui/.eslintrc.yml similarity index 60% rename from src/webui/src/.eslintrc.yml rename to src/webui/.eslintrc.yml index 00bc05b7b..41cbe141d 100644 --- a/src/webui/src/.eslintrc.yml +++ b/src/webui/.eslintrc.yml @@ -3,9 +3,14 @@ ## rules for react components -extends: ["eslint:recommended", "google", "plugin:react/recommended", "plugin:flowtype/recommended", "prettier", "prettier/react"] +extends: + - google + - eslint:recommended + - plugin:react/recommended + - plugin:flowtype/recommended -plugins: ["flowtype", "prettier"] +plugins: + - flowtype parser: babel-eslint diff --git a/src/webui/scripts/dev.server.js b/src/webui/scripts/dev.server.js new file mode 100644 index 000000000..18b3b2ccf --- /dev/null +++ b/src/webui/scripts/dev.server.js @@ -0,0 +1,37 @@ +import webpack from 'webpack'; +import WebpackDevServer from 'webpack-dev-server'; +import config from './webpack.dev.config.babel'; +import ora from 'ora'; +import env from '../../config/env' + +const compiler = webpack(config); +const spinner = ora('Compiler is running...').start(); +compiler.plugin('done', () => { + if (!global.rebuild) { + spinner.stop(); + console.log('Dev Server Listening at http://localhost:4872/') + global.rebuild = true + } +}); + +new WebpackDevServer(compiler, { + contentBase: `${env.DIST_PATH}`, + publicPath: config.output.publicPath, + hot: true, + historyApiFallback: true, + quiet: true, + noInfo: false, + stats: { + assets: false, + colors: true, + version: true, + hash: true, + timings: true, + chunks: true, + chunkModules: false + } +}).listen(4872, 'localhost', function (err) { + if (err) { + return console.log(err); + } +}) diff --git a/src/webui/scripts/webpack.config.js b/src/webui/scripts/webpack.config.js new file mode 100644 index 000000000..1af39f2dc --- /dev/null +++ b/src/webui/scripts/webpack.config.js @@ -0,0 +1,66 @@ +import env from '../../config/env' + +const isDev = process.env.NODE_ENV === 'development' + +export default { + entry: `${env.SRC_ROOT}/webui/src/index.jsx`, + + output: { + path: `${env.APP_ROOT}/static/`, + filename: '[name].[hash].js' + }, + + resolve: { + extensions: ['.js', '.jsx'] + }, + + module: { + rules: [ + /* Pre loader */ + { + enforce: 'pre', + test: /\.jsx?$/, + exclude: /node_modules/, + use: 'eslint-loader' + }, + + /* Normal loader */ + { + test: /\.jsx?$/, + exclude: /node_modules/, + use: 'babel-loader' + }, + { + test: /\.(jpe?g|png|gif|svg)$/, + use: 'file-loader?name=/[name].[ext]' + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: [ + { + loader: 'style-loader' + }, + { + loader: 'css-loader', + options: { + sourceMap: true, + module: true, + localIdentName: '[path][name]__[local]--[hash:base64:5]' + } + }, + { + loader: 'ruby-sass-loader', + options: { + sourceMap: true + } + } + ] + } + ] + }, + + devtool: isDev ? 'source-map' : 'eval', + + stats: {children: false} +}; diff --git a/src/webui/scripts/webpack.dev.config.babel.js b/src/webui/scripts/webpack.dev.config.babel.js new file mode 100644 index 000000000..f4e4a4d5d --- /dev/null +++ b/src/webui/scripts/webpack.dev.config.babel.js @@ -0,0 +1,40 @@ +import webpack from 'webpack'; +import HTMLWebpackPlugin from 'html-webpack-plugin'; +import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin'; +import baseConfig from './webpack.config' +import env from '../../config/env' + +export default { + ...baseConfig, + entry: { + main: [ + 'react-hot-loader/patch', + 'webpack-dev-server/client?http://localhost:4872', + 'webpack/hot/only-dev-server', + `${env.SRC_ROOT}/webui/src/index.jsx` + ] + }, + + output: { + ...baseConfig.output, + publicPath: '/' + }, + + plugins: [ + new webpack.DefinePlugin({ + __DEBUG__: true, + 'process.env.NODE_ENV': '"development"' + }), + new HTMLWebpackPlugin({ + title: 'Verdaccio', + filename: 'index.html', + verdaccioURL: '//localhost:4873/-/', + template: `${env.SRC_ROOT}/webui/template.html`, + debug: true, + inject: true, + }), + new webpack.HotModuleReplacementPlugin(), + new webpack.NoEmitOnErrorsPlugin(), + new FriendlyErrorsPlugin() + ] +} diff --git a/src/webui/scripts/webpack.prod.config.babel.js b/src/webui/scripts/webpack.prod.config.babel.js new file mode 100644 index 000000000..03c484973 --- /dev/null +++ b/src/webui/scripts/webpack.prod.config.babel.js @@ -0,0 +1,51 @@ +import webpack from 'webpack'; +import HTMLWebpackPlugin from 'html-webpack-plugin'; +import ExtractTextPlugin from 'extract-text-webpack-plugin'; +import baseConfig from './webpack.config' +import env from '../../config/env' +import _ from 'lodash' + +baseConfig.module.rules + .filter(loader => + Array.isArray(loader.use) && loader.use.find(v => /css/.test(v.loader.split('-')[0])) + ).forEach(loader => { + loader.use = ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: _.tail(loader.use) + }) +}) + +export default { + ...baseConfig, + entry: { + main: `${env.SRC_ROOT}/webui/src/index.jsx` + }, + + output: { + ...baseConfig.output, + publicPath: 'ToReplaceByVerdaccio' + }, + + plugins: [ + new webpack.DefinePlugin({ + __DEBUG__: false, + 'process.env.NODE_ENV': '"production"' + }), + new webpack.optimize.UglifyJsPlugin({ + sourceMap: true, + compress: { + warnings: false + } + }), + new ExtractTextPlugin('style.[contenthash].css'), + new HTMLWebpackPlugin({ + title: 'Verdaccio', + filename: 'index.html', + verdaccioURL: 'ToReplaceByVerdaccio', + template: `${env.SRC_ROOT}/webui/template.html`, + debug: true, + inject: true, + }), + new webpack.NoEmitOnErrorsPlugin() + ] +} diff --git a/src/webui/src/App.jsx b/src/webui/src/App.jsx new file mode 100644 index 000000000..fa7af5325 --- /dev/null +++ b/src/webui/src/App.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +import classes from './test.scss'; + +export default class App extends React.Component { + render() { + return

Hello, Verdaccio

+ } +} diff --git a/src/webui/src/components/App.js b/src/webui/src/components/App.js deleted file mode 100644 index d068b4e59..000000000 --- a/src/webui/src/components/App.js +++ /dev/null @@ -1,93 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import _ from 'lodash'; -import injectTapEventPlugin from 'react-tap-event-plugin'; -import request from 'superagent'; -import getMuiTheme from 'material-ui/styles/getMuiTheme'; -import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; -import {green100, green500, green700} from 'material-ui/styles/colors'; - -import Header from './Header/Header'; -import Search from './Search/Search'; -import List from './List/List'; - -injectTapEventPlugin(); - -if (process.env.BROWSER) { - require('./browser.css'); -} - -const muiTheme = getMuiTheme({ - palette: { - primary1Color: green500, - primary2Color: green700, - primary3Color: green100, - }, -}, { - avatar: { - borderColor: null, - }, - userAgent: false, -}); - -class App extends React.Component { - - constructor(props) { - super(); - this.state = { - packages: props.packages, - frontPackages: props.packages, - req: null, - }; - this.updatePackages = this.updatePackages.bind(this); - } - - updatePackages(keyword) { - if (keyword !== '') { - if (this.req) { - this.req.abort(); - } - this.req = request.get(`/-/search/${keyword}`) - .end((err, res) => { - if(_.isNil(err) === false) { - this.setState({ - packages: [], - }); - } else { - this.setState({ - packages: res.body, - }); - } - }); - } else { - if (this.req) { - this.req.abort(); - } - this.setState({ - packages: this.state.frontPackages, - }); - } - } - - render() { - return ( - -
-
-
- - -
-
-
- ); - } -} - -App.propTypes = { - packages: PropTypes.array.isRequired, - baseUrl: PropTypes.string.isRequired, - username: PropTypes.string, -}; - -export default App; diff --git a/src/webui/src/css/fontello.less b/src/webui/src/css/fontello.less deleted file mode 100644 index 22ea25c33..000000000 --- a/src/webui/src/css/fontello.less +++ /dev/null @@ -1,56 +0,0 @@ -@font-face { - font-family: 'fontello'; - src: url('../static/fontello.eot?10872183'); - src: url('../static/fontello.eot?10872183#iefix') format('embedded-opentype'), - url('../static/fontello.woff?10872183') format('woff'), - url('../static/fontello.ttf?10872183') format('truetype'), - url('../static/fontello.svg?10872183#fontello') format('svg'); - font-weight: normal; - font-style: normal; -} -/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ -/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ -/* -@media screen and (-webkit-min-device-pixel-ratio:0) { - @font-face { - font-family: 'fontello'; - src: url('../font/fontello.svg?10872183#fontello') format('svg'); - } -} -*/ - - [class^="icon-"]:before, [class*=" icon-"]:before { - font-family: "fontello"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - /* opacity: .8; */ - - /* For safety - reset parent styles, that can break glyph codes*/ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - /* remove if not needed */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - /* font-size: 120%; */ - - /* Uncomment for 3D effect */ - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ -} - -.icon-search:before { content: '\e801'; } /* '' */ -.icon-cancel:before { content: '\e803'; } /* '' */ -.icon-right-open:before { content: '\e802'; } /* '' */ -.icon-angle-right:before { content: '\e800'; } /* '' */ \ No newline at end of file diff --git a/src/webui/src/css/helpers.less b/src/webui/src/css/helpers.less deleted file mode 100644 index 9f194178b..000000000 --- a/src/webui/src/css/helpers.less +++ /dev/null @@ -1,136 +0,0 @@ -// -// copied from https://github.com/bpeacock/helpers.less -// -// author: Brian Peacock -// license: MIT -// - -.backface-visibility(@style) { - -webkit-backface-visibility: @style; - -moz-backface-visibility: @style; - -ms-backface-visibility: @style; - -o-backface-visibility: @style; - backface-visibility: @style; -} - -.perspective(@style) { - -webkit-perspective: @style; - -moz-perspective: @style; - -ms-perspective: @style; - -o-perspective: @style; - perspective: @style; -} - -.border-radius(@radius) { - -webkit-border-radius: @radius; - -moz-border-radius: @radius; - border-radius: @radius; -} - -.border-radius-topleft(@radius) { - -moz-border-radius-topleft: @radius; - border-top-left-radius: @radius; -} - -.border-radius-topright(@radius) { - -moz-border-radius-topright: @radius; - border-top-right-radius: @radius; -} - -.border-radius-bottomleft(@radius) { - -moz-border-radius-bottomleft: @radius; - border-bottom-left-radius: @radius; -} - -.border-radius-bottomright(@radius) { - -moz-border-radius-bottomright: @radius; - border-bottom-right-radius: @radius; -} - -.circle(@diameter) { - width: @diameter; - height: @diameter; - .border-radius(@diameter/2); -} - -.no-select() { - -moz-user-select: none; - -ms-user-select: none; - -khtml-user-select: none; - -webkit-user-select: none; - -o-user-select: none; - user-select: none; -} - -.do-select() { - -moz-user-select: text; - -ms-user-select: text; - -khtml-user-select: text; - -webkit-user-select: text; - -o-user-select: text; - user-select: text; -} - -.border-box() { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.box-shadow(@value1, @value2:X, ...) { - @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; - -moz-box-shadow: @value; - -webkit-box-shadow: @value; - box-shadow: @value; -} - -.transition(@value1, @value2:X, ...) { - @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; - - -webkit-transition: @value; - -moz-transition: @value; - -ms-transition: @value; - -o-transition: @value; - transition: @value; -} - -.transformTransition(@value1, @value2:X, ...) { - @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; - - -webkit-transition: -webkit-transform @value; - -moz-transition: -moz-transform @value; - -ms-transition: -ms-transform @value; - -o-transition: -o-transform @value; - transition: transform @value; -} - -.animation(@value1, @value2:X, ...) { - @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; - - -webkit-animation: @value; - -moz-animation: @value; - -o-animation: @value; - animation: @value; -} - -.transform(@value1, @value2:X, ...) { - @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`; - - -webkit-transform: @value; - -moz-transform: @value; - -o-transform: @value; - -ms-transform: @value; - transform: @value; -} - -.rotate(@deg) { - .transform(rotate(@deg)); -} - -.scale(@ratio) { - .transform(scale(@ratio, @ratio)); -} - -.translate(@x, @y) { - .transform(translate(@x, @y)); -} diff --git a/src/webui/src/css/highlight.js.less b/src/webui/src/css/highlight.js.less deleted file mode 100644 index 3d8485b48..000000000 --- a/src/webui/src/css/highlight.js.less +++ /dev/null @@ -1,153 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -.hljs { - display: block; padding: 0.5em; - background: #F0F0F0; -} - -.hljs, -.hljs-subst, -.hljs-tag .hljs-title, -.lisp .hljs-title, -.clojure .hljs-built_in, -.nginx .hljs-title { - color: black; -} - -.hljs-string, -.hljs-title, -.hljs-constant, -.hljs-parent, -.hljs-tag .hljs-value, -.hljs-rules .hljs-value, -.hljs-rules .hljs-value .hljs-number, -.hljs-preprocessor, -.hljs-pragma, -.haml .hljs-symbol, -.ruby .hljs-symbol, -.ruby .hljs-symbol .hljs-string, -.hljs-aggregate, -.hljs-template_tag, -.django .hljs-variable, -.smalltalk .hljs-class, -.hljs-addition, -.hljs-flow, -.hljs-stream, -.bash .hljs-variable, -.apache .hljs-tag, -.apache .hljs-cbracket, -.tex .hljs-command, -.tex .hljs-special, -.erlang_repl .hljs-function_or_atom, -.asciidoc .hljs-header, -.markdown .hljs-header, -.coffeescript .hljs-attribute { - color: #800; -} - -.smartquote, -.hljs-comment, -.hljs-annotation, -.hljs-template_comment, -.diff .hljs-header, -.hljs-chunk, -.asciidoc .hljs-blockquote, -.markdown .hljs-blockquote { - color: #888; -} - -.hljs-number, -.hljs-date, -.hljs-regexp, -.hljs-literal, -.hljs-hexcolor, -.smalltalk .hljs-symbol, -.smalltalk .hljs-char, -.go .hljs-constant, -.hljs-change, -.lasso .hljs-variable, -.makefile .hljs-variable, -.asciidoc .hljs-bullet, -.markdown .hljs-bullet, -.asciidoc .hljs-link_url, -.markdown .hljs-link_url { - color: #080; -} - -.hljs-label, -.hljs-javadoc, -.ruby .hljs-string, -.hljs-decorator, -.hljs-filter .hljs-argument, -.hljs-localvars, -.hljs-array, -.hljs-attr_selector, -.hljs-important, -.hljs-pseudo, -.hljs-pi, -.haml .hljs-bullet, -.hljs-doctype, -.hljs-deletion, -.hljs-envvar, -.hljs-shebang, -.apache .hljs-sqbracket, -.nginx .hljs-built_in, -.tex .hljs-formula, -.erlang_repl .hljs-reserved, -.hljs-prompt, -.asciidoc .hljs-link_label, -.markdown .hljs-link_label, -.vhdl .hljs-attribute, -.clojure .hljs-attribute, -.asciidoc .hljs-attribute, -.lasso .hljs-attribute, -.coffeescript .hljs-property, -.hljs-phony { - color: #88F -} - -.hljs-keyword, -.hljs-id, -.hljs-title, -.hljs-built_in, -.hljs-aggregate, -.css .hljs-tag, -.hljs-javadoctag, -.hljs-phpdoc, -.hljs-yardoctag, -.smalltalk .hljs-class, -.hljs-winutils, -.bash .hljs-variable, -.apache .hljs-tag, -.go .hljs-typename, -.tex .hljs-command, -.asciidoc .hljs-strong, -.markdown .hljs-strong, -.hljs-request, -.hljs-status { - font-weight: bold; -} - -.asciidoc .hljs-emphasis, -.markdown .hljs-emphasis { - font-style: italic; -} - -.nginx .hljs-built_in { - font-weight: normal; -} - -.coffeescript .javascript, -.javascript .xml, -.lasso .markup, -.tex .hljs-formula, -.xml .javascript, -.xml .vbscript, -.xml .css, -.xml .hljs-cdata { - opacity: 0.5; -} diff --git a/src/webui/src/css/main.less b/src/webui/src/css/main.less deleted file mode 100644 index ffba2b533..000000000 --- a/src/webui/src/css/main.less +++ /dev/null @@ -1,7 +0,0 @@ -@import "helpers.less"; -@import (less) "bootstrap.css"; -@import "markdown.less"; -@import "highlight.js.less"; -@import "fontello.less"; -@import "styles.less"; -@import "responsive.less"; diff --git a/src/webui/src/css/markdown.less b/src/webui/src/css/markdown.less deleted file mode 100644 index 9bfc80c47..000000000 --- a/src/webui/src/css/markdown.less +++ /dev/null @@ -1,700 +0,0 @@ -/*** Sourced from this Gist: https://github.com/sindresorhus/github-markdown-css ***/ -@font-face { - font-family: octicons-anchor; - src: url(data:font/woff;charset=utf-8;base64,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) format('woff'); -} - -.readme { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - color: #333; - overflow: hidden; - font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; - font-size: 16px; - line-height: 1.6; - word-wrap: break-word; - - - a { - background: transparent; - - &:active, - &:hover { - outline: 0; - } - } - - strong { - font-weight: bold; - } - - h1 { - text-align: left; - font-size: 2em; - margin: 0.67em 0; - } - - img { - border: 0; - } - - hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; - } - - pre { - overflow: auto; - } - - code, - kbd, - pre { - font-family: monospace, monospace; - font-size: 1em; - } - - input { - color: inherit; - font: inherit; - margin: 0; - } - - html input[disabled] { - cursor: default; - } - - input { - line-height: normal; - } - - input[type="checkbox"] { - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; - } - - table { - border-collapse: collapse; - border-spacing: 0; - } - - td, - th { - padding: 0; - } - - * { - -moz-box-sizing: border-box; - box-sizing: border-box; - } - - input { - font: 13px/1.4 Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; - } - - a { - color: #4183c4; - text-decoration: none; - - &:hover, - &:focus, - &:active { - text-decoration: underline; - } - } - - hr { - height: 0; - margin: 15px 0; - overflow: hidden; - background: transparent; - border: 0; - border-bottom: 1px solid #ddd; - - &:before { - display: table; - content: ""; - } - - &:after { - display: table; - clear: both; - content: ""; - } - } - - h1, - h2, - h3, - h4, - h5, - h6 { - margin-top: 15px; - margin-bottom: 15px; - line-height: 1.1; - } - - h1 { - font-size: 30px; - } - - h2 { - font-size: 21px; - } - - h3 { - font-size: 16px; - } - - h4 { - font-size: 14px; - } - - h5 { - font-size: 12px; - } - - h6 { - font-size: 11px; - } - - blockquote { - margin: 0; - } - - ul, - ol { - padding: 0; - margin-top: 0; - margin-bottom: 0; - - ol { - list-style-type: lower-roman; - - ol { - list-style-type: lower-alpha; - } - } - } - - ul { - ul { - ol { - list-style-type: lower-alpha; - } - } - } - - ol { - ul { - ol { - list-style-type: lower-alpha; - } - } - } - - - dd { - margin-left: 0; - } - - code { - font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; - } - - pre { - margin-top: 0; - margin-bottom: 0; - font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; - } - - kbd { - background-color: #e7e7e7; - background-image: -webkit-linear-gradient(#fefefe, #e7e7e7); - background-image: linear-gradient(#fefefe, #e7e7e7); - background-repeat: repeat-x; - border-radius: 2px; - border: 1px solid #cfcfcf; - color: #000; - padding: 3px 5px; - line-height: 10px; - font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; - display: inline-block; - } - - >*:first-child { - margin-top: 0 !important; - } - - >*:last-child { - margin-bottom: 0 !important; - } - - .anchor { - position: absolute; - top: 0; - bottom: 0; - left: 0; - display: block; - padding-right: 6px; - padding-left: 30px; - margin-left: -30px; - } - - .anchor:focus { - outline: none; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - position: relative; - margin-top: 1em; - margin-bottom: 16px; - font-weight: bold; - line-height: 1.4; - - .octicon-link { - display: none; - color: #000; - vertical-align: middle; - } - - &:hover { - .anchor { - height: 1em; - padding-left: 8px; - margin-left: -30px; - line-height: 1; - text-decoration: none; - - .octicon-link { - display: inline-block; - } - } - } - } - - h1 { - padding-bottom: 0.3em; - font-size: 2.25em; - line-height: 1.2; - border-bottom: 1px solid #eee; - } - - h2 { - padding-bottom: 0.3em; - font-size: 1.75em; - line-height: 1.225; - border-bottom: 1px solid #eee; - } - - h3 { - font-size: 1.5em; - line-height: 1.43; - } - - h4 { - font-size: 1.25em; - } - - h5 { - font-size: 1em; - } - - h6 { - font-size: 1em; - color: #777; - } - - p, - blockquote, - ul, - ol, - dl, - table, - pre { - margin-top: 0; - margin-bottom: 16px; - } - - hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: #e7e7e7; - border: 0 none; - } - - ul, - ol { - padding-left: 2em; - - ul, ol { - margin-top: 0; - margin-bottom: 0; - } - } - - li { - >p { - margin-top: 16px; - } - } - - dl { - padding: 0; - - dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: bold; - } - - dd { - padding: 0 16px; - margin-bottom: 16px; - } - } - - blockquote { - padding: 0 15px; - color: #777; - border-left: 4px solid #ddd; - - >:first-child { - margin-top: 0; - } - - >:last-child { - margin-bottom: 0; - } - } - - table { - display: block; - width: 100%; - overflow: auto; - word-break: normal; - word-break: keep-all; - - th { - font-weight: bold; - } - - th, - td { - padding: 6px 13px; - border: 1px solid #ddd; - } - - tr { - background-color: #fff; - border-top: 1px solid #ccc; - - &:nth-child(2n) { - background-color: #f8f8f8; - } - } - - - } - - img { - max-width: 100%; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - - code { - padding: 0; - padding-top: 0.2em; - padding-bottom: 0.2em; - margin: 0; - font-size: 85%; - background-color: rgba(0,0,0,0.04); - border-radius: 3px; - - &:before, - &:after { - letter-spacing: -0.2em; - content: "\00a0"; - } - } - - pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f7f7f7; - border-radius: 3px; - word-wrap: normal; - - >code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; - - &:before, - &:after { - content: normal; - } - } - } - - .highlight { - margin-bottom: 16px; - background: #fff; - - pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f7f7f7; - border-radius: 3px; - margin-bottom: 0; - word-break: normal; - } - } - - .highlight{ - .mf, - .mh, - .mi, - .mo, - .il, - .m { - color: #945277; - } - - .s, - .sb, - .sc, - .sd, - .s2, - .se, - .sh, - .si, - .sx, - .s1 { - color: #df5000; - } - - .kc, - .kd, - .kn, - .kp, - .kr, - .kt, - .k, - .o { - font-weight: bold; - } - - .kt { - color: #458; - } - - .c, - .cm, - .c1 { - color: #998; - font-style: italic; - } - - .cp, - .cs { - color: #999; - font-weight: bold; - } - - .cs { - font-style: italic; - } - - .n { - color: #333; - } - - .na, - .nv, - .vc, - .vg, - .vi { - color: #008080; - } - - .nb { - color: #0086B3; - } - - .nc { - color: #458; - font-weight: bold; - } - - .no { - color: #094e99; - } - - .ni { - color: #800080; - } - - .ne { - color: #990000; - font-weight: bold; - } - - .nf { - color: #945277; - font-weight: bold; - } - - .nn { - color: #555; - } - - .nt { - color: #000080; - } - - .err { - color: #a61717; - background-color: #e3d2d2; - } - - .gd { - color: #000; - background-color: #fdd; - - .x { - color: #000; - background-color: #faa; - } - } - - .ge { - font-style: italic; - } - - .gr { - color: #aa0000; - } - - .gh { - color: #999; - } - - .gi { - color: #000; - background-color: #dfd; - - .x { - color: #000; - background-color: #afa; - } - } - - .go { - color: #888; - } - - .gp { - color: #555; - } - - .gs { - font-weight: bold; - } - - .gu { - color: #800080; - font-weight: bold; - } - - .gt { - color: #aa0000; - } - - .ow { - font-weight: bold; - } - - .w { - color: #bbb; - } - - .sr { - color: #017936; - } - - .ss { - color: #8b467f; - } - - .bp { - color: #999; - } - - .gc { - color: #999; - background-color: #EAF2F5; - } - } - - .octicon { - font: normal normal 16px octicons-anchor; - line-height: 1; - display: inline-block; - text-decoration: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } - - .octicon-link { - &:before { - content: '\f05c'; - } - } - - .task-list-item { - list-style-type: none; - - +.task-list-item { - margin-top: 3px; - } - - input { - float: left; - margin: 0.3em 0 0.25em -1.6em; - vertical-align: middle; - } - } -} diff --git a/src/webui/src/css/responsive.less b/src/webui/src/css/responsive.less deleted file mode 100644 index 4e6b413c6..000000000 --- a/src/webui/src/css/responsive.less +++ /dev/null @@ -1,38 +0,0 @@ -@media (max-width: 992px) { - .body { - .main-header { - .npm-logo { - width: 100px; - float: left; - } - - .packages-header { - border-bottom: none; - } - } - } -} - -@media (max-width: 768px) { - .body { - .content { - padding-top: @mainHeaderHeight + @packagesHeaderHeight + @smRegistryInfoHeight + 10; - - .entry { - .title { - margin-bottom: 0; - } - - .author { - float: none !important; - clear: both; - padding: 0 0 5px 18px; - } - } - } - - .no-results { - margin: 10px 0 0; - } - } -} diff --git a/src/webui/src/css/styles.less b/src/webui/src/css/styles.less deleted file mode 100644 index 3325d78a0..000000000 --- a/src/webui/src/css/styles.less +++ /dev/null @@ -1,197 +0,0 @@ -//vars -@npmRed: #cc3d33; -@white: #fff; -@entryBg: #F3F3F3; -@mainHeaderHeight: 50px; -@packagesHeaderHeight: 60px; -@headerBorderWidth: 2px; -@smRegistryInfoHeight: 25px; - -/*** Main Styles ***/ -.body { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left:0; - margin: 0; - padding: 0; - - .main-header { - background: @white; - - .navbar { - margin-bottom: 0; - } - - .npm-logo { - width: 79px; - height: @mainHeaderHeight; - // https://example.org/verdaccio/-/static/../../-/logo - background-image: url( ../../-/logo ); - background-repeat: no-repeat; - background-position: center center; - - >a { - display: block; - width: 100%; - height: 100%; - } - } - - .setup { - line-height: 1.3em; - padding-top: 5px; - } - - .packages-header { - border-bottom: @headerBorderWidth solid #e6e6e6; - - .search-container { - top: 9px; - - .search-icon { - background: #e6e6e6; - } - } - } - - .sm-registry-info { - height: @smRegistryInfoHeight; - line-height: 1.7em; - } - } - - .content { - padding-top: 10px; - - .entry { - .transition(height .3s); - padding: 9px 10px; - overflow: hidden; - border-bottom: 1px solid #E7E7E7; - - &:last-child { - border-bottom: none; - } - - &:nth-child( even ) { - background: @entryBg; - } - - .title { - margin: 0 0 5px 10px; - } - - .description { - margin: 0 0 0 18px; - font-size: 13px; - } - - .name:hover { - text-decoration: none; - } - - .name:before { - margin: 0; - margin-left: -10px; - .transformTransition(.2s); - } - - &.open .name:before { - .rotate(90deg); - } - - .version { - color: #666; - } - - .author { - color: #666; - } - - .readme { - font-size: 14px; - margin-top: 10px; - background: @white; - padding: 10px 12px; - .border-radius(3px); - border: 1px solid darken( @entryBg, 10% ); - } - } - } -} - -.pkg-search-container { - display: none; -} - -.pkg-search-container { - .search-ajax { - display: block; - margin: 50px auto; - } -} - -.no-results { - text-align: center; - margin: 50px 0; - color: #888; - - big { - font-size: 38px; - margin-bottom: 8px; - } - - code { - font-size: 1.2em; - } -} - -.red { - color: @npmRed; -} - -.light-red { - color: lighten( @npmRed, 10% ); -} - -.white { - color: @white !important; -} - -.red-bg { - background: @npmRed; -} - -.light-red-bg { - background: lighten( @npmRed, 10% ); -} - -.no-bg { - background: none !important; -} - -.no-border { - border: none !important; -} -.no-rnd-cnr { - .border-radius( 0 ); -} - -.center { - text-align: center; -} - -.login-btn { - margin-left: 10px; - margin-top: 5px; -} - -.pad-right-10 { - padding-right: 10px; -} - -.inline-block { - display: inline-block; -} diff --git a/src/webui/src/entry.hbs b/src/webui/src/entry.hbs deleted file mode 100644 index a6efb9872..000000000 --- a/src/webui/src/entry.hbs +++ /dev/null @@ -1,23 +0,0 @@ -
-
-
-

- {{ name }} - v{{ version }} -

-
-
-
- {{!-- I can't make hbs helper work without break code style --}} - {{#with author}} - By: {{{ name }}} - {{/with}} -
-
-
-
-
-

{{ description }}

-
-
-
diff --git a/src/webui/src/index.js b/src/webui/src/index.js deleted file mode 100644 index fc38b4492..000000000 --- a/src/webui/src/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -import App from './components/App.js'; -import './style.css'; - -const state = window.__INITIAL_STATE; -ReactDOM.render(, document.getElementById('root')); diff --git a/src/webui/src/index.jsx b/src/webui/src/index.jsx new file mode 100644 index 000000000..a380fcccd --- /dev/null +++ b/src/webui/src/index.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { AppContainer } from 'react-hot-loader' + +import App from './App' + +let rootNode = document.getElementById('root') + +let renderApp = (Component) => { + ReactDOM.render( + + + , + rootNode + ) +} + +renderApp(App); + +if (module.hot) { + module.hot.accept('./App', () => { + renderApp(App) + }) +} diff --git a/src/webui/src/style.css b/src/webui/src/style.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/webui/src/test.scss b/src/webui/src/test.scss new file mode 100644 index 000000000..e06b4c35b --- /dev/null +++ b/src/webui/src/test.scss @@ -0,0 +1,3 @@ +.helloWorld { + color: pink +} diff --git a/src/webui/template.html b/src/webui/template.html new file mode 100644 index 000000000..83785d067 --- /dev/null +++ b/src/webui/template.html @@ -0,0 +1,15 @@ + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + +
+ + diff --git a/src/webui/utils/const.js b/src/webui/utils/const.js deleted file mode 100644 index 854827a4f..000000000 --- a/src/webui/utils/const.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -const CONTENT_JSON = 'application/json'; - -module.exports.CONTENT_JSON = CONTENT_JSON; diff --git a/tools/.eslintrc.yml b/tools/.eslintrc.yml deleted file mode 100644 index e744c71c9..000000000 --- a/tools/.eslintrc.yml +++ /dev/null @@ -1,15 +0,0 @@ -# vim: syntax=yaml - - -## rules for react components - -env: - node: true - browser: true - -rules: - # jsdoc is mandatory - require-jsdoc: 0 - comma-dangle: 0 - - diff --git a/tools/webpack.config.js b/tools/webpack.config.js deleted file mode 100644 index c67abc1be..000000000 --- a/tools/webpack.config.js +++ /dev/null @@ -1,56 +0,0 @@ -const webpack = require('webpack'); -const ExtractTextPlugin = require('extract-text-webpack-plugin'); -const env = require('../src/config/env'); - -module.exports = { - entry: `${env.SRC_ROOT}/webui/src/index.js`, - devtool: 'source-map', - output: { - path: `${env.APP_ROOT}/static/`, - filename: 'bundle.js' - }, - module: { - rules: [ - { - enforce: 'pre', - test: /\.js$/, - exclude: /node_modules/, - loader: 'eslint-loader', - options: { - failOnError: true, - } - }, - { - test: /\.(js)$/, - exclude: /node_modules/, - use: ['babel-loader'] - }, - { - test: /\.(jpe?g|png|gif|svg)$/i, - use: 'file-loader?name=/[name].[ext]' - }, - { - test: /\.(ttf|eot|woff|woff2|svg)$/, - loader: 'url-loader?limit=50000&name=fonts/[hash].[ext]' - }, - { - test: /\.css$/, - use: ExtractTextPlugin.extract({ - fallback: 'style-loader', - use: 'css-loader' - }) - } - ] - }, - plugins: [ - new ExtractTextPlugin('styles.css'), - new webpack.DefinePlugin({ - 'process.env': { - BROWSER: JSON.stringify(true) - } - }) - ], - resolve: { - extensions: ['.js', '.css'] - } -}; diff --git a/yarn.lock b/yarn.lock index d0bdbeea3b107ed21a3ff7d8615ba9b9d3b010fb..b6022ebe9beb13443ebf7fa5636b172034c7212e 100644 GIT binary patch delta 28818 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%0AVb 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 wTqKBz3X=$;1vV8DBLmz*R0huy>sx