Compare commits

...

52 Commits
2.1.4 ... 2.3.0

Author SHA1 Message Date
fengmk2
2a3b629a9c Release 2.3.0 2015-10-15 17:55:48 +08:00
fengmk2
9a4a7c6bf0 Merge pull request #684 from ibigbug/ant-design-fix
Ant design fix
2015-10-15 16:36:47 +08:00
Yuwei Ba
550024176f Add dev dependencies. 2015-10-15 15:22:34 +08:00
Yuwei Ba
90485d33dd Package page fix. 2015-10-15 14:57:14 +08:00
fengmk2
02d9bd923e refactor: add more sync log 2015-10-15 14:48:02 +08:00
Yuwei Ba
a256e044c5 Add mock data. 2015-10-15 14:35:20 +08:00
Yiyu He
a194fc8f3c Merge pull request #681 from cnpm/greenkeeper-koa-1.1.0
Update koa to version 1.1.0 🚀
2015-10-15 14:08:28 +08:00
Yiyu He
0f61c71e2b Merge pull request #682 from cnpm/greenkeeper-should-7.1.0
Update should to version 7.1.0 🚀
2015-10-15 14:08:12 +08:00
Yiyu He
2acfc52057 Merge pull request #683 from cnpm/greenkeeper-debug-2.2.0
Update debug to version 2.2.0 🚀
2015-10-15 14:07:45 +08:00
fengmk2
e144506634 refactor: add more sync log 2015-10-15 13:27:21 +08:00
Yuwei Ba
cc9b547c86 Fix sidebar overflow. 2015-10-15 12:25:24 +08:00
fengmk2
e8bea69a4d Merge pull request #680 from ibigbug/ant-design
Try to use ant design style
2015-10-15 11:47:00 +08:00
Yuwei Ba
cd36984a56 Clean code. 2015-10-15 11:39:02 +08:00
Yuwei Ba
ec00eeee75 Indent. 2015-10-15 11:38:04 +08:00
greenkeeperio-bot
571aea5277 chore(package): update debug to version 2.2.0
http://greenkeeper.io/
2015-10-15 07:51:41 +08:00
greenkeeperio-bot
9e9fd84e12 chore(package): update should to version 7.1.0
http://greenkeeper.io/
2015-10-15 00:39:54 +08:00
greenkeeperio-bot
dbe0f96855 chore(package): update koa to version 1.1.0
http://greenkeeper.io/
2015-10-14 22:48:35 +08:00
Yuwei Ba
66f17619e6 Remove default adBanner. 2015-10-14 21:32:55 +08:00
Yuwei Ba
1d491a244b Package pages. 2015-10-14 21:22:08 +08:00
Yuwei Ba
bbb6a59441 Common styles. 2015-10-14 21:22:08 +08:00
Yuwei Ba
76e0563308 search page. 2015-10-14 21:22:08 +08:00
Yuwei Ba
5e969cc305 Sync page. 2015-10-14 21:22:08 +08:00
Yuwei Ba
9d886b0599 Profile page antd style. 2015-10-14 21:22:08 +08:00
Yuwei Ba
cd2e96f460 Unpublished pkg page style. 2015-10-14 21:22:08 +08:00
Yuwei Ba
f86734674d Add page title for unpubed pkg. 2015-10-14 21:22:08 +08:00
Yuwei Ba
e2c37d312f Index page style use antd. 2015-10-14 21:22:08 +08:00
Yiyu He
689e7e1c08 Merge pull request #677 from cnpm/greenkeeper-moment-2.10.6
Update moment to version 2.10.6 🚀
2015-10-14 18:11:54 +08:00
Yiyu He
cd6f78d91b Merge pull request #678 from cnpm/greenkeeper-cfork-1.3.1
Update cfork to version 1.3.1 🚀
2015-10-14 18:11:40 +08:00
Yiyu He
b832c91d21 Merge pull request #679 from cnpm/greenkeeper-pg-4.4.2
Update pg to version 4.4.2 🚀
2015-10-14 18:11:25 +08:00
greenkeeperio-bot
646c830a68 chore(package): update pg to version 4.4.2
http://greenkeeper.io/
2015-10-14 18:00:54 +08:00
greenkeeperio-bot
e543f8578b chore(package): update cfork to version 1.3.1
http://greenkeeper.io/
2015-10-14 17:44:48 +08:00
greenkeeperio-bot
5ff7e2867f chore(package): update moment to version 2.10.6
http://greenkeeper.io/
2015-10-14 14:28:31 +08:00
fengmk2
98e8e7d498 Merge pull request #671 from ibigbug/use-qn-dn
feat(badge): Use qiniu cdn
2015-10-08 18:20:26 +08:00
Yuwei Ba
b7eb9f8374 feat(badge): Use qiniu cdn
Issue #658
2015-10-08 17:28:36 +08:00
fengmk2
12a8eff1f6 Release 2.2.1 2015-09-30 17:30:51 +08:00
fengmk2
9156be88a9 Merge pull request #666 from cnpm/support-nfs.url-generator
fix: support nfs.url is generator
2015-09-30 17:29:31 +08:00
fengmk2
cebbf7dda2 Merge pull request #669 from cnpm/try_catch
move out try/catch block
2015-09-30 17:25:25 +08:00
fengmk2
ea226e8ad6 test: use istanbul 2015-09-30 17:22:14 +08:00
Jackson Tian
eb3b79cae2 move out try/catch block 2015-09-30 17:01:10 +08:00
fengmk2
49b70b4b4d fix: support nfs.url is generator 2015-09-29 20:13:58 +08:00
fengmk2
af724960c2 Release 2.2.0 2015-09-29 01:28:32 +08:00
fengmk2
79797376d3 Merge pull request #663 from cnpm/list-package-by-username
feat: list packages by username
2015-09-28 14:05:26 +08:00
fengmk2
7fd264440e feat: list packages by username
GET /-/users/:user/packages

return user packages list

{
  "user": {
    "name": $name
  },
  "packages": [
    {
      "name": $name,
      "description": $description,
      "version": $version
    }, ...
  ],
}

closes #661
2015-09-28 13:58:02 +08:00
fengmk2
1982b9404e Merge pull request #656 from cnpm/badge-subject
feat(badge): support custom subject
2015-09-08 11:01:29 +08:00
fengmk2
4bea6f4e5f test: use codecov 2015-09-08 10:58:53 +08:00
fengmk2
3dd04b6aac feat(badge): support custom subject
https://cnpmjs.org/badge/v/npm.svg?tag=beta&subject=偏右
=>
https://img.shields.io/badge/%E5%81%8F%E5%8F%B3-3.3.1-blue.svg?style=flat-square

closes #655
2015-09-08 10:51:34 +08:00
fengmk2
ec605efc9c Merge pull request #653 from cnpm/since-tool
feat(sync): add sync scripts
2015-09-08 10:45:52 +08:00
fengmk2
7f27447dac fix(sync): add recover logic 2015-09-08 08:03:28 +08:00
fengmk2
a2c151f246 feat(sync): add sync scripts 2015-09-06 14:50:12 +08:00
fengmk2
35efc132b3 Release 2.1.5 2015-09-05 22:00:41 +08:00
fengmk2
dd37527651 Merge pull request #652 from cnpm/filter-update-packages-by-modified
fix: only sync update packages
2015-09-05 21:48:35 +08:00
fengmk2
a82e772097 fix: only sync update packages 2015-09-05 21:41:27 +08:00
43 changed files with 1078 additions and 494 deletions

View File

@@ -2,3 +2,6 @@ node_modules/
coverage/
.tmp/
.git/
tools/
public/
test/

View File

@@ -1,8 +1,11 @@
sudo: false
language: node_js
node_js:
- 'iojs-2'
- '1'
- '2'
- '4'
addons:
- postgresql: '9.3'
script: 'make test-travis-all'
after_script: 'npm install coveralls@2 && cat ./coverage/lcov.info | coveralls'
after_script:
- "npm i codecov.io && cat ./coverage/coverage.json | ./node_modules/codecov.io/bin/codecov.io.js"

View File

@@ -5,3 +5,5 @@ dead-horse <dead_horse@qq.com> (https://github.com/dead-horse)
alsotang <alsotang@gmail.com> (https://github.com/alsotang)
4simple <wondger@qq.com> (https://github.com/4simple)
afc163 <afc163@gmail.com> (https://github.com/afc163)
Yuwei Ba <i@xiaoba.me> (https://github.com/ibigbug)

View File

@@ -1,4 +1,54 @@
2.3.0 / 2015-10-15
==================
* Add dev dependencies.
* Package page fix.
* refactor: add more sync log
* Add mock data.
* refactor: add more sync log
* Fix sidebar overflow.
* Merge pull request #680 from ibigbug/ant-design
* Clean code.
* Indent.
* chore(package): update debug to version 2.2.0
* chore(package): update should to version 7.1.0
* chore(package): update koa to version 1.1.0
* Remove default adBanner.
* Package pages.
* Common styles.
* search page.
* Sync page.
* Profile page antd style.
* Unpublished pkg page style.
* Add page title for unpubed pkg.
* Index page style use antd.
* chore(package): update pg to version 4.4.2
* chore(package): update cfork to version 1.3.1
* chore(package): update moment to version 2.10.6
* feat(badge): Use qiniu cdn
2.2.1 / 2015-09-30
==================
* test: use istanbul
* pref: move out try/catch block
* fix: support nfs.url is generator
2.2.0 / 2015-09-29
==================
* feat: list packages by username
* test: use codecov
* feat(badge): support custom subject
* fix(sync): add recover logic
* feat(sync): add sync scripts
2.1.5 / 2015-09-05
==================
* fix: only sync update packages
2.1.4 / 2015-09-05
==================

View File

@@ -3,12 +3,12 @@ REPORTER = spec
TIMEOUT = 30000
MOCHA_OPTS =
DB = sqlite
DISTURL = http://npm.taobao.org/mirrors/iojs
DISTURL = https://npm.taobao.org/mirrors/iojs
BIN = iojs
ifeq ($(findstring io.js, $(shell which node)),)
BIN = node
DISTURL = http://npm.taobao.org/mirrors/node
DISTURL = https://npm.taobao.org/mirrors/node
endif
install:
@@ -56,7 +56,7 @@ test-pg: init-pg
test-all: test-sqlite test-mysql
test-cov cov: install init-database
@NODE_ENV=test DB=${DB} $(BIN) --harmony \
@NODE_ENV=test DB=${DB} $(BIN) \
node_modules/.bin/istanbul cover --preserve-comments \
node_modules/.bin/_mocha \
-- -u exports \
@@ -77,10 +77,9 @@ test-cov-mysql: init-mysql
test-travis: install init-database
@NODE_ENV=test DB=${DB} CNPM_SOURCE_NPM=http://registry.npmjs.com CNPM_SOURCE_NPM_ISCNPM=false \
$(BIN) --harmony \
$(BIN) \
node_modules/.bin/istanbul cover --preserve-comments \
node_modules/.bin/_mocha \
--report lcovonly \
-- -u exports \
--reporter dot \
--timeout $(TIMEOUT) \

View File

@@ -3,29 +3,20 @@ cnpmjs.org
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]
[![Gittip][gittip-image]][gittip-url]
[![Test coverage][cov-image]][cov-url]
[![David deps][david-image]][david-url]
[![node version][node-image]][node-url]
[![npm download][download-image]][download-url]
[![gitter][gitter-image]][gitter-url]
[npm-image]: http://cnpmjs.org/badge/v/cnpmjs.org.svg?style=flat-square
[npm-url]: http://cnpmjs.org/package/cnpmjs.org
[travis-image]: https://img.shields.io/travis/cnpm/cnpmjs.org.svg?style=flat-square
[travis-url]: https://travis-ci.org/cnpm/cnpmjs.org
[coveralls-image]: https://img.shields.io/coveralls/cnpm/cnpmjs.org.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/cnpm/cnpmjs.org?branch=master
[gittip-image]: https://img.shields.io/gittip/fengmk2.svg?style=flat-square
[gittip-url]: https://www.gittip.com/fengmk2/
[cov-image]: http://codecov.io/github/cnpm/cnpmjs.org/coverage.svg?branch=master
[cov-url]: http://codecov.io/github/cnpm/cnpmjs.org?branch=master
[david-image]: https://img.shields.io/david/cnpm/cnpmjs.org.svg?style=flat-square
[david-url]: https://david-dm.org/cnpm/cnpmjs.org
[node-image]: https://img.shields.io/badge/node.js-%3E=_0.11-red.svg?style=flat-square
[node-url]: http://nodejs.org/download/
[download-image]: https://img.shields.io/npm/dm/cnpmjs.org.svg?style=flat-square
[download-url]: https://npmjs.org/package/cnpmjs.org
[gitter-image]: https://badges.gitter.im/Join%20Chat.svg
[gitter-url]: https://gitter.im/cnpm/cnpmjs.org?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
![logo](https://raw.github.com/cnpm/cnpmjs.org/master/logo.png)
@@ -120,8 +111,8 @@ Tips: make sure your code is following the [node-style-guide](https://github.com
## Sponsors
- [![UCloud云计算](https://www.ucloud.cn/www/img/www/logo.png)](http://www.ucloud.cn/sdk?sem=sdk-CNPMJS)
- [![UCloud云计算](https://www.ucloud.cn/static/style/images/about/logo.png)](http://www.ucloud.cn?sem=sdk-CNPMJS)
## License
MIT
[MIT](LICENSE.txt)

View File

@@ -1,11 +1,9 @@
/*!
* cnpmjs.org - common/nfs.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';

View File

@@ -1,6 +1,4 @@
/**!
* cnpmjs.org - config/index.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*

View File

@@ -1,11 +1,9 @@
/**!
* cnpmjs.org - controllers/registry/package/download.js
*
* Copyright(c) fengmk2 and other contributors.
* Copyright(c) cnpm and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';
@@ -18,6 +16,7 @@ var debug = require('debug')('cnpmjs.org:controllers:registry:download');
var mime = require('mime');
var utility = require('utility');
var defer = require('co-defer');
var is = require('is-type-of');
var nfs = require('../../../common/nfs');
var logger = require('../../../common/logger');
var common = require('../../../lib/common');
@@ -32,12 +31,16 @@ module.exports = function* download(next) {
var name = this.params.name || this.params[0];
var filename = this.params.filename || this.params[1];
var version = filename.slice(name.length + 1, -4);
var row = yield* packageService.getModule(name, version);
var row = yield packageService.getModule(name, version);
// can not get dist
var url = null;
if (typeof nfs.url === 'function') {
url = nfs.url(common.getCDNKey(name, filename));
if (is.generatorFunction(nfs.url)) {
url = yield nfs.url(common.getCDNKey(name, filename));
} else {
url = nfs.url(common.getCDNKey(name, filename));
}
}
debug('download %s %s %s %s', name, filename, version, url);
@@ -78,7 +81,7 @@ module.exports = function* download(next) {
this.attachment(filename);
this.etag = dist.shasum;
this.body = yield* downloadAsReadStream(dist.key);
this.body = yield downloadAsReadStream(dist.key);
};
defer.setInterval(function* () {

View File

@@ -0,0 +1,29 @@
/**!
* list packages by username
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <m@fengmk2.com> (http://fengmk2.com)
*/
'use strict';
/**
* Module dependencies.
*/
const packageService = require('../../../services/package');
module.exports = function*() {
const username = this.params.user;
const packages = yield packageService.listModulesByUser(username);
this.body = {
user: {
name: username,
},
packages: packages,
};
};

View File

@@ -1,6 +1,4 @@
/**!
* cnpmjs.org - controllers/sync_module_worker.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
@@ -874,6 +872,7 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
};
SyncModuleWorker.prototype._syncOneVersion = function *(versionIndex, sourcePackage) {
logger.syncInfo('[sync_module_worker] start sync %s@%s', sourcePackage.name, sourcePackage.version);
var that = this;
var username = this.username;
var downurl = sourcePackage.dist.tarball;
@@ -930,6 +929,7 @@ SyncModuleWorker.prototype._syncOneVersion = function *(versionIndex, sourcePack
try {
// get tarball
logger.syncInfo('[sync_module_worker] downloading %j to %j', downurl, filepath);
var r = yield urllib.request(downurl, options);
var statusCode = r.status || -1;
// https://github.com/cnpm/cnpmjs.org/issues/325
@@ -980,8 +980,17 @@ SyncModuleWorker.prototype._syncOneVersion = function *(versionIndex, sourcePack
};
// upload to NFS
logger.syncInfo('[sync_module_worker] uploading %j to nfs', options);
var result = yield nfs.upload(filepath, options);
return yield *afterUpload(result);
var result;
try {
result = yield nfs.upload(filepath, options);
} catch (err) {
logger.syncInfo('[sync_module_worker] upload %j to nfs error: %s', err);
throw err;
}
logger.syncInfo('[sync_module_worker] uploaded, saving %j to database', result);
var r = yield *afterUpload(result);
logger.syncInfo('[sync_module_worker] sync %s@%s done!', sourcePackage.name, sourcePackage.version);
return r;
} finally {
// remove tmp file whatever
fs.unlink(filepath, utility.noop);

View File

@@ -41,19 +41,22 @@ exports.version = function* () {
}
var subject = config.badgeSubject.replace(/\-/g, '--');
if (this.query.subject) {
subject = this.query.subject.replace(/\-/g, '--');
}
version = version.replace(/\-/g, '--');
var style = this.query.style || 'flat-square';
var url = util.format('https://img.shields.io/badge/%s-%s-%s.svg?style=%s',
subject, version, color, utility.encodeURIComponent(style));
var url = util.format('https://dn-img-shields-io.qbox.me/badge/%s-%s-%s.svg?style=%s',
utility.encodeURIComponent(subject), version, color, utility.encodeURIComponent(style));
this.redirect(url);
};
exports.downloads = function* () {
// https://img.shields.io/badge/downloads-100k/month-brightgreen.svg?style=flat-square
// https://dn-img-shields-io.qbox.me/badge/downloads-100k/month-brightgreen.svg?style=flat-square
var name = this.params[0];
var count = yield DownloadTotal.getTotalByName(name);
var style = this.query.style || 'flat-square';
var url = util.format('https://img.shields.io/badge/downloads-%s-brightgreen.svg?style=%s',
var url = util.format('https://dn-img-shields-io.qbox.me/badge/downloads-%s-brightgreen.svg?style=%s',
count, utility.encodeURIComponent(style));
this.redirect(url);
};

View File

@@ -68,7 +68,8 @@ module.exports = function* show(next) {
}
}
yield this.render('package_unpublished', {
package: data
package: data,
title: 'Package - ' + name
});
return;
}
@@ -178,7 +179,7 @@ module.exports = function* show(next) {
pkg.engines[k] = {
version: engine,
title: k + ': ' + engine,
badgeURL: 'https://img.shields.io/badge/' + encodeURIComponent(k) +
badgeURL: 'https://dn-img-shields-io.qbox.me/badge/' + encodeURIComponent(k) +
'-' + encodeURIComponent(engine) + '-' + color + '.svg?style=flat-square',
};
}

View File

@@ -1,12 +1,10 @@
/**!
* cnpmjs.org - dispatch.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* dead_horse <dead_horse@qq.com>
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';

View File

@@ -9,6 +9,7 @@ So `cnpm` is meaning: **Company npm**.
- [Node.js](https://nodejs.org) version: <span id="node-version"></span>
- For developers behind the GFW, please visit [the Chinese mirror](https://npm.taobao.org). 中国用户请访问[国内镜像站点](https://npm.taobao.org/)。
<div class="ant-table">
<table class="downloads">
<tbody>
<tr>
@@ -28,12 +29,17 @@ So `cnpm` is meaning: **Company npm**.
</tr>
</tbody>
</table>
</div>
<div class="sync" style="display:none;">
<h3>Sync Status</h3>
<p id="sync-model"></p>
<p>Last sync time is <span id="last-sync-time"></span>. </p>
<p class="syncing alert alert-info">The sync worker is working in the backend now. </p>
<div class="ant-alert ant-alert-info">
<span class="anticon ant-alert-icon anticon-info-circle"></span>
<span class="syncing ant-alert-description">The sync worker is working in the backend now. </span>
</div>
<div class="ant-table">
<table class="sync-status">
<tbody>
<tr>
@@ -48,6 +54,7 @@ So `cnpm` is meaning: **Company npm**.
</tr>
</tbody>
</table>
</div>
</div>
<script src="/js/readme.js"></script>
@@ -60,9 +67,9 @@ Default style is `flat-square`.
Badge URL: `http://cnpmjs.org/badge/v/cnpmjs.org.svg` ![cnpmjs.org-version-badge](//cnpmjs.org/badge/v/cnpmjs.org.svg)
* `<0.1.0 & >=0.0.0`: ![red-badge](https://img.shields.io/badge/cnpm-0.0.1-red.svg?style=flat-square)
* `<1.0.0 & >=0.1.0`: ![red-badge](https://img.shields.io/badge/cnpm-0.1.0-green.svg?style=flat-square)
* `>=1.0.0`: ![red-badge](https://img.shields.io/badge/cnpm-1.0.0-blue.svg?style=flat-square)
* `<0.1.0 & >=0.0.0`: ![red-badge](https://dn-img-shields-io.qbox.me/badge/cnpm-0.0.1-red.svg?style=flat-square)
* `<1.0.0 & >=0.1.0`: ![red-badge](https://dn-img-shields-io.qbox.me/badge/cnpm-0.1.0-green.svg?style=flat-square)
* `>=1.0.0`: ![red-badge](https://dn-img-shields-io.qbox.me/badge/cnpm-1.0.0-blue.svg?style=flat-square)
### Downloads
@@ -144,4 +151,4 @@ Release [History](/history).
## Sponsors
- [![UCloud云计算](https://www.ucloud.cn/www/img/www/logo.png)](http://www.ucloud.cn/sdk?sem=sdk-CNPMJS)
- [![UCloud云计算](https://www.ucloud.cn/static/style/images/about/logo.png)](http://www.ucloud.cn?sem=sdk-CNPMJS)

View File

@@ -1,6 +1,4 @@
/**!
* cnpmjs.org - index.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*

View File

@@ -1,11 +1,9 @@
/**!
* cnpmjs.org - models/index.js
*
* Copyright(c) fengmk2 and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';
@@ -15,7 +13,6 @@
*/
var path = require('path');
var Sequelize = require('sequelize');
var sequelize = require('../common/sequelize');
function load(name) {

View File

@@ -1,6 +1,6 @@
{
"name": "cnpmjs.org",
"version": "2.1.4",
"version": "2.3.0",
"description": "Private npm registry and web for Enterprise, base on MySQL and Simple Store Service",
"main": "index.js",
"scripts": {
@@ -16,14 +16,14 @@
"agentkeepalive": "~1.2.0",
"bluebird": "~2.9.7",
"bytes": "~1.0.0",
"cfork": "~1.2.2",
"cfork": "~1.3.1",
"co": "~4.3.1",
"co-defer": "~1.0.0",
"co-gather": "~0.0.1",
"co-sleep": "~0.0.1",
"commander": "~2.6.0",
"copy-to": "~2.0.1",
"debug": "~2.1.1",
"debug": "~2.2.0",
"error-formater": "~1.0.3",
"fs-cnpm": "~1.2.0",
"giturl": "~0.0.3",
@@ -32,8 +32,9 @@
"gravatar": "~1.1.0",
"humanize-ms": "~1.0.1",
"humanize-number": "~0.0.2",
"is-type-of": "~0.3.1",
"kcors": "~1.0.1",
"koa": "~0.17.0",
"koa": "~1.1.0",
"koa-limit": "~1.0.2",
"koa-markdown": "~2.0.1",
"koa-middlewares": "~2.1.0",
@@ -43,7 +44,7 @@
"mime": "~1.3.4",
"mini-logger": "~1.0.0",
"mkdirp": "~0.5.0",
"moment": "~2.9.0",
"moment": "~2.10.6",
"mysql": "~2.5.4",
"nodemailer": "~1.3.0",
"semver": "~4.2.0",
@@ -60,15 +61,15 @@
"chunkstream": "*",
"co-mocha": "*",
"contributors": "*",
"istanbul-harmony": "*",
"istanbul": "*",
"jshint": "*",
"mm": "*",
"mocha": "*",
"node-dev": "*",
"pedding": "*",
"pg": "~4.2.0",
"pg": "~4.4.2",
"pg-hstore": "~2.3.1",
"should": "~4.0.4",
"should": "~7.1.0",
"should-http": "*",
"sqlite3": "*",
"supertest": "*"
@@ -91,7 +92,7 @@
"registry"
],
"engines": {
"node": ">= 0.11.14"
"node": ">= 1.0.0"
},
"author": [
"fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)",

1
public/css/antd-0.9.1.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,28 +1,127 @@
body {
font-size: 16px;
color: #333333;
}
header {
max-width: 1140px;
min-width: 960px;
margin: 30px auto 30px auto;
.mb15 {
margin-bottom: 15px !important;
}
header .logo {
.container {
min-width: 960px;;
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto
}
@media (min-width: 768px) {
.container {
width:750px
}
}
@media (min-width: 992px) {
.container {
width:970px
}
}
@media (min-width: 1200px) {
.container {
width:1170px
}
}
hr {
margin-top: 20px;
margin-bottom: 20px;
border: 0;
border-top: 1px solid #eee;
height: 0;
}
#header {
padding: 30px 0;
height: 156px;
}
#header .logo {
display: inline-block;
}
header #search-input {
#header .logo a {
display: inline-block;
vertical-align: top;
}
#search-input {
display: inline-block;
width: 400px;
height: 50px;
font-size: 30px;
font-size: 20px;
float: right;
margin-top: 22px;
border-radius: 8px;
padding: 10px 20px;
}
#search .package.match {
font-weight: bold;
}
.bottom {
text-align: center;
font-size: 14px;
padding-bottom: 15px;
}
code {
padding: 2px 4px;
font-size: 95%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
}
img {
vertical-align: middle;
}
pre {
margin-bottom: 20px;
background: #333;
color: #fff;
border-radius: 6px;
margin-top: 30px;
padding: 10px 20px;
word-wrap: break-word;
}
pre code {
padding: 0;
font-size: inherit;
color: inherit;
white-space: pre-wrap;
background-color: transparent;
border-radius: 0;
}
.ant-table {
font-size: 14px;
}
.ant-alert {
font-size: 14px !important;
padding: 15px;
}
.pack-overview {
min-width: 960px;
color: #f1f1f1;
height: 300px;
width: 100%;
margin-bottom: 50px;
position: relative;
}
.pack-overview-background {
height: 300px;
@@ -34,13 +133,18 @@ header #search-input {
}
.pack-overview a {
color: #f1f1f1;
text-decoration: underline;
text-decoration: none;
font-size: 16px;
transition: all .2s ease-in-out;
padding-bottom: 2px;
border-bottom: 1px solid;
}
.pack-overview a:hover {
color: #ffffff;
opacity: .7;
}
.pack-info {
position: relative;
max-width: 1140px;
margin: 0 auto;
padding: 30px 0;
@@ -53,133 +157,125 @@ header #search-input {
line-height: 48px;
color: #fff;
}
.pack-description {
line-height: 28px;
text-overflow: ellipsis;
color: #fff;
font-family: "-apple-system", sans-serif;
margin-top: 20px;
display: block; /* Fallback for non-webkit */
display: -webkit-box;
width: 600px;
white-space:nowrap;
font-size: 20px;
line-height: 26px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
overflow:hidden;
max-height: 100px;
}
.deprecated {
text-decoration: line-through;
color: #BDBDBD;
}
.deprecated-content {
color: #FF8A65;
color: #555;
width: 600px;
white-space:nowrap;
text-overflow: ellipsis;
overflow:hidden;
font-style: italic;
}
.pack-ver {
font-size: 28px;
line-height: 48px;
}
.pack-repo {
margin-top: 50px;
.pack-lastup {
font-size: 14px;
display: inline-block;
}
.pack-repo {
position: absolute;
bottom: 10px;
text-align: right;
width: 100%;
}
.pack-repo a {
border: none;
}
.pack-repo a:hover {
border-bottom: 1px solid;
}
.pack-install {
position: absolute;
top: 85px;
top: 75px;
right: 0px;
max-width: 450px;
}
.pack-install pre {
border: none;
background-color: #666666;
color: #f1f1f1;
font-size: 16px;
width: 480px;
}
.pack-details {
max-width: 1140px;
min-width: 960px;
margin: 40px auto;
}
.pack-details a {
color: #333333;
}
.cols-box {
display: flex;
-webkit-box-pack: center;
.pack-details a:hover {
border-bottom: 1px solid;
opacity: .8;
}
.cols-box ul {
list-style: none;
margin: 0;
padding: 0;
}
.cols-box-item {
flex: 1;
height: 250px;
margin-right: 30px;
margin-bottom: 15px;
}
.cols-box-item:last-child {
margin-right: 0;
}
.cols-box-title {
font-size: 20px;
color: #428bca;
margin-bottom: 10px;
font-weight: bold;
overflow: hidden;
border-bottom: 1px solid #ccc;
padding-bottom: 3px;
}
.cols-box-item .more-item {
font-size: 16px;
line-height: 28px;
color: #428bca;
text-decoration: underline;
float: right;
margin-top: 15px;
}
.pack-dep-ver, .pack-download-num {
float: right;
}
.pack-lastup, .pack-sync {
margin-top: 10px;
}
.pack-sync a {
font-size: 23px;
}
.maintainers .row {
display: -moz-box;
display: -webkit-box;
display: box;
-webkit-box-pack: center;
margin-right: 0;
margin-left: 0;
float: left;
}
.maintainer {
-moz-box-flex: 1;
-webkit-box-flex: 1;
box-flex: 1;
margin-bottom: 10px;
width: 50%;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
line-height: 50px;
line-height: 30px;
overflow: hidden;
}
.maintainer a:hover {
font-style: italic;
border: none;
}
.maintainer .avatar {
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
border-radius: 30px;
width: 30px;
height: 30px;
margin-right: 10px;
}
.downloads .row {
margin-left: 0;
margin-right: 50px;
line-height: 28px;
border-bottom: 1px solid #f2f2f2;
}
.pack-readme {
max-width: 1140px;
min-width: 960px;
margin: 10px auto;
border-top: 1px solid #dddddd;
}
.pack-readme .title {
color: #dddddd;
font-weight: bolder;
margin-bottom: 20px;
text-align: right;
}

147
public/css/yue.css Normal file
View File

@@ -0,0 +1,147 @@
/**
* yue.css
*
* yue.css is designed for readable content.
*
* Copyright (c) 2013 - 2014 by Hsiaoming Yang.
*/
.yue h1,
.yue h2,
.yue h3,
.yue h4,
.yue h5,
.yue h6 {
font-family: "-apple-system", "Georgia", "Xin Gothic", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei", "SimSun", sans-serif;
color: #222223;
}
.yue h1 {
font-size: 1.8em;
margin: 0.67em 0;
}
.yue > h1 {
margin-top: 0;
font-size: 2em;
}
.yue h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
.yue h3 {
font-size: 1.17em;
margin: 1em 0;
}
.yue h4,
.yue h5,
.yue h6 {
font-size: 1em;
margin: 1.6em 0 1em 0;
}
.yue h6 {
font-weight: 500;
}
.yue p {
margin-top: 0;
margin-bottom: 1.46em;
}
.yue strong,
.yue b {
font-weight: 700;
color: #222223;
}
.yue em,
.yue i {
font-style: italic;
color: #222223;
}
.yue hr {
display: block;
width: 14%;
margin: 40px auto 34px;
border: 0 none;
border-top: 3px solid #dededc;
}
.yue blockquote {
margin: 0 0 1.64em 0;
border-left: 3px solid #dadada;
padding-left: 12px;
color: #666664;
}
.yue blockquote a {
color: #666664;
}
.yue ul,
.yue ol {
margin: 0 0 24px 6px;
padding-left: 16px;
}
.yue ul {
list-style-type: square;
}
.yue ol {
list-style-type: decimal;
}
.yue li {
margin-bottom: 0.2em;
}
.yue li ul,
.yue li ol {
margin-top: 0;
margin-bottom: 0;
margin-left: 14px;
}
.yue li ul {
list-style-type: disc;
}
.yue li ul ul {
list-style-type: circle;
}
.yue li p {
margin: 0.4em 0 0.6em;
}
.yue .unstyled {
list-style-type: none;
margin: 0;
padding: 0;
}
@media (min-width: 1100px) {
.yue blockquote {
margin-left: -24px;
padding-left: 20px;
border-width: 4px;
}
.yue blockquote blockquote {
margin-left: 0;
}
}

View File

@@ -1,12 +1,10 @@
/**!
* cnpmjs.org - routes/registry.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* dead_horse <dead_horse@qq.com>
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
"use strict";
@@ -36,6 +34,7 @@ var removeOneVersion = require('../controllers/registry/package/remove_version')
var updatePackage = require('../controllers/registry/package/update');
var downloadPackage = require('../controllers/registry/package/download');
var downloadTotal = require('../controllers/registry/package/download_total');
var listPackagesByUser = require('../controllers/registry/package/list_by_user');
var addUser = require('../controllers/registry/user/add');
var showUser = require('../controllers/registry/user/show');
@@ -113,6 +112,7 @@ function routes(app) {
// list all packages of user
app.get('/-/by-user/:user', userPackage.list);
app.get('/-/users/:user/packages', listPackagesByUser);
// download times
app.get('/downloads/range/:range/:name', downloadTotal);

View File

@@ -15,6 +15,7 @@
* Module dependencies.
*/
var ms = require('humanize-ms');
var urllib = require('../common/urllib');
var config = require('../config');
@@ -69,6 +70,83 @@ exports.get = function* (name) {
return data;
};
exports.fetchUpdatesSince = function* (lastSyncTime, timeout) {
var lastModified = lastSyncTime - ms('10m');
var data = yield exports.getAllSince(lastModified, timeout);
var result = {
lastModified: lastSyncTime,
names: [],
};
if (!data) {
return result;
}
if (Array.isArray(data)) {
// support https://registry.npmjs.org/-/all/static/today.json
var maxModified;
data.forEach(function (pkg) {
if (pkg.time && pkg.time.modified) {
var modified = Date.parse(pkg.time.modified);
if (modified >= lastModified) {
result.names.push(pkg.name);
}
if (!maxModified || modified > maxModified) {
maxModified = modified;
}
} else {
result.names.push(pkg.name);
}
});
if (maxModified) {
result.lastModified = maxModified;
}
} else {
// /-/all/since
if (data._updated) {
result.lastModified = data._updated;
delete data._updated;
}
result.names = Object.keys(data);
}
return result;
};
exports.fetchAllPackagesSince = function* (timestamp) {
var r = yield request('/-/all/static/all.json', {
registry: 'http://registry.npmjs.org',
timeout: 600000
});
// {"_updated":1441520402174,"0":{"name":"0","dist-tags
// "time":{"modified":"2014-06-17T06:38:43.495Z"}
var data = r.data;
var result = {
lastModified: timestamp,
lastModifiedName: null,
names: [],
};
var maxModified;
for (var key in data) {
if (key === '_updated') {
continue;
}
var pkg = data[key];
if (!pkg.time || !pkg.time.modified) {
continue;
}
var modified = Date.parse(pkg.time.modified);
if (modified >= timestamp) {
result.names.push(pkg.name);
}
if (!maxModified || modified > maxModified) {
maxModified = modified;
result.lastModifiedName = pkg.name;
}
}
if (maxModified) {
result.lastModified = maxModified;
}
return result;
};
exports.getAllSince = function* (startkey, timeout) {
var r = yield* request('/-/all/since?stale=update_after&startkey=' + startkey, {
timeout: timeout || 300000

View File

@@ -28,19 +28,23 @@ var NpmModuleMaintainer = models.NpmModuleMaintainer;
// module
var _parseRow = function (row) {
if (row.package.indexOf('%7B%22') === 0) {
// now store package will encodeURIComponent() after JSON.stringify
row.package = decodeURIComponent(row.package);
}
row.package = JSON.parse(row.package);
if (typeof row.publish_time === 'string') {
// pg bigint is string
row.publish_time = Number(row.publish_time);
}
};
// module:read
function parseRow(row) {
if (row && row.package) {
try {
if (row.package.indexOf('%7B%22') === 0) {
// now store package will encodeURIComponent() after JSON.stringify
row.package = decodeURIComponent(row.package);
}
row.package = JSON.parse(row.package);
if (typeof row.publish_time === 'string') {
// pg bigint is string
row.publish_time = Number(row.publish_time);
}
_parseRow(row);
} catch (e) {
console.warn('parse package error: %s, id: %s version: %s, error: %s', row.name, row.id, row.version, e);
}
@@ -128,7 +132,7 @@ exports.listModules = function* (names) {
id: ids
},
attributes: [
'name', 'description'
'name', 'description', 'version',
]
});
return rows;

View File

@@ -1,4 +1,4 @@
/*!
/**!
* cnpmjs.org - sync/sync_all.js
*
* Copyright(c) cnpmjs.org and other contributors.
@@ -6,6 +6,7 @@
*
* Authors:
* dead_horse <dead_horse@qq.com> (http://deadhorse.me)
* fengmk2 <m@fengmk2.com> (http://fengmk2.com)
*/
'use strict';
@@ -14,7 +15,6 @@
* Module dependencies.
*/
var ms = require('humanize-ms');
var thunkify = require('thunkify-wrap');
var config = require('../config');
var Status = require('./status');
@@ -40,25 +40,6 @@ function* getFirstSyncPackages(lastSyncModule) {
}
}
/**
* get all the packages that update time > lastSyncTime
* @param {Number} lastSyncTime
*/
function* getCommonSyncPackages(lastSyncTime) {
var data = yield* npmService.getAllSince(lastSyncTime);
if (!data) {
return [];
} else if (Array.isArray(data)) {
// support https://registry.npmjs.org/-/all/static/today.json
return data.map(function (item) {
return item.name;
});
} else {
delete data._updated;
return Object.keys(data);
}
}
module.exports = function* sync() {
var syncTime = Date.now();
var info = yield* totalService.getTotalInfo();
@@ -72,7 +53,9 @@ module.exports = function* sync() {
logger.syncInfo('First time sync all packages from official registry');
packages = yield* getFirstSyncPackages(info.last_sync_module);
} else {
packages = yield* getCommonSyncPackages(info.last_sync_time - ms('10m'));
var result = yield npmService.fetchUpdatesSince(info.last_sync_time);
syncTime = result.lastModified;
packages = result.names;
}
packages = packages || [];

View File

@@ -1,6 +1,4 @@
/*!
* cnpmjs.org - sync/sync_exist.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
@@ -16,7 +14,6 @@
var debug = require('debug')('cnpmjs.org:sync:sync_exist');
var Status = require('./status');
var ms = require('humanize-ms');
var thunkify = require('thunkify-wrap');
var config = require('../config');
var npmService = require('../services/npm');
@@ -63,22 +60,10 @@ module.exports = function* sync() {
}
allPackages = pkgs;
} else {
debug('sync new module from last exist sync time: %s', info.last_sync_time);
var data = yield* npmService.getAllSince(info.last_exist_sync_time - ms('10m'));
if (!data) {
allPackages = [];
} else if (Array.isArray(data)) {
// support https://registry.npmjs.org/-/all/static/today.json
allPackages = data.map(function (item) {
return item.name;
});
} else {
if (data._updated) {
syncTime = data._updated;
delete data._updated;
}
allPackages = Object.keys(data);
}
debug('sync new module from last exist sync time: %s', info.last_exist_sync_time);
var result = yield npmService.fetchUpdatesSince(info.last_exist_sync_time);
allPackages = result.names;
syncTime = result.lastModified;
}
var packages = intersection(existPackages, allPackages);

66
sync/sync_since.js Normal file
View File

@@ -0,0 +1,66 @@
/**!
* sync packages since by some days ago
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <m@fengmk2.com> (http://fengmk2.com)
*/
'use strict';
/**
* Module dependencies.
*/
const thunkify = require('thunkify-wrap');
const co = require('co');
const ms = require('humanize-ms');
const npmService = require('../services/npm');
const SyncModuleWorker = require('../controllers/sync_module_worker');
function* sync(sinceTimestamp) {
console.log('Fetching packages since: %s', new Date(sinceTimestamp));
var result = yield npmService.fetchAllPackagesSince(sinceTimestamp);
var packages = result.names;
packages = packages || [];
if (!packages.length) {
console.log('no packages need be sync');
process.exit(0);
}
// var news = [];
// for (var i = 0; i < packages.length; i++) {
// if (packages[i] === 'elwms') {
// news = packages.slice(i);
// break;
// }
// }
// packages = news;
console.log('lastModified: %s, lastModified package: %s, total %d packages to sync: %j',
new Date(result.lastModified), result.lastModifiedName, packages.length, packages);
var worker = new SyncModuleWorker({
username: 'sync_since',
name: packages,
noDep: true,
concurrency: 1,
syncUpstreamFirst: false,
});
worker.start();
var end = thunkify.event(worker);
yield end();
console.log('All packages sync done, successes %d, fails %d',
worker.successes.length, worker.fails.length);
process.exit(0);
}
co(function* () {
var timestamp = Date.now() - ms(process.argv[2] || '30d');
yield sync(timestamp);
}).catch(function (err) {
console.error(err.stack);
process.exit(1);
});

View File

@@ -1,11 +1,9 @@
/**!
* cnpmjs.org - test/controllers/registry/package/download.test.js
*
* Copyright(c) fengmk2 and other contributors.
* Copyright(c) cnpm and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';
@@ -15,36 +13,66 @@
*/
var request = require('supertest');
var mm = require('mm');
var config = require('../../../../config');
var app = require('../../../../servers/registry');
var utils = require('../../../utils');
describe('controllers/registry/package/download.test.js', function () {
describe('test/controllers/registry/package/download.test.js', function () {
before(function (done) {
var pkg = utils.getPackage('@cnpmtest/download-test-module', '1.0.0', utils.admin);
request(app.listen())
request(app)
.put('/' + pkg.name)
.set('authorization', utils.adminAuth)
.send(pkg)
.expect(201, done);
});
afterEach(mm.restore);
describe('GET /:name/download/:filename', function () {
it('should download a file with 200', function (done) {
request(app.listen())
request(app)
.get('/@cnpmtest/download-test-module/download/@cnpmtest/download-test-module-1.0.0.tgz')
.expect(200, done);
});
it('should alias /:name/-/:filename to /:name/download/:filename', function (done) {
request(app.listen())
request(app)
.get('/@cnpmtest/download-test-module/-/@cnpmtest/download-test-module-1.0.0.tgz')
.expect(200, done);
});
it('should 404 when package not exists', function (done) {
request(app.listen())
request(app)
.get('/@cnpmtest/download-test-module-not-exists/download/@cnpmtest/download-test-module-not-exists-1.0.0.tgz')
.expect(404, done);
});
describe('nfs.url is function', function() {
it('should work with nfs.url is generatorFunction', function(done) {
mm(config.nfs, 'url', function*(key) {
return 'http://foo.test.com' + key;
});
mm(config, 'downloadRedirectToNFS', true);
request(app)
.get('/@cnpmtest/download-test-module/-/@cnpmtest/download-test-module-1.0.0.tgz')
.expect('Location', 'http://foo.test.com/@cnpmtest/download-test-module/-/@cnpmtest/download-test-module-1.0.0.tgz')
.expect(302, done);
});
it('should work with nfs.url is function', function(done) {
mm(config.nfs, 'url', function(key) {
return 'http://foo.test.com' + key;
});
mm(config, 'downloadRedirectToNFS', true);
request(app)
.get('/@cnpmtest/download-test-module/-/@cnpmtest/download-test-module-1.0.0.tgz')
.expect('Location', 'http://foo.test.com/@cnpmtest/download-test-module/-/@cnpmtest/download-test-module-1.0.0.tgz')
.expect(302, done);
});
});
});
});

View File

@@ -0,0 +1,87 @@
/**!
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';
/**
* Module dependencies.
*/
var request = require('supertest');
var mm = require('mm');
var should = require('should');
var app = require('../../../../servers/registry');
var utils = require('../../../utils');
describe('test/controllers/registry/package/list_by_user.test.js', function () {
var user = 'cnpmjstest_list_by_user';
var userauth = 'Basic ' + new Buffer(user + ':' + user).toString('base64');
afterEach(mm.restore);
before(function (done) {
var pkg = utils.getPackage('@cnpmtest/list_by_user_module1', '1.0.1', user);
request(app)
.put('/' + pkg.name)
.set('authorization', userauth)
.send(pkg)
.expect(201, function (err) {
should.not.exist(err);
var pkg2 = utils.getPackage('@cnpmtest/list_by_user_module2', '2.0.0', user);
request(app)
.put('/' + pkg2.name)
.set('authorization', userauth)
.send(pkg2)
.expect(201, done);
});
});
describe('GET /-/users/:user/packages', function () {
it('should get 200', function (done) {
var url = '/-/users/' + user + '/packages';
request(app)
.get(url)
.expect(function(res) {
var data = res.body;
data.user.name.should.equal(user);
var map = {};
data.packages.forEach(function(pkg) {
map[pkg.name] = pkg;
});
map['@cnpmtest/list_by_user_module1'].should.be.an.Object;
map['@cnpmtest/list_by_user_module1'].should.eql({
name: '@cnpmtest/list_by_user_module1',
description: '',
version: '1.0.1',
});
map['@cnpmtest/list_by_user_module2'].should.be.an.Object;
map['@cnpmtest/list_by_user_module2'].should.eql({
name: '@cnpmtest/list_by_user_module2',
description: '',
version: '2.0.0',
});
})
.expect(200, done);
});
it('should get empty packages list when user not exists', function (done) {
var url = '/-/users/not-exist-username/packages';
request(app)
.get(url)
.expect({
user: {
name: 'not-exist-username',
},
packages: [],
})
.expect(200, done);
});
});
});

View File

@@ -5,7 +5,7 @@
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';
@@ -35,7 +35,7 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square')
.expect('Location', 'https://img.shields.io/badge/cnpm-1.0.1-blue.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-1.0.1-blue.svg?style=flat-square')
.expect(302, done);
});
});
@@ -50,7 +50,22 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square&tag=v2')
.expect('Location', 'https://img.shields.io/badge/cnpm-2.0.1-blue.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-2.0.1-blue.svg?style=flat-square')
.expect(302, done);
});
});
it('should support custom subject', function (done) {
var pkg = utils.getPackage('@cnpmtest/badge-test-module', '3.0.1', utils.admin, 'v3');
request(registry)
.put('/' + pkg.name)
.set('authorization', utils.adminAuth)
.send(pkg)
.end(function (err) {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square&tag=v3&subject=ant-design')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/ant--design-3.0.1-blue.svg?style=flat-square')
.expect(302, done);
});
});
@@ -65,7 +80,7 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square')
.expect('Location', 'https://img.shields.io/badge/cnpm-1.0.0--beta1-blue.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-1.0.0--beta1-blue.svg?style=flat-square')
.expect(302, done);
});
});
@@ -80,7 +95,7 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square')
.expect('Location', 'https://img.shields.io/badge/cnpm-0.1.0-green.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-0.1.0-green.svg?style=flat-square')
.expect(302, done);
});
});
@@ -95,7 +110,7 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/v/@cnpmtest/badge-test-module.svg?style=flat-square')
.expect('Location', 'https://img.shields.io/badge/cnpm-0.0.0-red.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-0.0.0-red.svg?style=flat-square')
.expect(302, done);
});
});
@@ -103,7 +118,7 @@ describe('controllers/web/badge.test.js', function () {
it('should show invalid when package not exists', function (done) {
request(app)
.get('/badge/v/@cnpmtest/badge-test-module-not-exists.svg?style=flat')
.expect('Location', 'https://img.shields.io/badge/cnpm-invalid-lightgrey.svg?style=flat')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/cnpm-invalid-lightgrey.svg?style=flat')
.expect(302, done);
});
});
@@ -119,7 +134,7 @@ describe('controllers/web/badge.test.js', function () {
should.not.exists(err);
request(app)
.get('/badge/d/@cnpmtest/badge-download-module.svg?style=flat-square')
.expect('Location', 'https://img.shields.io/badge/downloads-0-brightgreen.svg?style=flat-square')
.expect('Location', 'https://dn-img-shields-io.qbox.me/badge/downloads-0-brightgreen.svg?style=flat-square')
.expect(302, done);
});
});

View File

@@ -38,6 +38,7 @@ var usernames = [
'cnpmjstest10', // admin
'cnpmjstestAdmin2', // other admin
'cnpmjstestAdmin3', // other admin
'cnpmjstest_list_by_user',
];
var count = usernames.length;

View File

@@ -9,7 +9,7 @@ module.exports = {
node: {
version: '>= 0.11.13',
title: 'node: >=0.11.13',
badgeURL: 'https://img.shields.io/badge/node-%3E%3D%200.11.13-red.svg?style=flat-square',
badgeURL: 'https://dn-img-shields-io.qbox.me/badge/node-%3E%3D%200.11.13-red.svg?style=flat-square',
}
},
_publish_on_cnpm: false,

View File

@@ -1,6 +1,15 @@
module.exports = {
package: {
name: 'inch-plugin-socket-behaviour-desktop',
description: description()
},
__requires: ['./default']
};
function description() {
var s = ''
for (var i = 0; i < 10; i++) {
s += 'description: Koa web app framework'
}
return s
}

View File

@@ -124,7 +124,7 @@ describe('test/services/package.test.js', function () {
var mods = yield* Package.listPublicModulesByUser('listPublicModuleNamesByUser-user');
mods.should.length(3);
mods.forEach(function (mod) {
mod.toJSON().should.have.keys('name', 'description');
mod.toJSON().should.have.keys('name', 'description', 'version');
mod.name.should.containEql('listPublicModuleNamesByUser-module');
});
});

