Deployed the page to Github Pages.

This commit is contained in:
Batuhan Berk Başoğlu 2024-11-03 21:30:09 -05:00
parent 1d79754e93
commit 2c89899458
Signed by: batuhan-basoglu
SSH key fingerprint: SHA256:kEsnuHX+qbwhxSAXPUQ4ox535wFHu/hIRaa53FzxRpo
62797 changed files with 6551425 additions and 15279 deletions

163
node_modules/istanbul-reports/lib/clover/index.js generated vendored Normal file
View file

@ -0,0 +1,163 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const { ReportBase } = require('istanbul-lib-report');
class CloverReport extends ReportBase {
constructor(opts) {
super();
this.cw = null;
this.xml = null;
this.file = opts.file || 'clover.xml';
}
onStart(root, context) {
this.cw = context.writer.writeFile(this.file);
this.xml = context.getXMLWriter(this.cw);
this.writeRootStats(root, context);
}
onEnd() {
this.xml.closeAll();
this.cw.close();
}
getTreeStats(node, context) {
const state = {
packages: 0,
files: 0,
classes: 0
};
const visitor = {
onSummary(node, state) {
const metrics = node.getCoverageSummary(true);
if (metrics) {
state.packages += 1;
}
},
onDetail(node, state) {
state.classes += 1;
state.files += 1;
}
};
node.visit(context.getVisitor(visitor), state);
return state;
}
writeRootStats(node, context) {
this.cw.println('<?xml version="1.0" encoding="UTF-8"?>');
this.xml.openTag('coverage', {
generated: Date.now().toString(),
clover: '3.2.0'
});
this.xml.openTag('project', {
timestamp: Date.now().toString(),
name: 'All files'
});
const metrics = node.getCoverageSummary();
this.xml.inlineTag('metrics', {
statements: metrics.lines.total,
coveredstatements: metrics.lines.covered,
conditionals: metrics.branches.total,
coveredconditionals: metrics.branches.covered,
methods: metrics.functions.total,
coveredmethods: metrics.functions.covered,
elements:
metrics.lines.total +
metrics.branches.total +
metrics.functions.total,
coveredelements:
metrics.lines.covered +
metrics.branches.covered +
metrics.functions.covered,
complexity: 0,
loc: metrics.lines.total,
ncloc: metrics.lines.total, // what? copied as-is from old report
...this.getTreeStats(node, context)
});
}
writeMetrics(metrics) {
this.xml.inlineTag('metrics', {
statements: metrics.lines.total,
coveredstatements: metrics.lines.covered,
conditionals: metrics.branches.total,
coveredconditionals: metrics.branches.covered,
methods: metrics.functions.total,
coveredmethods: metrics.functions.covered
});
}
onSummary(node) {
if (node.isRoot()) {
return;
}
const metrics = node.getCoverageSummary(true);
if (!metrics) {
return;
}
this.xml.openTag('package', {
name: asJavaPackage(node)
});
this.writeMetrics(metrics);
}
onSummaryEnd(node) {
if (node.isRoot()) {
return;
}
this.xml.closeTag(this.xml.stack[this.xml.stack.length - 1]);
}
onDetail(node) {
const fileCoverage = node.getFileCoverage();
const metrics = node.getCoverageSummary();
const branchByLine = fileCoverage.getBranchCoverageByLine();
this.xml.openTag('file', {
name: asClassName(node),
path: fileCoverage.path
});
this.writeMetrics(metrics);
const lines = fileCoverage.getLineCoverage();
Object.entries(lines).forEach(([k, count]) => {
const attrs = {
num: k,
count,
type: 'stmt'
};
const branchDetail = branchByLine[k];
if (branchDetail) {
attrs.type = 'cond';
attrs.truecount = branchDetail.covered;
attrs.falsecount = branchDetail.total - branchDetail.covered;
}
this.xml.inlineTag('line', attrs);
});
this.xml.closeTag('file');
}
}
function asJavaPackage(node) {
return node
.getRelativeName()
.replace(/\//g, '.')
.replace(/\\/g, '.')
.replace(/\.$/, '');
}
function asClassName(node) {
return node.getRelativeName().replace(/.*[\\/]/, '');
}
module.exports = CloverReport;

151
node_modules/istanbul-reports/lib/cobertura/index.js generated vendored Normal file
View file

@ -0,0 +1,151 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const path = require('path');
const { escape } = require('html-escaper');
const { ReportBase } = require('istanbul-lib-report');
class CoberturaReport extends ReportBase {
constructor(opts) {
super();
opts = opts || {};
this.cw = null;
this.xml = null;
this.timestamp = opts.timestamp || Date.now().toString();
this.projectRoot = opts.projectRoot || process.cwd();
this.file = opts.file || 'cobertura-coverage.xml';
}
onStart(root, context) {
this.cw = context.writer.writeFile(this.file);
this.xml = context.getXMLWriter(this.cw);
this.writeRootStats(root);
}
onEnd() {
this.xml.closeAll();
this.cw.close();
}
writeRootStats(node) {
const metrics = node.getCoverageSummary();
this.cw.println('<?xml version="1.0" ?>');
this.cw.println(
'<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">'
);
this.xml.openTag('coverage', {
'lines-valid': metrics.lines.total,
'lines-covered': metrics.lines.covered,
'line-rate': metrics.lines.pct / 100.0,
'branches-valid': metrics.branches.total,
'branches-covered': metrics.branches.covered,
'branch-rate': metrics.branches.pct / 100.0,
timestamp: this.timestamp,
complexity: '0',
version: '0.1'
});
this.xml.openTag('sources');
this.xml.inlineTag('source', null, this.projectRoot);
this.xml.closeTag('sources');
this.xml.openTag('packages');
}
onSummary(node) {
const metrics = node.getCoverageSummary(true);
if (!metrics) {
return;
}
this.xml.openTag('package', {
name: node.isRoot() ? 'main' : escape(asJavaPackage(node)),
'line-rate': metrics.lines.pct / 100.0,
'branch-rate': metrics.branches.pct / 100.0
});
this.xml.openTag('classes');
}
onSummaryEnd(node) {
const metrics = node.getCoverageSummary(true);
if (!metrics) {
return;
}
this.xml.closeTag('classes');
this.xml.closeTag('package');
}
onDetail(node) {
const fileCoverage = node.getFileCoverage();
const metrics = node.getCoverageSummary();
const branchByLine = fileCoverage.getBranchCoverageByLine();
this.xml.openTag('class', {
name: escape(asClassName(node)),
filename: path.relative(this.projectRoot, fileCoverage.path),
'line-rate': metrics.lines.pct / 100.0,
'branch-rate': metrics.branches.pct / 100.0
});
this.xml.openTag('methods');
const fnMap = fileCoverage.fnMap;
Object.entries(fnMap).forEach(([k, { name, decl }]) => {
const hits = fileCoverage.f[k];
this.xml.openTag('method', {
name: escape(name),
hits,
signature: '()V' //fake out a no-args void return
});
this.xml.openTag('lines');
//Add the function definition line and hits so that jenkins cobertura plugin records method hits
this.xml.inlineTag('line', {
number: decl.start.line,
hits
});
this.xml.closeTag('lines');
this.xml.closeTag('method');
});
this.xml.closeTag('methods');
this.xml.openTag('lines');
const lines = fileCoverage.getLineCoverage();
Object.entries(lines).forEach(([k, hits]) => {
const attrs = {
number: k,
hits,
branch: 'false'
};
const branchDetail = branchByLine[k];
if (branchDetail) {
attrs.branch = true;
attrs['condition-coverage'] =
branchDetail.coverage +
'% (' +
branchDetail.covered +
'/' +
branchDetail.total +
')';
}
this.xml.inlineTag('line', attrs);
});
this.xml.closeTag('lines');
this.xml.closeTag('class');
}
}
function asJavaPackage(node) {
return node
.getRelativeName()
.replace(/\//g, '.')
.replace(/\\/g, '.')
.replace(/\.$/, '');
}
function asClassName(node) {
return node.getRelativeName().replace(/.*[\\/]/, '');
}
module.exports = CoberturaReport;

3
node_modules/istanbul-reports/lib/html-spa/.babelrc generated vendored Normal file
View file

@ -0,0 +1,3 @@
{
"presets": [["@babel/preset-env", { "modules": "commonjs" }], "@babel/preset-react"]
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

View file

@ -0,0 +1,298 @@
/* Base */
body,
html {
margin: 0;
padding: 0;
height: 100%;
}
body {
color: #333;
background-color: #fcfcfc;
font: 14px/14px -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
Roboto, 'Helvetica Neue', Arial, sans-serif;
}
button {
margin: 0;
border: none;
font: inherit;
color: inherit;
}
button:focus {
outline: none;
}
*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* Typography */
h1 {
font-size: 20px;
line-height: 20px;
margin: 0;
}
a {
color: #0074d9;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.small {
font-size: 12px;
}
.strong {
font-weight: bold;
}
.center {
text-align: center;
}
.quiet {
opacity: 0.7;
}
/* Colors */
.low {
background: #fce1e5;
}
.low--dark {
background: #c21f39;
}
.medium {
background: #fff4c2;
}
.medium--dark {
background: #f9cd0b;
}
.high {
background: rgb(230, 245, 208);
}
.high--dark {
background: rgb(77, 146, 33);
}
/* App */
.app {
height: 100%;
}
/* Layout */
.layout {
display: flex;
flex-direction: column;
min-height: 100%;
padding: 20px;
}
.layout__section {
flex-grow: 0;
}
.layout__section--fill {
flex-grow: 1;
}
.layout__section + .layout__section {
margin-top: 20px;
}
@media only screen and (max-width: 640px) {
.col3 {
width: 100%;
max-width: 100%;
}
.hide-mobile {
display: none !important;
}
}
/* Toolbar */
.toolbar {
display: flex;
flex-wrap: wrap;
}
.toolbar__item {
margin-right: 40px;
margin-bottom: 10px;
}
/* Toggle */
.toggle {
display: inline-flex;
align-items: center;
}
.toggle__label {
margin-right: 0.5em;
}
.toggle__options {
display: inline-block;
border: 1px solid #0074d9;
border-radius: 4px;
color: #0074d9;
overflow: hidden;
white-space: nowrap;
}
.toggle__option {
padding: 4px 8px;
background: #fcfcfc;
}
.toggle__option + .toggle__option {
border-left: 1px solid #0074d9;
}
.toggle__option.is-toggled {
color: #fff;
background: #0074d9;
border-left-color: #fcfcfc;
}
/* Expand */
.expandbutton {
display: inline-block;
width: 1em;
margin-right: 0.25em;
padding: 0;
background-color: transparent;
font-weight: bold;
}
/* Fraction */
.fraction {
font-size: 12px;
color: #666;
padding: 2px 4px;
border-radius: 4px;
}
/* Coverage */
.coverage-summary {
border-collapse: collapse;
}
.coverage-summary tbody tr {
border-bottom: 1px solid #fff;
}
.coverage-summary td,
.coverage-summary th {
padding: 5px;
}
.coverage-summary th {
text-align: center;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs {
text-align: right;
}
.coverage-summary th.file {
min-width: 300px;
text-align: left;
}
.coverage-summary td.file {
white-space: nowrap;
}
.coverage-summary td.pct {
font-weight: 400;
}
.coverage-summary td.abs {
color: #666;
font-size: 12px;
}
.coverage-summary td.empty {
opacity: 0.5;
}
.coverage-summary .headercell {
border-top: 1px solid #eee;
text-align: right;
font-size: 12px;
color: #666;
}
.coverage-summary .headercell:nth-child(5n - 2),
.coverage-summary td:nth-child(5n - 2) {
border-left: 2px solid #fcfcfc;
padding-left: 2em;
}
.filetab {
display: inline-block;
width: 1em;
}
/* Sorter */
.sorter {
display: inline-block;
width: 7px;
height: 10px;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.sorted .sorter {
background-position: 0 -20px;
}
.sorted-desc .sorter {
background-position: 0 -10px;
}
.sortable {
cursor: pointer;
}
/* Bar */
.bar {
width: 50px;
height: 5px;
background: #fff;
}
.bar__data {
height: 100%;
}

176
node_modules/istanbul-reports/lib/html-spa/index.js generated vendored Normal file
View file

@ -0,0 +1,176 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const fs = require('fs');
const path = require('path');
const { ReportBase } = require('istanbul-lib-report');
const HtmlReport = require('../html');
const standardLinkMapper = {
getPath(node) {
if (typeof node === 'string') {
return node;
}
let filePath = node.getQualifiedName();
if (node.isSummary()) {
if (filePath !== '') {
filePath += '/index.html';
} else {
filePath = 'index.html';
}
} else {
filePath += '.html';
}
return filePath;
},
relativePath(source, target) {
const targetPath = this.getPath(target);
const sourcePath = path.dirname(this.getPath(source));
return path.relative(sourcePath, targetPath);
},
assetPath(node, name) {
return this.relativePath(this.getPath(node), name);
}
};
class HtmlSpaReport extends ReportBase {
constructor(opts = {}) {
super({
// force the summarizer to nested for html-spa
summarizer: 'nested'
});
this.verbose = opts.verbose || false;
this.linkMapper = opts.linkMapper || standardLinkMapper;
this.subdir = opts.subdir || '';
this.date = Date();
this.skipEmpty = opts.skipEmpty;
this.htmlReport = new HtmlReport(opts);
this.htmlReport.getBreadcrumbHtml = function() {
return '<a href="javascript:history.back()">Back</a>';
};
this.metricsToShow = opts.metricsToShow || [
'lines',
'branches',
'functions'
];
}
getWriter(context) {
if (!this.subdir) {
return context.writer;
}
return context.writer.writerForDir(this.subdir);
}
onStart(root, context) {
this.htmlReport.onStart(root, context);
const writer = this.getWriter(context);
const srcDir = path.resolve(__dirname, './assets');
fs.readdirSync(srcDir).forEach(f => {
const resolvedSource = path.resolve(srcDir, f);
const resolvedDestination = '.';
const stat = fs.statSync(resolvedSource);
let dest;
if (stat.isFile()) {
dest = resolvedDestination + '/' + f;
if (this.verbose) {
console.log('Write asset: ' + dest);
}
writer.copyFile(resolvedSource, dest);
}
});
}
onDetail(node, context) {
this.htmlReport.onDetail(node, context);
}
getMetric(metric, type, context) {
const isEmpty = metric.total === 0;
return {
total: metric.total,
covered: metric.covered,
skipped: metric.skipped,
missed: metric.total - metric.covered,
pct: isEmpty ? 0 : metric.pct,
classForPercent: isEmpty
? 'empty'
: context.classForPercent(type, metric.pct)
};
}
toDataStructure(node, context) {
const coverageSummary = node.getCoverageSummary();
const metrics = {
statements: this.getMetric(
coverageSummary.statements,
'statements',
context
),
branches: this.getMetric(
coverageSummary.branches,
'branches',
context
),
functions: this.getMetric(
coverageSummary.functions,
'functions',
context
),
lines: this.getMetric(coverageSummary.lines, 'lines', context)
};
return {
file: node.getRelativeName(),
isEmpty: coverageSummary.isEmpty(),
metrics,
children:
node.isSummary() &&
node
.getChildren()
.map(child => this.toDataStructure(child, context))
};
}
onEnd(rootNode, context) {
const data = this.toDataStructure(rootNode, context);
const cw = this.getWriter(context).writeFile(
this.linkMapper.getPath(rootNode)
);
cw.write(
`<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="spa.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app" class="app"></div>
<script>
window.data = ${JSON.stringify(data)};
window.generatedDatetime = ${JSON.stringify(
String(Date())
)};
window.metricsToShow = ${JSON.stringify(
this.metricsToShow
)};
</script>
<script src="bundle.js"></script>
</body>
</html>`
);
cw.close();
}
}
module.exports = HtmlSpaReport;

View file

@ -0,0 +1,31 @@
const React = require('react');
module.exports = function FileBreadcrumbs({ fileFilter = '', setFileFilter }) {
const parts = fileFilter.split('/');
const breadcrumbs = [
{
path: '',
name: 'all files'
},
...parts.map((part, i) => ({
path: parts.slice(0, i + 1).join('/'),
name: part
}))
];
return breadcrumbs.map(({ path, name }) =>
path === fileFilter ? (
name
) : (
<>
<a
href="javascript:void(0)"
onClick={() => setFileFilter(path)}
>
{name}
</a>
/
</>
)
);
};

View file

@ -0,0 +1,50 @@
const React = require('react');
function ToggleOption({ children, filter, activeFilters, setFilters }) {
return (
<button
className={
'toggle__option ' + (activeFilters[filter] ? 'is-toggled' : '')
}
onClick={() =>
setFilters({
...activeFilters,
[filter]: !activeFilters[filter]
})
}
>
{children}
</button>
);
}
module.exports = function FilterToggle({ activeFilters, setFilters }) {
return (
<div className="toggle">
<div className="toggle__label">Filter:</div>
<div className="toggle__options">
<ToggleOption
filter="low"
activeFilters={activeFilters}
setFilters={setFilters}
>
Low
</ToggleOption>
<ToggleOption
filter="medium"
activeFilters={activeFilters}
setFilters={setFilters}
>
Medium
</ToggleOption>
<ToggleOption
filter="high"
activeFilters={activeFilters}
setFilters={setFilters}
>
High
</ToggleOption>
</div>
</div>
);
};

View file

@ -0,0 +1,25 @@
const React = require('react');
module.exports = function FlattenButton({ setIsFlat, isFlat }) {
return (
<div className="toggle">
<div className="toggle__label">Files:</div>
<div className="toggle__options">
<button
onClick={() => setIsFlat(!isFlat)}
className={
'toggle__option ' + (!isFlat ? 'is-toggled' : '')
}
>
Tree
</button>
<button
onClick={() => setIsFlat(!isFlat)}
className={'toggle__option ' + (isFlat ? 'is-toggled' : '')}
>
Flat
</button>
</div>{' '}
</div>
);
};

View file

@ -0,0 +1,155 @@
function addPath(node, parentPath) {
if (!parentPath) {
return node;
}
return { ...node, file: parentPath + '/' + node.file };
}
function flatten(nodes, parentPath) {
let children = [];
for (let i = 0; i < nodes.length; i++) {
const child = nodes[i];
if (child.children) {
children = [
...children,
...flatten(
child.children,
(parentPath ? parentPath + '/' : '') + child.file
)
];
} else {
children.push(addPath(child, parentPath));
}
}
return children;
}
function filterByFile(nodes, fileFilter, parentPath) {
let children = [];
for (let i = 0; i < nodes.length; i++) {
const child = nodes[i];
const childFullPath = (parentPath ? parentPath + '/' : '') + child.file;
const isChildUnderFilter =
fileFilter === childFullPath ||
fileFilter.indexOf(childFullPath + '/') === 0;
const isChildAboveFilter =
childFullPath.indexOf(fileFilter + '/') === 0;
if (isChildUnderFilter) {
// flatten and continue looking underneath
children = [
...children,
...filterByFile(child.children, fileFilter, childFullPath)
];
} else if (isChildAboveFilter) {
// remove the parent path and add everything underneath
const charsToRemoveFromFile =
fileFilter.length - (parentPath ? parentPath.length : 0);
let childFilename = child.file.slice(charsToRemoveFromFile);
if (childFilename[0] === '/') {
childFilename = childFilename.slice(1);
}
children.push({
...child,
file: childFilename
});
}
}
return children;
}
function sort(childData, activeSort) {
const top = activeSort.order === 'asc' ? 1 : -1;
const bottom = activeSort.order === 'asc' ? -1 : 1;
childData.sort((a, b) => {
let valueA;
let valueB;
if (activeSort.sortKey === 'file') {
valueA = a.file;
valueB = b.file;
} else {
const [metricType, valueType] = activeSort.sortKey.split('.');
valueA = a.metrics[metricType][valueType];
valueB = b.metrics[metricType][valueType];
}
if (valueA === valueB) {
return 0;
}
return valueA < valueB ? top : bottom;
});
for (let i = 0; i < childData.length; i++) {
const child = childData[i];
if (child.children) {
childData[i] = {
...child,
children: sort(child.children, activeSort)
};
}
}
return childData;
}
function filter(nodes, metricsMap, activeFilters) {
const children = [];
for (let i = 0; i < nodes.length; i++) {
let child = nodes[i];
if (child.children) {
const newSubChildren = filter(
child.children,
metricsMap,
activeFilters
);
if (newSubChildren.length) {
child = { ...child, children: newSubChildren };
children.push(child);
}
} else {
if (
(metricsMap.statements &&
activeFilters[child.metrics.statements.classForPercent]) ||
(metricsMap.branches &&
activeFilters[child.metrics.branches.classForPercent]) ||
(metricsMap.functions &&
activeFilters[child.metrics.functions.classForPercent]) ||
(metricsMap.lines &&
activeFilters[child.metrics.lines.classForPercent])
) {
children.push(child);
}
}
}
return children;
}
module.exports = function getChildData(
sourceData,
metricsToShow,
activeSort,
isFlat,
activeFilters,
fileFilter
) {
let childData = sourceData.children;
if (isFlat) {
childData = flatten(childData.slice(0));
}
if (fileFilter) {
childData = filterByFile(childData, fileFilter);
}
if (activeFilters.low) {
activeFilters = { ...activeFilters, empty: true };
}
childData = filter(childData, metricsToShow, activeFilters);
if (activeSort) {
childData = sort(childData, activeSort);
}
return childData;
};

160
node_modules/istanbul-reports/lib/html-spa/src/index.js generated vendored Normal file
View file

@ -0,0 +1,160 @@
// The index file for the spa running on the summary page
const React = require('react');
const ReactDOM = require('react-dom');
const SummaryTableHeader = require('./summaryTableHeader');
const SummaryTableLine = require('./summaryTableLine');
const SummaryHeader = require('./summaryHeader');
const getChildData = require('./getChildData');
const FlattenToggle = require('./flattenToggle');
const FilterToggle = require('./filterToggle');
const FileBreadcrumbs = require('./fileBreadcrumbs');
const { setLocation, decodeLocation } = require('./routing');
const { useState, useMemo, useEffect } = React;
const sourceData = window.data;
const metricsToShow = {};
for (let i = 0; i < window.metricsToShow.length; i++) {
metricsToShow[window.metricsToShow[i]] = true;
}
let firstMount = true;
function App() {
const routingDefaults = decodeLocation();
const [activeSort, setSort] = useState(
(routingDefaults && routingDefaults.activeSort) || {
sortKey: 'file',
order: 'desc'
}
);
const [isFlat, setIsFlat] = useState(
(routingDefaults && routingDefaults.isFlat) || false
);
const [activeFilters, setFilters] = useState(
(routingDefaults && routingDefaults.activeFilters) || {
low: true,
medium: true,
high: true
}
);
const [expandedLines, setExpandedLines] = useState(
(routingDefaults && routingDefaults.expandedLines) || []
);
const [fileFilter, setFileFilter] = useState(
(routingDefaults && routingDefaults.fileFilter) || ''
);
const childData = useMemo(
() =>
getChildData(
sourceData,
metricsToShow,
activeSort,
isFlat,
activeFilters,
fileFilter
),
[activeSort, isFlat, activeFilters, fileFilter]
);
const overallMetrics = sourceData.metrics;
useEffect(() => {
setLocation(
firstMount,
activeSort,
isFlat,
activeFilters,
fileFilter,
expandedLines
);
firstMount = false;
}, [activeSort, isFlat, activeFilters, fileFilter, expandedLines]);
useEffect(() => {
window.onpopstate = () => {
const routingState = decodeLocation();
if (routingState) {
// make sure all the state is set before rendering to avoid url updates
// alternative is to merge all the states into one so it can be set in one go
// https://github.com/facebook/react/issues/14259
ReactDOM.unstable_batchedUpdates(() => {
setFilters(routingState.activeFilters);
setSort(routingState.activeSort);
setIsFlat(routingState.isFlat);
setExpandedLines(routingState.expandedLines);
setFileFilter(routingState.fileFilter);
});
}
};
}, []);
return (
<div className="layout">
<div className="layout__section">
<SummaryHeader
metrics={overallMetrics}
metricsToShow={metricsToShow}
/>
</div>
<div className="layout__section">
<div className="toolbar">
<div className="toolbar__item">
<FlattenToggle setIsFlat={setIsFlat} isFlat={isFlat} />
</div>
<div className="toolbar__item">
<FilterToggle
activeFilters={activeFilters}
setFilters={setFilters}
/>
</div>
</div>
</div>
<div className="layout__section">
<h1>
<FileBreadcrumbs
fileFilter={fileFilter}
setFileFilter={setFileFilter}
/>
</h1>
</div>
<div className="layout__section layout__section--fill">
<table className="coverage-summary">
<SummaryTableHeader
onSort={newSort => {
setSort(newSort);
}}
activeSort={activeSort}
metricsToShow={metricsToShow}
/>
<tbody>
{childData.map(child => (
<SummaryTableLine
{...child}
key={child.file}
metricsToShow={metricsToShow}
expandedLines={expandedLines}
setExpandedLines={setExpandedLines}
fileFilter={fileFilter}
setFileFilter={setFileFilter}
/>
))}
</tbody>
</table>
</div>
<div className="layout__section center small quiet">
Code coverage generated by{' '}
<a
href="https://istanbul.js.org/"
target="_blank"
rel="noopener noreferrer"
>
istanbul
</a>{' '}
at {window.generatedDatetime}
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'));

View file

@ -0,0 +1,52 @@
exports.setLocation = function setLocation(
isReplace,
activeSort,
isFlat,
activeFilters,
fileFilter,
expandedLines
) {
const params = [
activeSort.sortKey,
activeSort.order,
isFlat,
activeFilters.low,
activeFilters.medium,
activeFilters.high,
encodeURIComponent(fileFilter),
expandedLines.map(encodeURIComponent).join(',')
];
const newUrl = `#${params.join('/')}`;
if (newUrl === location.hash) {
return;
}
window.history[isReplace ? 'replaceState' : 'pushState'](null, '', newUrl);
};
exports.decodeLocation = function decodeLocation() {
const items = location.hash.substr(1).split('/');
if (items.length !== 8) {
return null;
}
try {
return {
activeSort: {
sortKey: items[0],
order: items[1]
},
isFlat: JSON.parse(items[2]),
activeFilters: {
low: JSON.parse(items[3]),
medium: JSON.parse(items[4]),
high: JSON.parse(items[5])
},
fileFilter: decodeURIComponent(items[6]),
expandedLines: items[7].split(',').map(decodeURIComponent)
};
} catch (e) {
return null;
}
};

View file

@ -0,0 +1,63 @@
const React = require('react');
function Ignores({ metrics, metricsToShow }) {
const metricKeys = Object.keys(metricsToShow);
const result = [];
for (let i = 0; i < metricKeys.length; i++) {
const metricKey = metricKeys[i];
if (metricsToShow[metricKey]) {
const skipped = metrics[metricKey].skipped;
if (skipped > 0) {
result.push(
`${skipped} ${metricKey}${
skipped === 1 ? '' : metricKey === 'branch' ? 'es' : 's'
}`
);
}
}
}
if (result.length === 0) {
return false;
}
return (
<div className="toolbar__item">
<span className="strong">{result.join(', ')}</span>
<span className="quiet">Ignored</span>
</div>
);
}
function StatusMetric({ data, name }) {
return (
<div className="toolbar__item">
<span className="strong">{data.pct}%</span>{' '}
<span className="quiet">{name}</span>{' '}
<span className={'fraction ' + data.classForPercent}>
{data.covered}/{data.total}
</span>
</div>
);
}
module.exports = function SummaryHeader({ metrics, metricsToShow }) {
return (
<div className="toolbar">
{metricsToShow.statements && (
<StatusMetric data={metrics.statements} name="Statements" />
)}
{metricsToShow.branches && (
<StatusMetric data={metrics.branches} name="Branches" />
)}
{metricsToShow.functions && (
<StatusMetric data={metrics.functions} name="Functions" />
)}
{metricsToShow.lines && (
<StatusMetric data={metrics.lines} name="Lines" />
)}
<Ignores metrics={metrics} metricsToShow={metricsToShow} />
</div>
);
};

View file

@ -0,0 +1,130 @@
const React = require('react');
function getSortDetails(sortKey, activeSort) {
let newSort = { sortKey, order: 'desc' };
let sortClass = '';
if (activeSort && activeSort.sortKey === sortKey) {
sortClass = 'sorted';
if (activeSort.order === 'desc') {
sortClass += '-desc';
newSort.order = 'asc';
} else {
if (sortKey !== 'file') {
newSort = { sortKey: 'file', order: 'desc' };
}
}
}
return {
newSort,
sortClass
};
}
function SummaryTableHeaderCell({ name, onSort, sortKey, activeSort }) {
const { newSort, sortClass } = getSortDetails(sortKey, activeSort);
return (
<th
className={'sortable headercell ' + sortClass}
onClick={() => onSort(newSort)}
>
{name}
<span className="sorter" />
</th>
);
}
function FileHeaderCell({ onSort, activeSort }) {
const { newSort, sortClass } = getSortDetails('file', activeSort);
return (
<th
className={'sortable file ' + sortClass}
onClick={() => onSort(newSort)}
>
File
<span className="sorter" />
</th>
);
}
function SubHeadings({ sortKeyPrefix, onSort, activeSort }) {
return (
<>
<SummaryTableHeaderCell
name="%"
onSort={onSort}
sortKey={sortKeyPrefix + '.pct'}
activeSort={activeSort}
/>
<th className="headercell"></th>
<SummaryTableHeaderCell
name="Covered"
onSort={onSort}
sortKey={sortKeyPrefix + '.covered'}
activeSort={activeSort}
/>
<SummaryTableHeaderCell
name="Missed"
onSort={onSort}
sortKey={sortKeyPrefix + '.missed'}
activeSort={activeSort}
/>
<SummaryTableHeaderCell
name="Total"
onSort={onSort}
sortKey={sortKeyPrefix + '.total'}
activeSort={activeSort}
/>
</>
);
}
module.exports = function SummaryTableHeader({
onSort,
activeSort,
metricsToShow
}) {
return (
<thead>
<tr className="topheading">
<th></th>
{metricsToShow.statements && <th colSpan={4}>Statements</th>}
{metricsToShow.branches && <th colSpan={4}>Branches</th>}
{metricsToShow.functions && <th colSpan={4}>Functions</th>}
{metricsToShow.lines && <th colSpan={4}>Lines</th>}
</tr>
<tr className="subheading">
<FileHeaderCell onSort={onSort} activeSort={activeSort} />
{metricsToShow.statements && (
<SubHeadings
sortKeyPrefix="statements"
onSort={onSort}
activeSort={activeSort}
/>
)}
{metricsToShow.branches && (
<SubHeadings
sortKeyPrefix="branches"
onSort={onSort}
activeSort={activeSort}
/>
)}
{metricsToShow.functions && (
<SubHeadings
sortKeyPrefix="functions"
onSort={onSort}
activeSort={activeSort}
/>
)}
{metricsToShow.lines && (
<SubHeadings
sortKeyPrefix="lines"
onSort={onSort}
activeSort={activeSort}
/>
)}
</tr>
</thead>
);
};

View file

@ -0,0 +1,159 @@
const React = require('react');
function MetricCells({ metrics }) {
const { classForPercent, pct, covered, missed, total } = metrics;
return (
<>
<td className={'pct ' + classForPercent}>{Math.round(pct)}% </td>
<td className={classForPercent}>
<div className="bar">
<div
className={`bar__data ${classForPercent} ${classForPercent}--dark`}
style={{ width: pct + '%' }}
></div>
</div>
</td>
<td className={'abs ' + classForPercent}>{covered}</td>
<td className={'abs ' + classForPercent}>{missed}</td>
<td className={'abs ' + classForPercent}>{total}</td>
</>
);
}
function FileCell({
file,
prefix,
expandedLines,
setExpandedLines,
hasChildren,
setFileFilter
}) {
if (hasChildren) {
const expandedIndex = expandedLines.indexOf(prefix + file);
const isExpanded = expandedIndex >= 0;
const newExpandedLines = isExpanded
? [
...expandedLines.slice(0, expandedIndex),
...expandedLines.slice(expandedIndex + 1)
]
: [...expandedLines, prefix + file];
return (
<>
<button
type="button"
onClick={() => setExpandedLines(newExpandedLines)}
className="expandbutton"
>
{isExpanded ? String.fromCharCode(0x2013) : '+'}
</button>
<a
href="javascript:void(0)"
onClick={() => setFileFilter(prefix + file)}
>
{file}
</a>
</>
);
} else {
return <a href={`./${prefix}${file}.html`}>{file}</a>;
}
}
function getWorstMetricClassForPercent(metricsToShow, metrics) {
let classForPercent = 'none';
for (const metricToShow in metricsToShow) {
if (metricsToShow[metricToShow]) {
const metricClassForPercent = metrics[metricToShow].classForPercent;
// ignore none metrics so they don't change whats shown
if (metricClassForPercent === 'none') {
continue;
}
// if the metric low or lower than whats currently being used, replace it
if (
metricClassForPercent == 'low' ||
(metricClassForPercent === 'medium' &&
classForPercent !== 'low') ||
(metricClassForPercent === 'high' &&
classForPercent !== 'low' &&
classForPercent !== 'medium')
) {
classForPercent = metricClassForPercent;
}
}
}
return classForPercent;
}
module.exports = function SummaryTableLine({
prefix,
metrics,
file,
children,
tabSize,
metricsToShow,
expandedLines,
setExpandedLines,
fileFilter,
setFileFilter
}) {
tabSize = tabSize || 0;
if (children && tabSize > 0) {
tabSize--;
}
prefix = (fileFilter ? fileFilter + '/' : '') + (prefix || '');
return (
<>
<tr>
<td
className={
'file ' +
getWorstMetricClassForPercent(metricsToShow, metrics)
}
>
{/* eslint-disable-line prefer-spread */ Array.apply(null, {
length: tabSize
}).map((nothing, index) => (
<span className="filetab" key={index} />
))}
<FileCell
file={file}
prefix={prefix}
expandedLines={expandedLines}
setExpandedLines={setExpandedLines}
hasChildren={Boolean(children)}
setFileFilter={setFileFilter}
/>
</td>
{metricsToShow.statements && (
<MetricCells metrics={metrics.statements} />
)}
{metricsToShow.branches && (
<MetricCells metrics={metrics.branches} />
)}
{metricsToShow.functions && (
<MetricCells metrics={metrics.functions} />
)}
{metricsToShow.lines && <MetricCells metrics={metrics.lines} />}
</tr>
{children &&
expandedLines.indexOf(prefix + file) >= 0 &&
children.map(child => (
<SummaryTableLine
{...child}
tabSize={tabSize + 2}
key={child.file}
prefix={prefix + file + '/'}
metricsToShow={metricsToShow}
expandedLines={expandedLines}
setExpandedLines={setExpandedLines}
setFileFilter={setFileFilter}
/>
))}
</>
);
};

View file

@ -0,0 +1,22 @@
'use strict';
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, 'src/index.js'),
output: {
path: path.resolve(__dirname, 'assets'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};

305
node_modules/istanbul-reports/lib/html/annotator.js generated vendored Normal file
View file

@ -0,0 +1,305 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const InsertionText = require('./insertion-text');
const lt = '\u0001';
const gt = '\u0002';
const RE_LT = /</g;
const RE_GT = />/g;
const RE_AMP = /&/g;
// eslint-disable-next-line
var RE_lt = /\u0001/g;
// eslint-disable-next-line
var RE_gt = /\u0002/g;
function title(str) {
return ' title="' + str + '" ';
}
function customEscape(text) {
text = String(text);
return text
.replace(RE_AMP, '&amp;')
.replace(RE_LT, '&lt;')
.replace(RE_GT, '&gt;')
.replace(RE_lt, '<')
.replace(RE_gt, '>');
}
function annotateLines(fileCoverage, structuredText) {
const lineStats = fileCoverage.getLineCoverage();
if (!lineStats) {
return;
}
Object.entries(lineStats).forEach(([lineNumber, count]) => {
if (structuredText[lineNumber]) {
structuredText[lineNumber].covered = count > 0 ? 'yes' : 'no';
structuredText[lineNumber].hits = count;
}
});
}
function annotateStatements(fileCoverage, structuredText) {
const statementStats = fileCoverage.s;
const statementMeta = fileCoverage.statementMap;
Object.entries(statementStats).forEach(([stName, count]) => {
const meta = statementMeta[stName];
const type = count > 0 ? 'yes' : 'no';
const startCol = meta.start.column;
let endCol = meta.end.column + 1;
const startLine = meta.start.line;
const endLine = meta.end.line;
const openSpan =
lt +
'span class="' +
(meta.skip ? 'cstat-skip' : 'cstat-no') +
'"' +
title('statement not covered') +
gt;
const closeSpan = lt + '/span' + gt;
let text;
if (type === 'no' && structuredText[startLine]) {
if (endLine !== startLine) {
endCol = structuredText[startLine].text.originalLength();
}
text = structuredText[startLine].text;
text.wrap(
startCol,
openSpan,
startCol < endCol ? endCol : text.originalLength(),
closeSpan
);
}
});
}
function annotateFunctions(fileCoverage, structuredText) {
const fnStats = fileCoverage.f;
const fnMeta = fileCoverage.fnMap;
if (!fnStats) {
return;
}
Object.entries(fnStats).forEach(([fName, count]) => {
const meta = fnMeta[fName];
const type = count > 0 ? 'yes' : 'no';
// Some versions of the instrumenter in the wild populate 'func'
// but not 'decl':
const decl = meta.decl || meta.loc;
const startCol = decl.start.column;
let endCol = decl.end.column + 1;
const startLine = decl.start.line;
const endLine = decl.end.line;
const openSpan =
lt +
'span class="' +
(meta.skip ? 'fstat-skip' : 'fstat-no') +
'"' +
title('function not covered') +
gt;
const closeSpan = lt + '/span' + gt;
let text;
if (type === 'no' && structuredText[startLine]) {
if (endLine !== startLine) {
endCol = structuredText[startLine].text.originalLength();
}
text = structuredText[startLine].text;
text.wrap(
startCol,
openSpan,
startCol < endCol ? endCol : text.originalLength(),
closeSpan
);
}
});
}
function annotateBranches(fileCoverage, structuredText) {
const branchStats = fileCoverage.b;
const branchMeta = fileCoverage.branchMap;
if (!branchStats) {
return;
}
Object.entries(branchStats).forEach(([branchName, branchArray]) => {
const sumCount = branchArray.reduce((p, n) => p + n, 0);
const metaArray = branchMeta[branchName].locations;
let i;
let count;
let meta;
let startCol;
let endCol;
let startLine;
let endLine;
let openSpan;
let closeSpan;
let text;
// only highlight if partial branches are missing or if there is a
// single uncovered branch.
if (sumCount > 0 || (sumCount === 0 && branchArray.length === 1)) {
// Need to recover the metaArray placeholder item to count an implicit else
if (
// Check if the branch is a conditional if branch.
branchMeta[branchName].type === 'if' &&
// Check if the branch has an implicit else.
branchArray.length === 2 &&
// Check if the implicit else branch is unaccounted for.
metaArray.length === 1 &&
// Check if the implicit else branch is uncovered.
branchArray[1] === 0
) {
metaArray[1] = {
start: {},
end: {}
};
}
for (
i = 0;
i < branchArray.length && i < metaArray.length;
i += 1
) {
count = branchArray[i];
meta = metaArray[i];
startCol = meta.start.column;
endCol = meta.end.column + 1;
startLine = meta.start.line;
endLine = meta.end.line;
openSpan =
lt +
'span class="branch-' +
i +
' ' +
(meta.skip ? 'cbranch-skip' : 'cbranch-no') +
'"' +
title('branch not covered') +
gt;
closeSpan = lt + '/span' + gt;
// If the branch is an implicit else from an if statement,
// then the coverage report won't show a statistic.
// Therefore, the previous branch will be used to report that
// there is no coverage on that implicit branch.
if (
count === 0 &&
startLine === undefined &&
branchMeta[branchName].type === 'if'
) {
const prevMeta = metaArray[i - 1];
startCol = prevMeta.start.column;
endCol = prevMeta.end.column + 1;
startLine = prevMeta.start.line;
endLine = prevMeta.end.line;
}
if (count === 0 && structuredText[startLine]) {
//skip branches taken
if (endLine !== startLine) {
endCol = structuredText[
startLine
].text.originalLength();
}
text = structuredText[startLine].text;
if (branchMeta[branchName].type === 'if') {
// 'if' is a special case
// since the else branch might not be visible, being nonexistent
text.insertAt(
startCol,
lt +
'span class="' +
(meta.skip
? 'skip-if-branch'
: 'missing-if-branch') +
'"' +
title(
(i === 0 ? 'if' : 'else') +
' path not taken'
) +
gt +
(i === 0 ? 'I' : 'E') +
lt +
'/span' +
gt,
true,
false
);
} else {
text.wrap(
startCol,
openSpan,
startCol < endCol ? endCol : text.originalLength(),
closeSpan
);
}
}
}
}
});
}
function annotateSourceCode(fileCoverage, sourceStore) {
let codeArray;
let lineCoverageArray;
try {
const sourceText = sourceStore.getSource(fileCoverage.path);
const code = sourceText.split(/(?:\r?\n)|\r/);
let count = 0;
const structured = code.map(str => {
count += 1;
return {
line: count,
covered: 'neutral',
hits: 0,
text: new InsertionText(str, true)
};
});
structured.unshift({
line: 0,
covered: null,
text: new InsertionText('')
});
annotateLines(fileCoverage, structured);
//note: order is important, since statements typically result in spanning the whole line and doing branches late
//causes mismatched tags
annotateBranches(fileCoverage, structured);
annotateFunctions(fileCoverage, structured);
annotateStatements(fileCoverage, structured);
structured.shift();
codeArray = structured.map(
item => customEscape(item.text.toString()) || '&nbsp;'
);
lineCoverageArray = structured.map(item => ({
covered: item.covered,
hits: item.hits > 0 ? item.hits + 'x' : '&nbsp;'
}));
return {
annotatedCode: codeArray,
lineCoverage: lineCoverageArray,
maxLines: structured.length
};
} catch (ex) {
codeArray = [ex.message];
lineCoverageArray = [{ covered: 'no', hits: 0 }];
String(ex.stack || '')
.split(/\r?\n/)
.forEach(line => {
codeArray.push(line);
lineCoverageArray.push({ covered: 'no', hits: 0 });
});
return {
annotatedCode: codeArray,
lineCoverage: lineCoverageArray,
maxLines: codeArray.length
};
}
}
module.exports = annotateSourceCode;

224
node_modules/istanbul-reports/lib/html/assets/base.css generated vendored Normal file
View file

@ -0,0 +1,224 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}
.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }
.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}
div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}
table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }
.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
span.cline-neutral { background: #eaeaea; }
.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}
.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}

View file

@ -0,0 +1,86 @@
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];
// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
// Selecter that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);
var currentIndex;
function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}
function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}
makeCurrent(nextIndex);
}
function goToNext() {
var nextIndex = 0;
if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}
makeCurrent(nextIndex);
}
return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}
switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

195
node_modules/istanbul-reports/lib/html/assets/sorter.js generated vendored Normal file
View file

@ -0,0 +1,195 @@
var addSorting = (function() {
'use strict';
var cols,
currentSort = {
index: 0,
desc: false
};
// returns the summary table element
function getTable() {
return document.querySelector('.coverage-summary');
}
// returns the thead element of the summary table
function getTableHeader() {
return getTable().querySelector('thead tr');
}
// returns the tbody element of the summary table
function getTableBody() {
return getTable().querySelector('tbody');
}
// returns the th element for nth column
function getNthColumn(n) {
return getTableHeader().querySelectorAll('th')[n];
}
function onFilterInput() {
const searchValue = document.getElementById('fileSearch').value;
const rows = document.getElementsByTagName('tbody')[0].children;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
if (
row.textContent
.toLowerCase()
.includes(searchValue.toLowerCase())
) {
row.style.display = '';
} else {
row.style.display = 'none';
}
}
}
// loads the search box
function addSearchBox() {
var template = document.getElementById('filterTemplate');
var templateClone = template.content.cloneNode(true);
templateClone.getElementById('fileSearch').oninput = onFilterInput;
template.parentElement.appendChild(templateClone);
}
// loads all columns
function loadColumns() {
var colNodes = getTableHeader().querySelectorAll('th'),
colNode,
cols = [],
col,
i;
for (i = 0; i < colNodes.length; i += 1) {
colNode = colNodes[i];
col = {
key: colNode.getAttribute('data-col'),
sortable: !colNode.getAttribute('data-nosort'),
type: colNode.getAttribute('data-type') || 'string'
};
cols.push(col);
if (col.sortable) {
col.defaultDescSort = col.type === 'number';
colNode.innerHTML =
colNode.innerHTML + '<span class="sorter"></span>';
}
}
return cols;
}
// attaches a data attribute to every tr element with an object
// of data values keyed by column name
function loadRowData(tableRow) {
var tableCols = tableRow.querySelectorAll('td'),
colNode,
col,
data = {},
i,
val;
for (i = 0; i < tableCols.length; i += 1) {
colNode = tableCols[i];
col = cols[i];
val = colNode.getAttribute('data-value');
if (col.type === 'number') {
val = Number(val);
}
data[col.key] = val;
}
return data;
}
// loads all row data
function loadData() {
var rows = getTableBody().querySelectorAll('tr'),
i;
for (i = 0; i < rows.length; i += 1) {
rows[i].data = loadRowData(rows[i]);
}
}
// sorts the table using the data for the ith column
function sortByIndex(index, desc) {
var key = cols[index].key,
sorter = function(a, b) {
a = a.data[key];
b = b.data[key];
return a < b ? -1 : a > b ? 1 : 0;
},
finalSorter = sorter,
tableBody = document.querySelector('.coverage-summary tbody'),
rowNodes = tableBody.querySelectorAll('tr'),
rows = [],
i;
if (desc) {
finalSorter = function(a, b) {
return -1 * sorter(a, b);
};
}
for (i = 0; i < rowNodes.length; i += 1) {
rows.push(rowNodes[i]);
tableBody.removeChild(rowNodes[i]);
}
rows.sort(finalSorter);
for (i = 0; i < rows.length; i += 1) {
tableBody.appendChild(rows[i]);
}
}
// removes sort indicators for current column being sorted
function removeSortIndicators() {
var col = getNthColumn(currentSort.index),
cls = col.className;
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
col.className = cls;
}
// adds sort indicators for current column being sorted
function addSortIndicators() {
getNthColumn(currentSort.index).className += currentSort.desc
? ' sorted-desc'
: ' sorted';
}
// adds event listeners for all sorter widgets
function enableUI() {
var i,
el,
ithSorter = function ithSorter(i) {
var col = cols[i];
return function() {
var desc = col.defaultDescSort;
if (currentSort.index === i) {
desc = !currentSort.desc;
}
sortByIndex(i, desc);
removeSortIndicators();
currentSort.index = i;
currentSort.desc = desc;
addSortIndicators();
};
};
for (i = 0; i < cols.length; i += 1) {
if (cols[i].sortable) {
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {
el.addEventListener('click', ithSorter(i));
} else {
el.attachEvent('onclick', ithSorter(i));
}
}
}
}
// adds sorting functionality to the UI
return function() {
if (!getTable()) {
return;
}
cols = loadColumns();
loadData();
addSearchBox();
addSortIndicators();
enableUI();
};
})();
window.addEventListener('load', addSorting);

