Commit 4e62325f by lxyang

feat:代码覆盖率查看服务上传0.0.1版本

parents
lib/
node_modules/
*tgz
.history
dist
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
!fixtures/node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
src/
node_modules/
.history/
\ No newline at end of file
language: node_js
node_js:
- "0.10"
- "0.12"
branches:
except:
- gh-pages
before_install:
- phantomjs -v
- if [[ `node --version` == *v0.8* ]]; then npm install -g npm; fi
Copyright (c) 2016, Istanbul Code Coverage
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of babel-plugin-istanbul nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
istanbul-middleware-ry
===================
## 新增使用方法
需先全局安装pm2: npm install pm2@5.2.0 -g --save-dev
代码查看npm包安装:
启动查看服务命令(本地调试) coverage -n || coverage --nodemon(本地调试方案建议使用此方案退出ctrl + c或control + c)
启动查看服务命令coverage -s || coverage --serve
关闭查看服务命令coverage -c || coverage --close
查看命令使用方法coverage -h || coverage --help
可传入参数
是否收集上报数据进行展示如为false则其他的不触发 IS_PITCHING_PILE (string):true/false 默认 true
自动启动服务时的端口号 FRACTION_OF_COVERAGE_PORT(string): 默认10000
项目中添加js文件以vue为例:
src目录下添加xxxx.js,在main.js下引用import './xxxx.js'
.gitignore下添加忽略文件/src/xxxx.js,上传提交时记得注释main.js下的import './xxxx.js'
请求地址为启动覆盖服务的地址如服务端口号为10001: 'http://localhost:10001/coverage/client',
上报覆盖率调用接口写法:
点击上报:
```javascript
import axios from 'axios'
let istanbulSync = () => {
if (window.__coverage__) {
console.log(window.__coverage__, 'window.__coverage__')
axios({
method: 'post',
url: 'http://localhost:10000/coverage/client',
contentType: 'application/json',
data: window.__coverage__
})
}
}
window.onload = () => {
istanbulSync()
}
// 点击上报
document.body.addEventListener('click', istanbulSync)
```
轮询上报:
```javascript
// 循环上报
setInterval(function () {
istanbulSync()
}, REGULAR_REPORT_TO_DATA)
```
添加按钮主动上报:
```javascript
// 按钮主动上报
var element = document.createElement("input");
element.setAttribute("type", "button");
element.setAttribute("value", "点击上报");
element.setAttribute("style", "background: rgb(45, 140, 240); border: 0; position: fixed; color: #fff; bottom: 50px; right: 50px; width: 60px; height: 60px; border-radius: 50%; font-size: 12px; text-align: center; padding: 0; z-index: 9999")
element.setAttribute("onclick", "istanbulSync()");
document.body.appendChild(element);
```
启动命令事例:coverage -n FRACTION_OF_COVERAGE_PORT=10001 || coverage -s FRACTION_OF_COVERAGE_PORT=10001
Connect middleware for getting code coverage numbers in functional tests for nodejs apps using istanbul.
Run the sample app at `test/app` to get a feel for how this works.
All of this is experimental and is known to work for narrow use-cases such as an express3 app. YMMV.
Server-side code coverage
-------------------------
This involves:
* hooking `require()` in the server process
* exposing coverage information on special endpoints (e.g. `/coverage`)
* allowing reset of coverage numbers to ensure clean slate
* allowing users to download coverage reports after tests have run
```javascript
var im = require('istanbul-middleware'),
isCoverageEnabled = (process.env.COVERAGE == "true"); // or a mechanism of your choice
//before your code is require()-ed, hook the loader for coverage
if (isCoverageEnabled) {
console.log('Hook loader for coverage - ensure this is not production!');
im.hookLoader(__dirname);
// cover all files except under node_modules
// see API for other options
}
// now require the rest of your code
var stuff = require('./lib'),
express = require('express'),
app = express();
// set up basic middleware
// ...
// add the coverage handler
if (isCoverageEnabled) {
//enable coverage endpoints under /coverage
app.use('/coverage', im.createHandler());
}
//add your router and other endpoints
//...
app.listen(80);
```
The above snippet adds the following endpoints to your app under `/coverage`
<table>
<thead>
<tr>
<th>URL</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GET&nbsp;/</code></td>
<td>
Dynamic code coverage HTML report showing live coverage.
Clickable with drill-downs just like the static version
</td>
</tr>
<tr>
<td><code>POST&nbsp;/reset</code></td>
<td>Reset coverage to baseline numbers</td>
</tr>
<tr>
<td><code>GET&nbsp;/download</code></td>
<td>Download a zip file with coverage JSON, HTML and lcov reports</td>
</tr>
<tr>
<td><code>POST&nbsp;/client</code></td>
<td>
Allows you to post a coverage object for client-side code coverage from the browser.
Must be a JSON object with a <code>Content-type: application/json</code> header.
This object is aggregated with the stats already present on the server
</td>
</tr>
</tbody>
</table>
Client-side coverage
--------------------
This involves:
* Delivering instrumented code instead of the original Javascript to the browser
* Having your tests post the coverage information to the server (see `POST /client` endpoint above)
using the `window.__coverage__` object. You need to figure out how to do this using your favorite test runner.
* Aggregating the client and server coverage numbers. This is automatically done for you by the server-side middleware.
The API for this is _highly_ experimental given the number of moving parts. But, it roughly looks like this:
```javascript
var path = require('path'),
im = require('istanbul-middleware');
// do the server side stuff as described above
// add a client handler at the appropriate place
// (before your static handler, for example)
// all JS files under here will be sent instrumented to the browser
// see API below for additional options (e.g. ignoring framework code)
app.use(im.createClientHandler(__dirname));
// however, it will only reliably work for simple cases
// such as absolute URLs to the JS.
// you still need to post the coverage numbers to the
//server from your browser tests
```
You can write your own custom middleware and completely ignore this library's client handler. As in:
```javascript
app.use(function (req, res, next) {
if (isJSRequiringCoverage(req)) {
var file = getFilePath(req), //translate request to file name to be delivered
code = readTheCodeFromFile(file), //use async for a real implementation
instrumenter = im.getInstrumenter();
res.send(instrumenter.instrumentSync(code, file));
//exception handling omitted for brevity
} else {
next();
}
});
```
API
---
### `istanbulMiddleware.hookLoader(rootOrMatcher, instrumenterOpts)`
hooks `require` for coverage using istanbul.
`rootOrMatcher` can be:
* a string in which case it is assumed to be the root under which you want to cover all files except those under `node_modules`
* a function in which case it is assumed to be a match function with signature `fn(filePath)`
that should return `true` when the supplied `filePath` should be covered and `false` otherwise
`instrumenterOpts` is an optional object with additional options to be passed to the istanbul instrumenter. See the
API docs in istanbul for more information. In addition, options can also contain the `postLoadHook` key that is
passed to `istanbul.hook.hookRequire()`
### `istanbulMiddleware.createHandler(opts)`
returns connect middleware that exposes additional endpoints for coverage. Endpoints exposed are documented in the summary.
`opts` is optional and currently only supports one flag.
* `resetOnGet` - boolean to allow resets of coverage to baseline numbers using `GET` in addition to `POST`
### `istanbulMiddleware.createClientHandler(root, opts)`
returns connect middleware similar to the `static` middleware to return instrumented JS to the client.
The default behavior of the middleware is to intercept all `GET` requests to Javascript files and return the
instrumented version by deriving the path of the file from the URL, instrumenting the code and sending the
instrumented version in the response.
`opts` is an optional object with the following supported keys:
* `matcher` - a function of the form `fn(request)` that returns true if instrumentation
is required and false otherwise.
* `pathTransformer` - a function of the form `fn(request)` that inspects the request URL
and returns the physical path to the JS file on the filesystem.
An example of a matcher function could be:
```javascript
function ignoreFrameworks(req) {
var parsed = require('url').parse(req.url);
return parsed.pathname && parsed.pathname.match(/\.js$/) && !parsed.pathname.match(/jquery/);
}
```
For all other cases where the client handler provided by this library is not good enough, just write your own
middleware as documented in the summary.
### `istanbulMiddleware.getInstrumenter()`
returns the instrumenter object that is created as a side-effect of the `hookLoader` call. Useful for custom
client-side instrumentation to ensure that the instrumentation is done with the same options for all code.
Third-party libraries
---------------------
The following third-party libraries are used by this module:
* express: https://github.com/visionmedia/express - to implement the middleware
* archiver: https://github.com/ctalkington/node-archiver - for zip functionality
'use strict'
module.exports = {
plugins: ['@babel/plugin-transform-modules-commonjs'],
env: {
test: {
plugins: ['./lib']
}
}
}
#!/usr/bin/env node
var program = require('commander')
var path = require('path')
const nopt = require('nopt')
const config = nopt({ coverage: Boolean })
const configArray = ['s', 'serve', 'n', 'nodemon'].filter(item => config[item])
const coverageRequired = configArray.length >= 1
var istanbulMiddleware = require(path.resolve(__dirname, '..', 'lib/autoIstanbulLib/autoIstanbulHandlers.js'))
var { FRACTION_OF_COVERAGE_PORT_DATA } = istanbulMiddleware.globalVariable()
var exec = require('child_process').exec
var stopPm2 = `pm2 stop all`
const port = FRACTION_OF_COVERAGE_PORT_DATA
program
.option('-h --help', 'help information', helpInformation)
.option('-s --serve', 'start the service', serveInformation)
.option('-n --nodemon', 'close the service', nodemonInformation)
.option('-c --close', 'close the service', closeInformation)
.parse(process.argv);
function helpInformation() {
console.log('options:');
console.log('');
console.log('-s --serve start the service');
console.log('-n --nodemon start the service');
console.log('-c --close close the service');
console.log('');
};
function serveInformation() {
runSever()
}
function nodemonInformation() {
runSever()
}
function closeInformation() {
exec(stopPm2, (err, stdout, stderr) => {
if (err){
console.log(err);
console.warn(new Date(),' 代码覆盖率服务残留停止失败');
} else {
console.log(stdout);
console.warn(new Date(),' 代码覆盖率服务残留停止成功');
}
})
}
function runSever() {
if (coverageRequired) {
console.log('Turning on coverage; ensure this is not production')
istanbulMiddleware.hookLoader(__dirname, { verbose: true })
}
console.log('Starting server at: http://localhost:' + port)
if (!coverageRequired) {
console.log('Coverage NOT turned on, run with --coverage to turn it on')
}
require(path.resolve(__dirname, '..', 'lib/lstanbulabServer/index.js')).serve(port, coverageRequired)
}
\ No newline at end of file
#!/usr/bin/env node
"use strict";
var program = require('commander');
var path = require('path');
const nopt = require('nopt');
const config = nopt({
coverage: Boolean
});
const configArray = ['s', 'serve', 'n', 'nodemon'].filter(item => config[item]);
const coverageRequired = configArray.length >= 1;
var istanbulMiddleware = require(path.resolve(__dirname, '..', 'lib/autoIstanbulLib/autoIstanbulHandlers.js'));
var {
FRACTION_OF_COVERAGE_PORT_DATA
} = istanbulMiddleware.globalVariable();
var exec = require('child_process').exec;
var stopPm2 = `pm2 stop all`;
const port = FRACTION_OF_COVERAGE_PORT_DATA;
program.option('-h --help', 'help information', helpInformation).option('-s --serve', 'start the service', serveInformation).option('-n --nodemon', 'close the service', nodemonInformation).option('-c --close', 'close the service', closeInformation).parse(process.argv);
function helpInformation() {
console.log('options:');
console.log('');
console.log('-s --serve start the service');
console.log('-n --nodemon start the service');
console.log('-c --close close the service');
console.log('');
}
;
function serveInformation() {
runSever();
}
function nodemonInformation() {
runSever();
}
function closeInformation() {
exec(stopPm2, (err, stdout, stderr) => {
if (err) {
console.log(err);
console.warn(new Date(), ' 代码覆盖率服务残留停止失败');
} else {
console.log(stdout);
console.warn(new Date(), ' 代码覆盖率服务残留停止成功');
}
});
}
function runSever() {
if (coverageRequired) {
console.log('Turning on coverage; ensure this is not production');
istanbulMiddleware.hookLoader(__dirname, {
verbose: true
});
}
console.log('Starting server at: http://localhost:' + port);
if (!coverageRequired) {
console.log('Coverage NOT turned on, run with --coverage to turn it on');
}
require(path.resolve(__dirname, '..', 'lib/lstanbulabServer/index.js')).serve(port, coverageRequired);
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "istanbul-middleware-ry",
"description": "Connect middleware for Istanbul to handle server-side as well as browser coverage use-cases for node apps",
"version": "0.0.1",
"main": "lib/index.js",
"files": [
"lib"
],
"bin": {
"name": "istanbul-middleware-ry",
"coverage": "binLib/coverage.js"
},
"repository": {
"type": "git",
"url": "git@github.com:gotwarlost/istanbul-middleware.git"
},
"scripts": {
"release": "babel src --out-dir lib",
"release:bin": "babel bin --out-dir binLib",
"pretest": "jshint --config ./node_modules/yui-lint/jshint.json lib/*js",
"build:watch": "onchange ./src -- npm run release",
"nodemon": "nodemon ./lib/index.js --coverage # start the app with coverage --watch",
"run:pm2": "pm2 start ./lib/index.js --watch -f",
"stop:pm2": "pm2 stop ./lib/index.js"
},
"contributors": [
"@arboleya",
"@harking",
"@mikaturunen",
"@jelmertanen",
"@tkmunzwa",
"@mcollina",
"@lpinca"
],
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/parser": "^7.14.7",
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.2",
"archiver": "0.14.x",
"babel-generator": "^6.18.0",
"babel-template": "^6.26.0",
"babel-traverse": "^6.18.0",
"babel-types": "^6.18.0",
"body-parser": "~1.12.3",
"child_process": "^1.0.2",
"commander": "^9.4.1",
"concurrently": "^7.3.0",
"cross-env": "^7.0.3",
"express": "^4.18.1",
"fs": "^0.0.1-security",
"hbs": "^4.2.0",
"nodemon": "^2.0.19",
"nopt": "^6.0.0",
"onchange": "^7.1.0",
"pm2": "^5.2.0"
},
"devDependencies": {
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
"@babel/plugin-transform-modules-commonjs": "^7.7.5",
"@babel/preset-env": "^7.19.3",
"@babel/register": "^7.7.4",
"async": "*",
"axios": "^1.1.2",
"babel-cli": "^6.3.17",
"body-parser": "^1.4.3",
"cors": "^2.8.5",
"jshint": "*",
"mkdirp": "*",
"pm2": "^5.2.0",
"rimraf": "*",
"ry-istanbul-web": "^0.0.2",
"yui-lint": "*"
},
"engines": {
"node": ">=0.6.x"
},
"license": "BSD"
}
/*
Copyright (c) 2013, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const path = require('path')
const fs = require('fs')
const core = require(path.resolve(__dirname, '.', 'autoIstanbulCore'))
const istanbul = require('ry-istanbul-web')
const bodyParser = require('body-parser')
const ASSETS_DIR = istanbul.assetsDir
const existsSync = fs.existsSync || path.existsSync
const url = require('url')
const express = require('express')
const JS_RE = /\.js$/
const getPitchingPiles = core.getPitchingPile()
/**
* Set default max limit to 100mb for incoming JSON and urlencoded
* @type {String}
*/
var fileSizeMaximum = '1024mb'
var isExtended = true
function createHandler(opts, isAll) {
/*jslint nomen: true */
opts = opts || {}
var app = express()
// 设置跨域
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Content-Type')
next()
})
// using separete options objects to maintain readability as the objects are getting more complex
var urlOptions = { extended: isExtended, limit: fileSizeMaximum }
var jsonOptions = { limit: fileSizeMaximum }
//send static file for /asset/asset-name
app.use('/asset', express.static(ASSETS_DIR))
app.use('/asset', express.static(path.join(ASSETS_DIR, 'vendor')))
app.use(bodyParser.urlencoded(urlOptions))
app.use(bodyParser.json(jsonOptions))
app.use(express.static(path.resolve(__dirname, '..', 'istanbulGather')));
//show main page for coverage report for /
app.get('/', function (req, res) {
var origUrl = url.parse(req.originalUrl).pathname,
origLength = origUrl.length
if (origUrl.charAt(origLength - 1) !== '/') {
origUrl += '/'
}
res.type('css')
core.render(null, res, origUrl)
})
//show page for specific file/ dir for /show?file=/path/to/file
app.get('/show', function (req, res) {
var origUrl = url.parse(req.originalUrl).pathname,
u = url.parse(req.url).pathname,
pos = origUrl.indexOf(u),
file = req.query.p
if (pos >= 0) {
origUrl = origUrl.substring(0, pos)
}
if (!file) {
res.setHeader('Content-type', 'text/plain')
return res.end('[p] parameter must be specified')
}
res.type('css')
core.render(file, res, origUrl)
})
//reset coverage to baseline on POST /reset
app.post('/reset', function (req, res) {
core.restoreBaseline()
res.json({ ok: true })
})
//opt-in to allow resets on GET as well (useful for easy browser-based demos :)
if (opts.resetOnGet) {
app.get('/reset', function (req, res) {
core.restoreBaseline()
res.json({ ok: true })
})
}
//return global coverage object on /object as JSON
app.get('/object', function (req, res) {
getPitchingPiles ? res.json(core.getCoverageObject() || {}) : {}
})
//merge client coverage posted from browser
app.post('/client', function (req, res) {
var body = req.body
// let parse = JSON.parse(req.body.coverage)
if (!(body && typeof body === 'object') && !getPitchingPiles) {
//probably needs to be more robust
return res.send(400, 'Please post an object with content-type: application/json and The global variable IS PITCHING PILE DATA IS not true')
}
if (!(body && typeof body === 'object')) {
//probably needs to be more robust
return res.send(400, 'Please post an object with content-type: application/json')
}
if (!getPitchingPiles) {
return res.send(400, 'The global variable IS PITCHING PILE DATA IS not true')
}
core.mergeClientCoverage(body)
res.json({
ok: true
})
})
return app
}
function defaultClientMatcher(req) {
var parsed = url.parse(req.url)
return parsed.pathname && parsed.pathname.match(JS_RE)
}
function defaultPathTransformer(root) {
return function (req) {
var parsed = url.parse(req.url),
pathName = parsed.pathname
if (pathName && pathName.charAt(0) === '/') {
pathName = pathName.substring(1)
}
return path.resolve(root, pathName)
}
}
function clientHandler(matcher, pathTransformer, opts) {
var verbose = opts.verbose
return function (req, res, next) {
if (!matcher(req)) {
return next()
}
var fullPath = pathTransformer(req)
if (!fullPath) {
return next()
}
if (!core.getInstrumenter()) {
console.error(
'No instrumenter set up, please call createHandler() before you use the client middleware'
)
return next()
}
if (!existsSync(fullPath)) {
console.warn('Could not find file [' + fullPath + '], ignoring')
return next()
}
fs.readFile(fullPath, 'utf8', function (err, contents) {
var instrumented
if (err) {
console.warn('Error reading file: ' + fullPath)
return next()
}
try {
instrumented = core.getInstrumenter().instrumentSync(contents, fullPath)
if (verbose) {
console.log('Sending instrumented code for: ' + fullPath + ', url:' + req.url)
}
res.setHeader('Content-type', 'application/javascript')
return res.send(instrumented)
} catch (ex) {
console.warn('Error instrumenting file:' + fullPath)
return next()
}
})
}
}
function createClientHandler(root, opts) {
opts = opts || {}
var app = express(),
matcher = opts.matcher || defaultClientMatcher,
pathTransformer = opts.pathTransformer || defaultPathTransformer(root)
app.get('*', clientHandler(matcher, pathTransformer, opts))
return app
}
module.exports = {
createClientHandler: createClientHandler,
createHandler: createHandler,
hookLoader: core.hookLoader,
globalVariable: core.globalVariable,
getPitchingPile: core.getPitchingPile
}
// var autoIstanbulCore = require(path.resolve(__dirname, '..', 'autoIstanbulLib/autoIstanbulCore.js'))
// console.log(process.env)
// var { FRACTION_OF_COVERAGE_PORT_DATA, IS_PITCHING_PILE_DATA, REGULAR_REPORT_TO_DATA, IS_REGULAR_REPORT_TO_DATA, IS_MANUAL_REPORTING_DATA } = autoIstanbulCore.globalVariable()
let IS_PITCHING_PILE_DATA = true // 是否收集上报数据进行展示如为false则其他的不触发
let FRACTION_OF_COVERAGE_PORT_DATA = 10000 // 端口号
let REGULAR_REPORT_TO_DATA = 5000 // 轮询上报触发时间
let IS_REGULAR_REPORT_TO_DATA = false // 是否轮询定时上报false的话就点击上报
let IS_MANUAL_REPORTING_DATA = false // 是否手动触发上报这个后期添加触发按钮
var axios = require('https://unpkg.com/axios/dist/axios.min.js')
let istanbulSync = () => {
if (window.__coverage__) {
axios({
method: 'post',
url: `http://localhost:${FRACTION_OF_COVERAGE_PORT_DATA}/coverage/client`,
contentType: 'application/json',
data: window.__coverage__
})
}
}
if ((IS_PITCHING_PILE_DATA === 'true' && IS_PITCHING_PILE_DATA !== 'false') || IS_PITCHING_PILE_DATA) {
window.onload = () => {
istanbulSync()
}
// 是否轮询上报false或'false'就是点击上报如果是true或'true'则相反
if ((IS_REGULAR_REPORT_TO_DATA === 'false' && IS_REGULAR_REPORT_TO_DATA !== 'true') || !IS_REGULAR_REPORT_TO_DATA) {
// 点击上报
document.body.addEventListener('click', istanbulSync)
} else {
// 循环上报
setInterval(function () {
istanbulSync()
}, REGULAR_REPORT_TO_DATA)
}
if ((IS_MANUAL_REPORTING_DATA === 'true' && IS_MANUAL_REPORTING_DATA !== 'false') || IS_MANUAL_REPORTING_DATA) {
// 按钮主动上报
var element = document.createElement("input");
element.setAttribute("type", "button");
element.setAttribute("value", "点击上报");
element.setAttribute("style", "background: rgb(45, 140, 240); border: 0; position: fixed; color: #fff; bottom: 50px; right: 50px; width: 60px; height: 60px; border-radius: 50%; font-size: 12px; text-align: center; padding: 0; z-index: 9999")
element.setAttribute("onclick", "istanbulSync()");
document.body.appendChild(element);
}
}
\ No newline at end of file
const path = require('path')
const express = require('express')
const url = require('url')
const publicDir = path.resolve(__dirname, '..', 'publicIstanbulab')
const coverage = require(path.resolve(__dirname, '..', 'autoIstanbulLib/autoIstanbulHandlers'))
const bodyParser = require('body-parser')
function matcher(req) {
var parsed = url.parse(req.url)
return parsed.pathname && parsed.pathname.match(/\.js$/) && !parsed.pathname.match(/jquery/)
}
function list(req, res, next) {
var parsed = url.parse(req.url, true),
authors = data.authors;
if (parsed.query.alive === '1' || !coverage.getPitchingPile) {
authors = authors.filter(function (a) { return !a.deceased; });
}
res.render('index', { authors: authors });
}
module.exports = {
serve: function (port, needCover) {
var app = express()
if (needCover) {
console.log('Turn on coverage reporting at /coverage')
app.use('/coverage', coverage.createHandler({ verbose: true, resetOnGet: true }, false))
app.use(coverage.createClientHandler(publicDir, { matcher: matcher }))
}
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
app.set('view engine', 'hbs');
app.engine('hbs', require('hbs').__express);
app.use(express['static'](publicDir))
app.get('/', list);
app.listen(port)
}
}
/*globals $, document */
$(function () {
$('.item').wrapInner(function () {
var link = $('<a/>');
link.attr('href', '/authors/' + $(this).attr('id'));
return link;
});
});
/*globals $ */
function showDeceased(flag) {
if (flag) {
$('#deceased').css('display', '');
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment