refactor: modify webui dependencies & add some code

This commit is contained in:
Meeeeow 2017-06-26 02:13:39 +08:00 committed by Juan Picado @jotadeveloper
parent bffd8c3d7c
commit 3ba8d0827b
No known key found for this signature in database
GPG Key ID: 18AC54485952D158
32 changed files with 1494 additions and 3127 deletions

View File

@ -1,20 +0,0 @@
{
"presets": [
"react",
["env", {
"targets": {
"browsers": "last 2 versions"
},
"loose": true,
"modules": false
}]
],
"env": {
"test": {
"plugins": [
"transform-es2015-modules-commonjs"
]
}
}
}

4
.gitignore vendored
View File

@ -27,3 +27,7 @@ bundle.js
bundle.js.map
__tests__
__snapshots__
# Compiled script
static
!static/favicon.png

View File

@ -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": {

View File

@ -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);

View File

@ -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;

View File

@ -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)
}
);
});

View File

@ -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/'),
};

25
src/webui/.babelrc Normal file
View File

@ -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"
]
}
}
}

View File

@ -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

View File

@ -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);
}
})

View File

@ -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}
};

View File

@ -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()
]
}

View File

@ -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()
]
}

9
src/webui/src/App.jsx Normal file
View File

@ -0,0 +1,9 @@
import React from 'react';
import classes from './test.scss';
export default class App extends React.Component {
render() {
return <h1 className={classes.helloWorld}>Hello, Verdaccio</h1>
}
}

View File

@ -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 (
<MuiThemeProvider muiTheme={muiTheme}>
<main>
<Header baseUrl={this.props.baseUrl} username={this.props.username}/>
<div className="wrapper">
<Search updatePackages={this.updatePackages}/>
<List packages={this.state.packages}/>
</div>
</main>
</MuiThemeProvider>
);
}
}
App.propTypes = {
packages: PropTypes.array.isRequired,
baseUrl: PropTypes.string.isRequired,
username: PropTypes.string,
};
export default App;

View File

@ -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'; } /* '' */

View File

@ -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));
}

View File

@ -1,153 +0,0 @@
/*
Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
*/
.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;
}

View File

@ -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";

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -1,23 +0,0 @@
<div class="entry" data-name="{{ name }}" data-version="{{ version }}">
<div class="row">
<div class="col-md-8 col-sm-8">
<h4 class="title">
<a class='name icon-angle-right red' href='javascript:void(0)'>{{ name }}</a>
<small class='version'>v{{ version }}</small>
</h4>
</div>
<div class="col-md-4 col-sm-4">
<div class="author pull-right">
{{!-- I can't make hbs helper work without break code style --}}
{{#with author}}
<small>By: {{{ name }}}</small>
{{/with}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="description">{{ description }}</p>
</div>
</div>
</div>

View File

@ -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(<App {...state} />, document.getElementById('root'));

24
src/webui/src/index.jsx Normal file
View File

@ -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(
<AppContainer>
<Component/>
</AppContainer>,
rootNode
)
}
renderApp(App);
if (module.hot) {
module.hot.accept('./App', () => {
renderApp(App)
})
}

3
src/webui/src/test.scss Normal file
View File

@ -0,0 +1,3 @@
.helloWorld {
color: pink
}

15
src/webui/template.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="icon" type="image/png" href="<%= htmlWebpackPlugin.options.verdaccioURL %>static/favicon.png"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
window.VERDACCIO_API_URL = '<%= htmlWebpackPlugin.options.verdaccioURL %>';
</script>
</head>
<body class="body">
<div id="root"></div>
</body>
</html>

View File

@ -1,5 +0,0 @@
'use strict';
const CONTENT_JSON = 'application/json';
module.exports.CONTENT_JSON = CONTENT_JSON;

View File

@ -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

View File

@ -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']
}
};

2690
yarn.lock

File diff suppressed because it is too large Load Diff