View File

@@ -56,7 +56,16 @@ describe('test/sync/sync_all.test.js', function () {
versions: {
'0.0.2': 'latest'
}
}
},
{
name: 'mk2testmodule1',
time: {
modified: '2015-09-05T07:31:35.734Z',
},
versions: {
'0.0.2': 'latest'
}
},
]);
mm.data(npmSerivce, 'getShort', ['mk2testmodule']);
mm.data(totalService, 'getTotalInfo', {last_sync_time: Date.now()});

View File

@@ -1,11 +1,9 @@
/**!
* cnpmjs.org - test/utils.js
*
* Copyright(c) fengmk2 and other contributors.
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
*/
'use strict';

View File

@@ -8,34 +8,15 @@
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="shortcut icon" href="/favicon.png">
<!-- Bootstrap -->
<link href="//dn-staticfile.qbox.me/twitter-bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
<!-- Ant design -->
<link href="/css/antd-0.9.1.min.css" rel="stylesheet" media="screen">
<link href="/css/main.css" rel="stylesheet" media="screen">
<link href="/css/yue.css" rel="stylesheet" media="screen">
<link href="/css/github.css" rel="stylesheet" media="screen">
<link href="/css/github-markdown.css" rel="stylesheet" media="screen">
<!-- JavaScript plugins (requires jQuery) -->
<script src="//dn-staticfile.qbox.me/jquery/2.0.3/jquery.min.js"></script>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="CNPM" />
<style>
#tagline{display:inline;}
/*#wrapper{padding:5% 8%;min-width:480px;}*/
#tagline{font:0.8em serif;color:#888;display:inline-block;margin:0.1em 0 1.2em;}
#fork{position:fixed;top:0;right:0;_position:absolute;}
.bottom{text-align: center;}
#content-header {margin: 20px 0 50px 0;}
.user .avatar {
width: 32px;
height: 32px;
margin-bottom: 3px;
}
table.downloads td.count {
text-align: right;
}
.nav-tabs{margin:20px 0;}
.nav-cont{display:none;}
.nav-cont.active{display:block;}
</style>
<script>
$(function () {
$('#search-input').keypress(function (e) {
@@ -62,15 +43,17 @@
</head>
<body>
<div class="container">
<header>
<header id="header">
<div class="logo">
<a href="/"><img src="{{logoURL}}"></a>
{{adBanner}}
</div>
<input type="text" id="search-input" class="form-control" placeholder="Search Packages">
<input type="text" id="search-input" class="ant-input ant-input-lg" placeholder="Search Packages">
</header>
<%- locals.body %>
<div class="yue">
<%- locals.body %>
</div>
<div class="bottom">
<hr/>
<p>
@@ -78,8 +61,6 @@
</p>
</div>
</div>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="//dn-staticfile.qbox.me/twitter-bootstrap/3.2.0/js/bootstrap.min.js"></script>
<!-- Enable responsive features in IE8 with Respond.js (https://github.com/scottjehl/Respond) -->
<script src="//dn-staticfile.qbox.me/respond.js/1.2.0/respond.min.js"></script>
@@ -91,7 +72,6 @@
$(function () {
$('pre code').parent().addClass('prettyprint');
prettyPrint();
$('table').addClass('table table-bordered table-striped');
});
</script>
</body>

View File

@@ -4,7 +4,7 @@
<% if (package.deprecated) { %>
<div class="pack-name deprecated"><%= package.name %></div>
<% if (package.description) {%>
<div class="pack-description deprecated"><%= package.description %></div>
<p class="pack-description deprecated"><%= package.description %></p>
<% } %>
<div class="deprecated-content" title="<%= package.deprecated %>"><%= package.deprecated %></div>
<% } else { %>
@@ -23,34 +23,34 @@
<% }
}%>
</div>
<% if (package.fromNow) { %>
<div class="pack-lastup">
Last updated <%= package.fromNow %>
<% if (package.lastPublishedUser) {
var name = package.lastPublishedUser.name;
%>
by <a href="/~<%= name %>"><%= name %></a>
<% } %>
.
</div>
<% } %>
<div class="pack-repo">
<% if (package.fromNow) { %>
<div class="pack-lastup">
Last updated <%= package.fromNow %>
<% if (package.lastPublishedUser) {
var name = package.lastPublishedUser.name;
%>
by <a href="/~<%= name %>"><%= name %></a>
<% } %>
.
</div>
<% } %>
<% if (package.license) { %>
<a href="<%= package.license.url %>" target="_blank"><%= package.license.name %></a>
<% } %>
<% if (package.repository) { %>
<% if (package.license) {%> | <% } %>
<% if (package.license) {%> &middot; <% } %>
<a href="<%= package.repository.weburl %>" target="_blank">Repository</a>
<% } %>
<% if (package.bugs.url) { %>
<% if (package.license || package.repository) {%> | <% } %>
<% if (package.license || package.repository) {%> &middot; <% } %>
<a href="<%= package.bugs.url %>" target="_blank">Bugs</a>
<% } %>
<% if (package.license || package.repository || package.bugs.url) {%> | <% } %>
<% if (package.license || package.repository || package.bugs.url) {%> &middot; <% } %>
<% if (!package._publish_on_cnpm) { %>
<a href="https://www.npmjs.org/package/<%= package.name %>" target="_blank">Original npm</a>
@@ -71,106 +71,117 @@
</div>
</div>
<div class="pack-details cols-box">
<div class="pack-dep cols-box-item">
<div class="cols-box-title">
<%
var deps = Object.keys(package.dependencies || {})
var l = deps.length
var m = 8
%>
Dependencies<%= ' (' + l + ')' %>
<% if (l > m) { %>
<a class="more-item" href="<%= package.registryUrl %>" target="_blank">+<%= l-m %> more</a>
<% } %>
</div>
<% if (l) { %>
<ul>
<% if (l > m) deps = deps.slice(0, m)
deps.forEach(function(pkg, i) {
%>
<li>
<a class="pack-dep-name" target="_blank" href="/package/<%= pkg %>"><%= pkg %></a>
<span class="pack-dep-ver"><%= package.dependencies[pkg]%></span>
</li>
<% }) %>
</ul>
<% } else { %>
None
<% } %>
<div class="row">
<div class="pack-readme col-17">
<section id="readme" class="markdown-body">
<%- package.readme || 'No README was found.' %>
</section>
</div>
<div class="pack-maintainers cols-box-item">
<div class="cols-box-title">
<%
var maintainers = package.maintainers || [];
var l = maintainers.length
var m = 6
%>
Maintainers <%= l > 0 ? ' (' + l + ')' : '' %>
<% if (l > m) { %>
<a class="more-item" href="<%= package.registryUrl %>" target="_blank">+<%= l-m %> more</a>
<% } %>
</div>
<div class="maintainers">
<% if (l > m) maintainers = maintainers.slice(0, m) %>
<% for (var i = 0; i < maintainers.length; i += 2) { %>
<div class="row">
<div class="pack-details cols-box col-6 col-push-1">
<div class="pack-maintainers cols-box-item">
<div class="cols-box-title">
<%
var maintainers = package.maintainers || [];
var l = maintainers.length
%>
Maintainers <%= l > 0 ? ' (' + l + ')' : '' %>
</div>
<div class="maintainers">
<% for (var i = 0; i < maintainers.length; i ++) { %>
<div class="maintainer">
<a class="username" href="/~<%= maintainers[i].name %>">
<img src="<%= maintainers[i].gravatar %>" class="avatar">
<%= maintainers[i].name %>
</a>
</div>
<% if (maintainers[i + 1]) { %>
<div class="maintainer">
<a class="username" href="/~<%= maintainers[i + 1].name %>">
<img src="<%= maintainers[i + 1].gravatar %>" class="avatar">
<%= maintainers[i + 1].name %>
</a>
</div>
<% } %>
<% } %>
</div>
</div>
<div class="pack-downloads cols-box-item">
<div class="cols-box-title">
Downloads
</div>
<div class="downloads">
<div class="row">
Today
<span class="pack-download-num"><%= download.today %></span>
</div>
<div class="row">
This Week
<span class="pack-download-num"><%= download.thisweek %></span>
</div>
<div class="row">
This Month
<span class="pack-download-num"><%= download.thismonth %></span>
</div>
<div class="row">
Last Day
<span class="pack-download-num"><%= download.lastday %></span>
</div>
<div class="row">
Last Week
<span class="pack-download-num"><%= download.lastweek %></span>
</div>
<div class="row">
Last Month
<span class="pack-download-num"><%= download.lastmonth %></span>
</div>
</div>
</div>
<div class="pack-dep cols-box-item">
<div class="cols-box-title">
<%
var deps = Object.keys(package.dependencies || {})
var l = deps.length
%>
Dependencies<%= ' (' + l + ')' %>
</div>
<% if (l) { %>
<ul>
<%
deps.forEach(function(pkg, i) {
%>
<li>
<a class="pack-dep-name" target="_blank" href="/package/<%= pkg %>"><%= pkg %></a>
<span class="pack-dep-ver"><%= package.dependencies[pkg]%></span>
</li>
<% }) %>
</ul>
<% } else { %>
None
<% } %>
</div>
</div>
<div class="pack-dep cols-box-item">
<div class="cols-box-title">
<%
var deps = Object.keys(package.devDependencies || {})
var l = deps.length
%>
Dev Dependencies<%= ' (' + l + ')' %>
<div class="pack-downloads cols-box-item">
<div class="cols-box-title">
Downloads
</div>
<div class="downloads">
<div class="row">
Today
<span class="pack-download-num"><%= download.today %></span>
</div>
<div class="row">
This Week
<span class="pack-download-num"><%= download.thisweek %></span>
</div>
<div class="row">
This Month
<span class="pack-download-num"><%= download.thismonth %></span>
</div>
<div class="row">
Last Day
<span class="pack-download-num"><%= download.lastday %></span>
</div>
<div class="row">
Last Week
<span class="pack-download-num"><%= download.lastweek %></span>
</div>
<div class="row">
Last Month
<span class="pack-download-num"><%= download.lastmonth %></span>
</div>
</div>
<% if (l) { %>
<ul>
<%
deps.forEach(function(pkg, i) {
%>
<li>
<a class="pack-dep-name" target="_blank" href="/package/<%= pkg %>"><%= pkg %></a>
<span class="pack-dep-ver"><%= package.devDependencies[pkg]%></span>
</li>
<% }) %>
</ul>
<% } else { %>
None
<% } %>
</div>
</div>
</div>
<div class="pack-readme">
<div class="title">README</div>
<section id="readme" class="markdown-body">
<%- package.readme %>
</section>
</div>

View File

@@ -7,65 +7,69 @@
</h1>
<p class="description">This package has been unpublished.</p>
<ul class="nav nav-tabs">
<li class="active"><a href="#meta">package.json</a></li>
<!-- package.json? -->
<ul class="ant-menu ant-menu-horizontal ant-menu-root unstyled mb15">
<li class="ant-menu-item-selected ant-menu-item unstyled">
<span>package.json</span>
</li>
</ul>
<table class="metadata active">
<% if (package.unpublished.description) { %>
<tr>
<th>Description</th>
<td>
<%= package.unpublished.description %>
</td>
</tr>
<% } %>
<div class="ant-table">
<table class="metadata active">
<% if (package.unpublished.description) { %>
<tr>
<th>Description</th>
<td>
<%= package.unpublished.description %>
</td>
</tr>
<% } %>
<tr>
<th>Unpublished By</th>
<td>
<span class="user">
<a class="username" href="/~<%= package.unpublished.name %>">
<%= package.unpublished.name %>
</a>
</span>
</td>
</tr>
<tr>
<th>Unpublished By</th>
<td>
<span class="user">
<a class="username" href="/~<%= package.unpublished.name %>">
<%= package.unpublished.name %>
</a>
</span>
</td>
</tr>
<tr>
<th>Unpublished On</th>
<td>
<%= package.unpublished.time %>
</td>
</tr>
<tr>
<th>Unpublished On</th>
<td>
<%= package.unpublished.time %>
</td>
</tr>
<% if (package.unpublished.maintainers) { %>
<tr>
<th>Maintainers</th>
<td>
<% package.unpublished.maintainers.forEach(function (m) { %>
<span class="user">
<a class="username" href="/~<%= m.name %>">
<% if (m.gravatar) { %>
<img src="<%= m.gravatar %>" class="avatar">
<% } %>
<%= m.name %>
</a>
</span>
<% }) %>
</td>
</tr>
<% } %>
<% if (package.unpublished.maintainers) { %>
<tr>
<th>Maintainers</th>
<td>
<% package.unpublished.maintainers.forEach(function (m) { %>
<span class="user">
<a class="username" href="/~<%= m.name %>">
<% if (m.gravatar) { %>
<img src="<%= m.gravatar %>" class="avatar">
<% } %>
<%= m.name %>
</a>
</span>
<% }) %>
</td>
</tr>
<% } %>
<% if (package.unpublished.versions) { %>
<tr>
<th>Versions (<%= package.unpublished.versions.length %>)</th>
<td>
<%= package.unpublished.versions.reverse().slice(0, 20).join(', ') %> ...
</td>
</tr>
<% } %>
<% if (package.unpublished.versions) { %>
<tr>
<th>Versions (<%= package.unpublished.versions.length %>)</th>
<td>
<%= package.unpublished.versions.reverse().slice(0, 20).join(', ') %> ...
</td>
</tr>
<% } %>
</table>
</table>
</div>
</div>

View File

@@ -1,12 +1,5 @@
<style>
#profile .package {
padding: 10px;
font-size: 18px;
border-bottom: 1px solid #ddd;
}
</style>
<div id="profile">
<h1>
<h2>
Packages by
<% if (user.json.homepage) { %>
<span class="user">
@@ -20,49 +13,57 @@
<% } else { %>
<span style="color:#09f;"><%= user.name %></span>
<% } %>
<% if (user.json.fullname) { %>
<small>(<%= user.json.fullname %>)</small>
<% } %>
<% if (user.email) { %>
<small>(<a href="mailto:<%= user.email %>"><%= user.email %></a>)</small>
<% } %>
<% if (user.email) { %>
<small><<a href="mailto:<%= user.email %>"><%= user.email %></a>></small>
<% } %>
<% if (user.json.fullname) { %>
<small>(<%= user.json.fullname %>)</small>
<% } %>
<small>(<a href="/sync/user:<%= user.name %>" target="_blank">SYNC</a> profile)</small>
</h1>
<table class="downloads">
<tbody>
<tr>
<th>Name</th>
<th>IM</th>
<th>Last modified</th>
<th>Is admin</th>
<th>Publish scopes</th>
</tr>
<tr>
<td>@<%= user.json.fullname || user.name %></td>
<td>
<% if (user.json.im) { %>
<a href="<%= user.json.im %>" target="_blank"><span class="glyphicon glyphicon-comment"></span></a>
<% } %>
</td>
<td><%- lastModified %></td>
<td><%- isAdmin %></td>
<td>
<%- scopes.map(function (scope) {
return '<a href="/browse/keyword/' + scope + '" target="_blank">' + scope + '</a>';
}).join(' , ') %>
</td>
</tr>
</tbody>
</table>
<small>[<a href="/sync/user:<%= user.name %>" target="_blank">SYNC</a> profile]</small>
</h2>
<div class="ant-table">
<table class="downloads">
<tbody>
<tr>
<th>Name</th>
<th>IM</th>
<th>Last modified</th>
<th>Is admin</th>
<th>Publish scopes</th>
</tr>
<tr>
<td>@<%= user.json.fullname || user.name %></td>
<td>
<% if (user.json.im) { %>
<a href="<%= user.json.im %>" target="_blank"><span class="glyphicon glyphicon-comment"></span></a>
<% } %>
</td>
<td><%- lastModified %></td>
<td><%- isAdmin %></td>
<td>
<%- scopes.map(function (scope) {
return '<a href="/browse/keyword/' + scope + '" target="_blank">' + scope + '</a>';
}).join(' , ') %>
</td>
</tr>
</tbody>
</table>
</div>
<hr />
<% if (!packages.length) { %>
<div class="alert alert-warning">Can not found any package by <%= user.name %>.</div>
<% } %>
<% for (var i = 0; i < packages.length; i++) { %>
<div class="package">
<a href="/package/<%= packages[i].name %>" class="package-name"><%= packages[i].name %></a>
<span class="package-description"><%= packages[i].description %></span>
</div>
<% for (var i = 0; i < packages.length; i++) {
var package = packages[i];
%>
<ul>
<li class="package">
<a href="/package/<%= packages[i].name %>" class="package-name"><%= package.name %></a>
<span class="package-description">(latest: <%= package.version %>) <%= package.description %></span>
</li>
</ul>
<% } %>
</div>

View File

@@ -1,42 +1,30 @@
<style>
#search .package {
padding: 10px;
font-size: 18px;
border-bottom: 1px solid #ddd;
}
#search .alert a {
font-size: 20px;
}
#search .package.match {
font-size: 25px;
font-weight: bolder;
}
</style>
<div id="search">
<div id="search" class="row">
<% if (!packages.length) { %>
<div class="alert alert-warning">
<div class="ant-alert ant-alert-warn">
Can not found package match <%= keyword %>. You can
<a href="/sync/<%= keyword %>" target="_blank">SYNC</a> from official npm registry or
<a href="https://npmjs.org/search?q=<%= keyword %>" target="_blank">SEARCH</a> in official npm website.
</div>
<% } else if (!match) { %>
<div class="alert alert-info">
<div class="ant-alert ant-alert-info">
Can not found package <%= keyword %>. You can
<a href="/sync/<%= keyword %>" target="_blank">SYNC</a> from official npm registry or
<a href="https://npmjs.org/search?q=<%= keyword %>" target="_blank">SEARCH</a> in official npm website.
</div>
<% } %>
<div class="col-12">
<% if (packages.length) { %>
<h1>
<h2>
Packages match "<span style="color: #09f;"><%= keyword %></span>"
</h1>
<hr />
</h2>
<% if (match) { %>
<div class="package match">
<a href="/package/<%= match.name %>" class="package-name"><%= match.name %></a>
<span class="package-description"><%= match.description %></span>
</div>
<ul>
<li class="package match">
<a href="/package/<%= match.name %>" class="package-name"><%= match.name %></a>
<span class="package-description"><%= match.description %></span>
</li>
</ul>
<% } %>
<% for (var i = 0; i < packages.length; i++) {
var item = packages[i];
@@ -44,25 +32,30 @@
continue;
}
%>
<div class="package">
<ul>
<li class="package">
<a href="/package/<%= item.name %>" class="package-name"><%= item.name %></a>
<span class="package-description"><%= item.description %></span>
</div>
</li>
</ul>
<% } %>
<% } %>
</div>
<div class="col-12">
<% if (keywords.length) { %>
<h1>
<h2>
Keywords match "<span style="color: #09f;"><%= keyword %></span>"
</h1>
<hr />
</h2>
<% for (var i = 0; i < keywords.length; i++) {
var item = keywords[i];
%>
<div class="package <%= item.name === keyword ? 'match' : '' %>">
<ul>
<li class="package <%= item.name === keyword ? 'match' : '' %>">
<a href="/package/<%= item.name %>" class="package-name"><%= item.name %></a>
<span class="package-description"><%= item.description %></span>
</div>
</li>
</ul>
<% } %>
<% } %>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<div id="sync">
<h1>Sync <%= type %> <span style="color:#09f;"><%= name %></span></h1>
<h2>Sync <%= type %> <span style="color:#09f;"><%= name %></span></h2>
<div id="sync-notify">
<div class="alert alert-success">Sync started, please wait patiently.</div>
<div class="ant-alert ant-alert-success">Sync started, please wait patiently.</div>
</div>
<h2>Log</h2>
<pre style="min-height: 400px;" id="sync-log"></pre>
@@ -28,7 +28,7 @@
dataType: 'json',
success: handleSyncSucess,
error: function (err) {
var alert = $('<div class="alert alert-error"></div>');
var alert = $('<div class="ant-alert ant-alert-error"></div>');
var message = 'Sync request error. ';
if (err.status === 404) {
message += name + ' not exist in official registry.';
@@ -48,7 +48,7 @@
location.hash = '#logid=' + data.logId;
return;
}
$notify.html('<div class="alert alert-error">Sync request error.</div>');
$notify.html('<div class="ant-alert ant-alert-error">Sync request error.</div>');
}
var offset = 0;

View File

@@ -1,6 +1,4 @@
/**!
* cnpmjs.org - worker.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*