View file

@ -0,0 +1 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

File diff suppressed because one or more lines are too long

421
node_modules/istanbul-reports/lib/html/index.js generated vendored Normal file
View file

@ -0,0 +1,421 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const fs = require('fs');
const path = require('path');
const html = require('html-escaper');
const { ReportBase } = require('istanbul-lib-report');
const annotator = require('./annotator');
function htmlHead(details) {
return `
<head>
<title>Code coverage report for ${html.escape(details.entity)}</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="${html.escape(details.prettify.css)}" />
<link rel="stylesheet" href="${html.escape(details.base.css)}" />
<link rel="shortcut icon" type="image/x-icon" href="${html.escape(
details.favicon
)}" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(${html.escape(details.sorter.image)});
}
</style>
</head>
`;
}
function headerTemplate(details) {
function metricsTemplate({ pct, covered, total }, kind) {
return `
<div class='fl pad1y space-right2'>
<span class="strong">${pct}% </span>
<span class="quiet">${kind}</span>
<span class='fraction'>${covered}/${total}</span>
</div>
`;
}
function skipTemplate(metrics) {
const statements = metrics.statements.skipped;
const branches = metrics.branches.skipped;
const functions = metrics.functions.skipped;
const countLabel = (c, label, plural) =>
c === 0 ? [] : `${c} ${label}${c === 1 ? '' : plural}`;
const skips = [].concat(
countLabel(statements, 'statement', 's'),
countLabel(functions, 'function', 's'),
countLabel(branches, 'branch', 'es')
);
if (skips.length === 0) {
return '';
}
return `
<div class='fl pad1y'>
<span class="strong">${skips.join(', ')}</span>
<span class="quiet">Ignored</span> &nbsp;&nbsp;&nbsp;&nbsp;
</div>
`;
}
return `
<!doctype html>
<html lang="en">
${htmlHead(details)}
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>${details.pathHtml}</h1>
<div class='clearfix'>
${metricsTemplate(details.metrics.statements, 'Statements')}
${metricsTemplate(details.metrics.branches, 'Branches')}
${metricsTemplate(details.metrics.functions, 'Functions')}
${metricsTemplate(details.metrics.lines, 'Lines')}
${skipTemplate(details.metrics)}
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line ${details.reportClass}'></div>
`;
}
function footerTemplate(details) {
return `
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at ${html.escape(details.datetime)}
</div>
<script src="${html.escape(details.prettify.js)}"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="${html.escape(details.sorter.js)}"></script>
<script src="${html.escape(details.blockNavigation.js)}"></script>
</body>
</html>
`;
}
function detailTemplate(data) {
const lineNumbers = new Array(data.maxLines).fill().map((_, i) => i + 1);
const lineLink = num =>
`<a name='L${num}'></a><a href='#L${num}'>${num}</a>`;
const lineCount = line =>
`<span class="cline-any cline-${line.covered}">${line.hits}</span>`;
/* This is rendered in a `<pre>`, need control of all whitespace. */
return [
'<tr>',
`<td class="line-count quiet">${lineNumbers
.map(lineLink)
.join('\n')}</td>`,
`<td class="line-coverage quiet">${data.lineCoverage
.map(lineCount)
.join('\n')}</td>`,
`<td class="text"><pre class="prettyprint lang-js">${data.annotatedCode.join(
'\n'
)}</pre></td>`,
'</tr>'
].join('');
}
const summaryTableHeader = [
'<div class="pad1">',
'<table class="coverage-summary">',
'<thead>',
'<tr>',
' <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>',
' <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>',
' <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>',
' <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>',
' <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>',
' <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>',
' <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>',
' <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>',
' <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>',
' <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>',
'</tr>',
'</thead>',
'<tbody>'
].join('\n');
function summaryLineTemplate(details) {
const { reportClasses, metrics, file, output } = details;
const percentGraph = pct => {
if (!isFinite(pct)) {
return '';
}
const cls = ['cover-fill'];
if (pct === 100) {
cls.push('cover-full');
}
pct = Math.floor(pct);
return [
`<div class="${cls.join(' ')}" style="width: ${pct}%"></div>`,
`<div class="cover-empty" style="width: ${100 - pct}%"></div>`
].join('');
};
const summaryType = (type, showGraph = false) => {
const info = metrics[type];
const reportClass = reportClasses[type];
const result = [
`<td data-value="${info.pct}" class="pct ${reportClass}">${info.pct}%</td>`,
`<td data-value="${info.total}" class="abs ${reportClass}">${info.covered}/${info.total}</td>`
];
if (showGraph) {
result.unshift(
`<td data-value="${info.pct}" class="pic ${reportClass}">`,
`<div class="chart">${percentGraph(info.pct)}</div>`,
`</td>`
);
}
return result;
};
return []
.concat(
'<tr>',
`<td class="file ${
reportClasses.statements
}" data-value="${html.escape(file)}"><a href="${html.escape(
output
)}">${html.escape(file)}</a></td>`,
summaryType('statements', true),
summaryType('branches'),
summaryType('functions'),
summaryType('lines'),
'</tr>\n'
)
.join('\n\t');
}
const summaryTableFooter = ['</tbody>', '</table>', '</div>'].join('\n');
const emptyClasses = {
statements: 'empty',
lines: 'empty',
functions: 'empty',
branches: 'empty'
};
const standardLinkMapper = {
getPath(node) {
if (typeof node === 'string') {
return node;
}
let filePath = node.getQualifiedName();
if (node.isSummary()) {
if (filePath !== '') {
filePath += '/index.html';
} else {
filePath = 'index.html';
}
} else {
filePath += '.html';
}
return filePath;
},
relativePath(source, target) {
const targetPath = this.getPath(target);
const sourcePath = path.dirname(this.getPath(source));
return path.posix.relative(sourcePath, targetPath);
},
assetPath(node, name) {
return this.relativePath(this.getPath(node), name);
}
};
function fixPct(metrics) {
Object.keys(emptyClasses).forEach(key => {
metrics[key].pct = 0;
});
return metrics;
}
class HtmlReport extends ReportBase {
constructor(opts) {
super();
this.verbose = opts.verbose;
this.linkMapper = opts.linkMapper || standardLinkMapper;
this.subdir = opts.subdir || '';
this.date = new Date().toISOString();
this.skipEmpty = opts.skipEmpty;
}
getBreadcrumbHtml(node) {
let parent = node.getParent();
const nodePath = [];
while (parent) {
nodePath.push(parent);
parent = parent.getParent();
}
const linkPath = nodePath.map(ancestor => {
const target = this.linkMapper.relativePath(node, ancestor);
const name = ancestor.getRelativeName() || 'All files';
return '<a href="' + target + '">' + name + '</a>';
});
linkPath.reverse();
return linkPath.length > 0
? linkPath.join(' / ') + ' ' + node.getRelativeName()
: 'All files';
}
fillTemplate(node, templateData, context) {
const linkMapper = this.linkMapper;
const summary = node.getCoverageSummary();
templateData.entity = node.getQualifiedName() || 'All files';
templateData.metrics = summary;
templateData.reportClass = context.classForPercent(
'statements',
summary.statements.pct
);
templateData.pathHtml = this.getBreadcrumbHtml(node);
templateData.base = {
css: linkMapper.assetPath(node, 'base.css')
};
templateData.sorter = {
js: linkMapper.assetPath(node, 'sorter.js'),
image: linkMapper.assetPath(node, 'sort-arrow-sprite.png')
};
templateData.blockNavigation = {
js: linkMapper.assetPath(node, 'block-navigation.js')
};
templateData.prettify = {
js: linkMapper.assetPath(node, 'prettify.js'),
css: linkMapper.assetPath(node, 'prettify.css')
};
templateData.favicon = linkMapper.assetPath(node, 'favicon.png');
}
getTemplateData() {
return { datetime: this.date };
}
getWriter(context) {
if (!this.subdir) {
return context.writer;
}
return context.writer.writerForDir(this.subdir);
}
onStart(root, context) {
const assetHeaders = {
'.js': '/* eslint-disable */\n'
};
['.', 'vendor'].forEach(subdir => {
const writer = this.getWriter(context);
const srcDir = path.resolve(__dirname, 'assets', subdir);
fs.readdirSync(srcDir).forEach(f => {
const resolvedSource = path.resolve(srcDir, f);
const resolvedDestination = '.';
const stat = fs.statSync(resolvedSource);
let dest;
if (stat.isFile()) {
dest = resolvedDestination + '/' + f;
if (this.verbose) {
console.log('Write asset: ' + dest);
}
writer.copyFile(
resolvedSource,
dest,
assetHeaders[path.extname(f)]
);
}
});
});
}
onSummary(node, context) {
const linkMapper = this.linkMapper;
const templateData = this.getTemplateData();
const children = node.getChildren();
const skipEmpty = this.skipEmpty;
this.fillTemplate(node, templateData, context);
const cw = this.getWriter(context).writeFile(linkMapper.getPath(node));
cw.write(headerTemplate(templateData));
cw.write(summaryTableHeader);
children.forEach(child => {
const metrics = child.getCoverageSummary();
const isEmpty = metrics.isEmpty();
if (skipEmpty && isEmpty) {
return;
}
const reportClasses = isEmpty
? emptyClasses
: {
statements: context.classForPercent(
'statements',
metrics.statements.pct
),
lines: context.classForPercent(
'lines',
metrics.lines.pct
),
functions: context.classForPercent(
'functions',
metrics.functions.pct
),
branches: context.classForPercent(
'branches',
metrics.branches.pct
)
};
const data = {
metrics: isEmpty ? fixPct(metrics) : metrics,
reportClasses,
file: child.getRelativeName(),
output: linkMapper.relativePath(node, child)
};
cw.write(summaryLineTemplate(data) + '\n');
});
cw.write(summaryTableFooter);
cw.write(footerTemplate(templateData));
cw.close();
}
onDetail(node, context) {
const linkMapper = this.linkMapper;
const templateData = this.getTemplateData();
this.fillTemplate(node, templateData, context);
const cw = this.getWriter(context).writeFile(linkMapper.getPath(node));
cw.write(headerTemplate(templateData));
cw.write('<pre><table class="coverage">\n');
cw.write(detailTemplate(annotator(node.getFileCoverage(), context)));
cw.write('</table></pre>\n');
cw.write(footerTemplate(templateData));
cw.close();
}
}
module.exports = HtmlReport;

View file

@ -0,0 +1,114 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
function InsertionText(text, consumeBlanks) {
this.text = text;
this.origLength = text.length;
this.offsets = [];
this.consumeBlanks = consumeBlanks;
this.startPos = this.findFirstNonBlank();
this.endPos = this.findLastNonBlank();
}
const WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/;
InsertionText.prototype = {
findFirstNonBlank() {
let pos = -1;
const text = this.text;
const len = text.length;
let i;
for (i = 0; i < len; i += 1) {
if (!text.charAt(i).match(WHITE_RE)) {
pos = i;
break;
}
}
return pos;
},
findLastNonBlank() {
const text = this.text;
const len = text.length;
let pos = text.length + 1;
let i;
for (i = len - 1; i >= 0; i -= 1) {
if (!text.charAt(i).match(WHITE_RE)) {
pos = i;
break;
}
}
return pos;
},
originalLength() {
return this.origLength;
},
insertAt(col, str, insertBefore, consumeBlanks) {
consumeBlanks =
typeof consumeBlanks === 'undefined'
? this.consumeBlanks
: consumeBlanks;
col = col > this.originalLength() ? this.originalLength() : col;
col = col < 0 ? 0 : col;
if (consumeBlanks) {
if (col <= this.startPos) {
col = 0;
}
if (col > this.endPos) {
col = this.origLength;
}
}
const len = str.length;
const offset = this.findOffset(col, len, insertBefore);
const realPos = col + offset;
const text = this.text;
this.text = text.substring(0, realPos) + str + text.substring(realPos);
return this;
},
findOffset(pos, len, insertBefore) {
const offsets = this.offsets;
let offsetObj;
let cumulativeOffset = 0;
let i;
for (i = 0; i < offsets.length; i += 1) {
offsetObj = offsets[i];
if (
offsetObj.pos < pos ||
(offsetObj.pos === pos && !insertBefore)
) {
cumulativeOffset += offsetObj.len;
}
if (offsetObj.pos >= pos) {
break;
}
}
if (offsetObj && offsetObj.pos === pos) {
offsetObj.len += len;
} else {
offsets.splice(i, 0, { pos, len });
}
return cumulativeOffset;
},
wrap(startPos, startText, endPos, endText, consumeBlanks) {
this.insertAt(startPos, startText, true, consumeBlanks);
this.insertAt(endPos, endText, false, consumeBlanks);
return this;
},
wrapLine(startText, endText) {
this.wrap(0, startText, this.originalLength(), endText);
},
toString() {
return this.text;
}
};
module.exports = InsertionText;

View file

@ -0,0 +1,56 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
class JsonSummaryReport extends ReportBase {
constructor(opts) {
super();
this.file = opts.file || 'coverage-summary.json';
this.contentWriter = null;
this.first = true;
}
onStart(root, context) {
this.contentWriter = context.writer.writeFile(this.file);
this.contentWriter.write('{');
}
writeSummary(filePath, sc) {
const cw = this.contentWriter;
if (this.first) {
this.first = false;
} else {
cw.write(',');
}
cw.write(JSON.stringify(filePath));
cw.write(': ');
cw.write(JSON.stringify(sc));
cw.println('');
}
onSummary(node) {
if (!node.isRoot()) {
return;
}
this.writeSummary('total', node.getCoverageSummary());
}
onDetail(node) {
this.writeSummary(
node.getFileCoverage().path,
node.getCoverageSummary()
);
}
onEnd() {
const cw = this.contentWriter;
cw.println('}');
cw.close();
}
}
module.exports = JsonSummaryReport;

44
node_modules/istanbul-reports/lib/json/index.js generated vendored Normal file
View file

@ -0,0 +1,44 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
class JsonReport extends ReportBase {
constructor(opts) {
super();
this.file = opts.file || 'coverage-final.json';
this.first = true;
}
onStart(root, context) {
this.contentWriter = context.writer.writeFile(this.file);
this.contentWriter.write('{');
}
onDetail(node) {
const fc = node.getFileCoverage();
const key = fc.path;
const cw = this.contentWriter;
if (this.first) {
this.first = false;
} else {
cw.write(',');
}
cw.write(JSON.stringify(key));
cw.write(': ');
cw.write(JSON.stringify(fc));
cw.println('');
}
onEnd() {
const cw = this.contentWriter;
cw.println('}');
cw.close();
}
}
module.exports = JsonReport;

33
node_modules/istanbul-reports/lib/lcov/index.js generated vendored Normal file
View file

@ -0,0 +1,33 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const { ReportBase } = require('istanbul-lib-report');
const LcovOnlyReport = require('../lcovonly');
const HtmlReport = require('../html');
class LcovReport extends ReportBase {
constructor(opts) {
super();
this.lcov = new LcovOnlyReport({ file: 'lcov.info', ...opts });
this.html = new HtmlReport({ subdir: 'lcov-report' });
}
}
['Start', 'End', 'Summary', 'SummaryEnd', 'Detail'].forEach(what => {
const meth = 'on' + what;
LcovReport.prototype[meth] = function(...args) {
const lcov = this.lcov;
const html = this.html;
if (lcov[meth]) {
lcov[meth](...args);
}
if (html[meth]) {
html[meth](...args);
}
};
});
module.exports = LcovReport;

77
node_modules/istanbul-reports/lib/lcovonly/index.js generated vendored Normal file
View file

@ -0,0 +1,77 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
class LcovOnlyReport extends ReportBase {
constructor(opts) {
super();
opts = opts || {};
this.file = opts.file || 'lcov.info';
this.projectRoot = opts.projectRoot || process.cwd();
this.contentWriter = null;
}
onStart(root, context) {
this.contentWriter = context.writer.writeFile(this.file);
}
onDetail(node) {
const fc = node.getFileCoverage();
const writer = this.contentWriter;
const functions = fc.f;
const functionMap = fc.fnMap;
const lines = fc.getLineCoverage();
const branches = fc.b;
const branchMap = fc.branchMap;
const summary = node.getCoverageSummary();
const path = require('path');
writer.println('TN:');
const fileName = path.relative(this.projectRoot, fc.path);
writer.println('SF:' + fileName);
Object.values(functionMap).forEach(meta => {
// Some versions of the instrumenter in the wild populate 'loc'
// but not 'decl':
const decl = meta.decl || meta.loc;
writer.println('FN:' + [decl.start.line, meta.name].join(','));
});
writer.println('FNF:' + summary.functions.total);
writer.println('FNH:' + summary.functions.covered);
Object.entries(functionMap).forEach(([key, meta]) => {
const stats = functions[key];
writer.println('FNDA:' + [stats, meta.name].join(','));
});
Object.entries(lines).forEach(entry => {
writer.println('DA:' + entry.join(','));
});
writer.println('LF:' + summary.lines.total);
writer.println('LH:' + summary.lines.covered);
Object.entries(branches).forEach(([key, branchArray]) => {
const meta = branchMap[key];
if (meta) {
const { line } = meta.loc.start;
branchArray.forEach((b, i) => {
writer.println('BRDA:' + [line, key, i, b].join(','));
});
} else {
console.warn('Missing coverage entries in', fileName, key);
}
});
writer.println('BRF:' + summary.branches.total);
writer.println('BRH:' + summary.branches.covered);
writer.println('end_of_record');
}
onEnd() {
this.contentWriter.close();
}
}
module.exports = LcovOnlyReport;

10
node_modules/istanbul-reports/lib/none/index.js generated vendored Normal file
View file

@ -0,0 +1,10 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const { ReportBase } = require('istanbul-lib-report');
class NoneReport extends ReportBase {}
module.exports = NoneReport;

67
node_modules/istanbul-reports/lib/teamcity/index.js generated vendored Normal file
View file

@ -0,0 +1,67 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
class TeamcityReport extends ReportBase {
constructor(opts) {
super();
opts = opts || {};
this.file = opts.file || null;
this.blockName = opts.blockName || 'Code Coverage Summary';
}
onStart(node, context) {
const metrics = node.getCoverageSummary();
const cw = context.writer.writeFile(this.file);
cw.println('');
cw.println("##teamcity[blockOpened name='" + this.blockName + "']");
//Statements Covered
cw.println(
lineForKey(metrics.statements.covered, 'CodeCoverageAbsBCovered')
);
cw.println(
lineForKey(metrics.statements.total, 'CodeCoverageAbsBTotal')
);
//Branches Covered
cw.println(
lineForKey(metrics.branches.covered, 'CodeCoverageAbsRCovered')
);
cw.println(lineForKey(metrics.branches.total, 'CodeCoverageAbsRTotal'));
//Functions Covered
cw.println(
lineForKey(metrics.functions.covered, 'CodeCoverageAbsMCovered')
);
cw.println(
lineForKey(metrics.functions.total, 'CodeCoverageAbsMTotal')
);
//Lines Covered
cw.println(
lineForKey(metrics.lines.covered, 'CodeCoverageAbsLCovered')
);
cw.println(lineForKey(metrics.lines.total, 'CodeCoverageAbsLTotal'));
cw.println("##teamcity[blockClosed name='" + this.blockName + "']");
cw.close();
}
}
function lineForKey(value, teamcityVar) {
return (
"##teamcity[buildStatisticValue key='" +
teamcityVar +
"' value='" +
value +
"']"
);
}
module.exports = TeamcityReport;

17
node_modules/istanbul-reports/lib/text-lcov/index.js generated vendored Normal file
View file

@ -0,0 +1,17 @@
'use strict';
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const LcovOnly = require('../lcovonly');
class TextLcov extends LcovOnly {
constructor(opts) {
super({
...opts,
file: '-'
});
}
}
module.exports = TextLcov;

View file

@ -0,0 +1,62 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
class TextSummaryReport extends ReportBase {
constructor(opts) {
super();
opts = opts || {};
this.file = opts.file || null;
}
onStart(node, context) {
const summary = node.getCoverageSummary();
const cw = context.writer.writeFile(this.file);
const printLine = function(key) {
const str = lineForKey(summary, key);
const clazz = context.classForPercent(key, summary[key].pct);
cw.println(cw.colorize(str, clazz));
};
cw.println('');
cw.println(
'=============================== Coverage summary ==============================='
);
printLine('statements');
printLine('branches');
printLine('functions');
printLine('lines');
cw.println(
'================================================================================'
);
cw.close();
}
}
function lineForKey(summary, key) {
const metrics = summary[key];
key = key.substring(0, 1).toUpperCase() + key.substring(1);
if (key.length < 12) {
key += ' '.substring(0, 12 - key.length);
}
const result = [
key,
':',
metrics.pct + '%',
'(',
metrics.covered + '/' + metrics.total,
')'
].join(' ');
const skipped = metrics.skipped;
if (skipped > 0) {
return result + ', ' + skipped + ' ignored';
}
return result;
}
module.exports = TextSummaryReport;

298
node_modules/istanbul-reports/lib/text/index.js generated vendored Normal file
View file

@ -0,0 +1,298 @@
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE
file for terms.
*/
'use strict';
const { ReportBase } = require('istanbul-lib-report');
const NAME_COL = 4;
const PCT_COLS = 7;
const MISSING_COL = 17;
const TAB_SIZE = 1;
const DELIM = ' | ';
function padding(num, ch) {
let str = '';
let i;
ch = ch || ' ';
for (i = 0; i < num; i += 1) {
str += ch;
}
return str;
}
function fill(str, width, right, tabs) {
tabs = tabs || 0;
str = String(str);
const leadingSpaces = tabs * TAB_SIZE;
const remaining = width - leadingSpaces;
const leader = padding(leadingSpaces);
let fmtStr = '';
if (remaining > 0) {
const strlen = str.length;
let fillStr;
if (remaining >= strlen) {
fillStr = padding(remaining - strlen);
} else {
fillStr = '...';
const length = remaining - fillStr.length;
str = str.substring(strlen - length);
right = true;
}
fmtStr = right ? fillStr + str : str + fillStr;
}
return leader + fmtStr;
}
function formatName(name, maxCols, level) {
return fill(name, maxCols, false, level);
}
function formatPct(pct, width) {
return fill(pct, width || PCT_COLS, true, 0);
}
function nodeMissing(node) {
if (node.isSummary()) {
return '';
}
const metrics = node.getCoverageSummary();
const isEmpty = metrics.isEmpty();
const lines = isEmpty ? 0 : metrics.lines.pct;
let coveredLines;
const fileCoverage = node.getFileCoverage();
if (lines === 100) {
const branches = fileCoverage.getBranchCoverageByLine();
coveredLines = Object.entries(branches).map(([key, { coverage }]) => [
key,
coverage === 100
]);
} else {
coveredLines = Object.entries(fileCoverage.getLineCoverage());
}
let newRange = true;
const ranges = coveredLines
.reduce((acum, [line, hit]) => {
if (hit) newRange = true;
else {
line = parseInt(line);
if (newRange) {
acum.push([line]);
newRange = false;
} else acum[acum.length - 1][1] = line;
}
return acum;
}, [])
.map(range => {
const { length } = range;
if (length === 1) return range[0];
return `${range[0]}-${range[1]}`;
});
return [].concat(...ranges).join(',');
}
function nodeName(node) {
return node.getRelativeName() || 'All files';
}
function depthFor(node) {
let ret = 0;
node = node.getParent();
while (node) {
ret += 1;
node = node.getParent();
}
return ret;
}
function nullDepthFor() {
return 0;
}
function findWidth(node, context, nodeExtractor, depthFor = nullDepthFor) {
let last = 0;
function compareWidth(node) {
last = Math.max(
last,
TAB_SIZE * depthFor(node) + nodeExtractor(node).length
);
}
const visitor = {
onSummary: compareWidth,
onDetail: compareWidth
};
node.visit(context.getVisitor(visitor));
return last;
}
function makeLine(nameWidth, missingWidth) {
const name = padding(nameWidth, '-');
const pct = padding(PCT_COLS, '-');
const elements = [];
elements.push(name);
elements.push(pct);
elements.push(padding(PCT_COLS + 1, '-'));
elements.push(pct);
elements.push(pct);
elements.push(padding(missingWidth, '-'));
return elements.join(DELIM.replace(/ /g, '-')) + '-';
}
function tableHeader(maxNameCols, missingWidth) {
const elements = [];
elements.push(formatName('File', maxNameCols, 0));
elements.push(formatPct('% Stmts'));
elements.push(formatPct('% Branch', PCT_COLS + 1));
elements.push(formatPct('% Funcs'));
elements.push(formatPct('% Lines'));
elements.push(formatName('Uncovered Line #s', missingWidth));
return elements.join(DELIM) + ' ';
}
function isFull(metrics) {
return (
metrics.statements.pct === 100 &&
metrics.branches.pct === 100 &&
metrics.functions.pct === 100 &&
metrics.lines.pct === 100
);
}
function tableRow(
node,
context,
colorizer,
maxNameCols,
level,
skipEmpty,
skipFull,
missingWidth
) {
const name = nodeName(node);
const metrics = node.getCoverageSummary();
const isEmpty = metrics.isEmpty();
if (skipEmpty && isEmpty) {
return '';
}
if (skipFull && isFull(metrics)) {
return '';
}
const mm = {
statements: isEmpty ? 0 : metrics.statements.pct,
branches: isEmpty ? 0 : metrics.branches.pct,
functions: isEmpty ? 0 : metrics.functions.pct,
lines: isEmpty ? 0 : metrics.lines.pct
};
const colorize = isEmpty
? function(str) {
return str;
}
: function(str, key) {
return colorizer(str, context.classForPercent(key, mm[key]));
};
const elements = [];
elements.push(colorize(formatName(name, maxNameCols, level), 'statements'));
elements.push(colorize(formatPct(mm.statements), 'statements'));
elements.push(colorize(formatPct(mm.branches, PCT_COLS + 1), 'branches'));
elements.push(colorize(formatPct(mm.functions), 'functions'));
elements.push(colorize(formatPct(mm.lines), 'lines'));
elements.push(
colorizer(
formatName(nodeMissing(node), missingWidth),
mm.lines === 100 ? 'medium' : 'low'
)
);
return elements.join(DELIM) + ' ';
}
class TextReport extends ReportBase {
constructor(opts) {
super(opts);
opts = opts || {};
const { maxCols } = opts;
this.file = opts.file || null;
this.maxCols = maxCols != null ? maxCols : process.stdout.columns || 80;
this.cw = null;
this.skipEmpty = opts.skipEmpty;
this.skipFull = opts.skipFull;
}
onStart(root, context) {
this.cw = context.writer.writeFile(this.file);
this.nameWidth = Math.max(
NAME_COL,
findWidth(root, context, nodeName, depthFor)
);
this.missingWidth = Math.max(
MISSING_COL,
findWidth(root, context, nodeMissing)
);
if (this.maxCols > 0) {
const pct_cols = DELIM.length + 4 * (PCT_COLS + DELIM.length) + 2;
const maxRemaining = this.maxCols - (pct_cols + MISSING_COL);
if (this.nameWidth > maxRemaining) {
this.nameWidth = maxRemaining;
this.missingWidth = MISSING_COL;
} else if (this.nameWidth < maxRemaining) {
const maxRemaining = this.maxCols - (this.nameWidth + pct_cols);
if (this.missingWidth > maxRemaining) {
this.missingWidth = maxRemaining;
}
}
}
const line = makeLine(this.nameWidth, this.missingWidth);
this.cw.println(line);
this.cw.println(tableHeader(this.nameWidth, this.missingWidth));
this.cw.println(line);
}
onSummary(node, context) {
const nodeDepth = depthFor(node);
const row = tableRow(
node,
context,
this.cw.colorize.bind(this.cw),
this.nameWidth,
nodeDepth,
this.skipEmpty,
this.skipFull,
this.missingWidth
);
if (row) {
this.cw.println(row);
}
}
onDetail(node, context) {
return this.onSummary(node, context);
}
onEnd() {
this.cw.println(makeLine(this.nameWidth, this.missingWidth));
this.cw.close();
}
}
module.exports = TextReport;