monocart-coverage-reports
Advanced tools
Comparing version 2.9.3 to 2.10.0
@@ -22,3 +22,3 @@ /** | ||
const { decode } = require('@jridgewell/sourcemap-codec'); | ||
const { minimatch } = require('minimatch'); | ||
const { minimatch } = require('../packages/monocart-coverage-vendor.js'); | ||
@@ -286,4 +286,4 @@ const InfoBranch = require('./info-branch.js'); | ||
data.functions = functions.map((info) => { | ||
return info.getRange(); | ||
data.functions = functions.map((info, i) => { | ||
return info.getRange(i); | ||
}); | ||
@@ -560,3 +560,3 @@ sortRanges(data.functions); | ||
const result = findOriginalRange(start, end, state, originalStateMap); | ||
const result = findOriginalRange(start, end, state, originalStateMap, true); | ||
if (result.error) { | ||
@@ -577,2 +577,6 @@ logMappingErrors('function', result); | ||
if (result.name) { | ||
originalFunction.functionName = result.name; | ||
} | ||
// body start and end | ||
@@ -870,3 +874,3 @@ updateFunctionBodyRange(start, end, bodyStart, bodyEnd, originalFunction); | ||
// const NAMES_INDEX = 4; | ||
const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment; | ||
const [generatedColumn, sourceIndex, originalLine, originalColumn, nameIndex] = segment; | ||
// the segment length could be 1, 4 or 5 | ||
@@ -891,3 +895,4 @@ | ||
originalLine, | ||
originalColumn | ||
originalColumn, | ||
nameIndex | ||
}; | ||
@@ -1111,2 +1116,4 @@ | ||
state.fileUrls = fileUrls; | ||
// for function names | ||
state.sourceMapNames = sourceMap.names || []; | ||
@@ -1506,2 +1513,10 @@ // =============================================== | ||
// sort v8DataList (files) | ||
v8DataList.sort((a, b) => { | ||
if (a.sourcePath > b.sourcePath) { | ||
return 1; | ||
} | ||
return -1; | ||
}); | ||
return { | ||
@@ -1508,0 +1523,0 @@ v8DataList, |
@@ -1,2 +0,2 @@ | ||
const diffSequence = require('diff-sequences').default; | ||
const { diffSequence } = require('../packages/monocart-coverage-vendor.js'); | ||
const Util = require('../utils/util.js'); | ||
@@ -537,4 +537,9 @@ const EC = Util.EC; | ||
// ======================================================================================================== | ||
const getFunctionName = (mp, state, checkName) => { | ||
if (checkName && typeof mp.nameIndex !== 'undefined') { | ||
return state.sourceMapNames[mp.nameIndex]; | ||
} | ||
}; | ||
const getFixedOriginalStart = (start, mappings, state, cache) => { | ||
const getFixedOriginalStart = (start, mappings, state, cache, checkName) => { | ||
@@ -547,3 +552,4 @@ const [m1, m2] = mappings; | ||
return { | ||
originalStart: m2.originalOffset | ||
originalStart: m2.originalOffset, | ||
originalName: getFunctionName(m2, state, checkName) | ||
}; | ||
@@ -579,3 +585,4 @@ } | ||
return { | ||
originalStart: originalOffset + originalPos | ||
originalStart: originalOffset + originalPos, | ||
originalName: getFunctionName(m1, state, checkName) | ||
}; | ||
@@ -641,3 +648,3 @@ }; | ||
const getOriginalStartPosition = (cache, state) => { | ||
const getOriginalStartPosition = (cache, state, checkName) => { | ||
@@ -647,3 +654,3 @@ const { start, startMappings } = cache; | ||
if (Array.isArray(startMappings)) { | ||
return getFixedOriginalStart(start, startMappings, state, cache); | ||
return getFixedOriginalStart(start, startMappings, state, cache, checkName); | ||
} | ||
@@ -653,3 +660,4 @@ | ||
return { | ||
originalStart: startMappings.originalOffset | ||
originalStart: startMappings.originalOffset, | ||
originalName: getFunctionName(startMappings, state, checkName) | ||
}; | ||
@@ -881,3 +889,3 @@ }; | ||
const findOriginalRange = (start, end, state, originalMap) => { | ||
const findOriginalRange = (start, end, state, originalMap, checkName) => { | ||
@@ -911,4 +919,4 @@ const { sourcePath, rangeCache } = state; | ||
const originalStartResult = getOriginalStartPosition(cache, state); | ||
const { originalStart } = originalStartResult; | ||
const originalStartResult = getOriginalStartPosition(cache, state, checkName); | ||
const { originalStart, originalName } = originalStartResult; | ||
// could be used for end | ||
@@ -939,2 +947,3 @@ cache.originalStart = originalStart; | ||
end: originalEnd, | ||
name: originalName, | ||
originalState | ||
@@ -941,0 +950,0 @@ }; |
const { decode } = require('@jridgewell/sourcemap-codec'); | ||
const COLUMN = 0; | ||
const SOURCES_INDEX = 1; | ||
const SOURCE_LINE = 2; | ||
const SOURCE_COLUMN = 3; | ||
const NAMES_INDEX = 4; | ||
function getLine(arr, index) { | ||
@@ -10,4 +16,17 @@ for (let i = arr.length; i <= index; i++) { | ||
function addMappings(options, sourcesOffset) { | ||
function getMapping(seg, column, sourcesOffset, namesOffset) { | ||
const sourcesIndex = sourcesOffset + seg[SOURCES_INDEX]; | ||
const sourceLine = seg[SOURCE_LINE]; | ||
const sourceColumn = seg[SOURCE_COLUMN]; | ||
if (seg.length === 4) { | ||
return [column, sourcesIndex, sourceLine, sourceColumn]; | ||
} | ||
return [column, sourcesIndex, sourceLine, sourceColumn, namesOffset + seg[NAMES_INDEX]]; | ||
} | ||
function addMappings(options, sourcesOffset, namesOffset) { | ||
const { | ||
@@ -22,6 +41,2 @@ input, | ||
const decoded = decode(input.mappings); | ||
const COLUMN = 0; | ||
const SOURCES_INDEX = 1; | ||
const SOURCE_LINE = 2; | ||
const SOURCE_COLUMN = 3; | ||
@@ -52,6 +67,3 @@ for (let i = 0; i < decoded.length; i++) { | ||
const sourcesIndex = sourcesOffset + seg[SOURCES_INDEX]; | ||
const sourceLine = seg[SOURCE_LINE]; | ||
const sourceColumn = seg[SOURCE_COLUMN]; | ||
out.push([column, sourcesIndex, sourceLine, sourceColumn]); | ||
out.push(getMapping(seg, column, sourcesOffset, namesOffset)); | ||
} | ||
@@ -71,3 +83,5 @@ } | ||
const sourcesOffset = options.sources.length; | ||
const namesOffset = options.names.length; | ||
// sources and sourcesContent | ||
if (!input.sourcesContent) { | ||
@@ -81,4 +95,11 @@ input.sourcesContent = []; | ||
addMappings(options, sourcesOffset); | ||
// names | ||
if (input.names) { | ||
input.names.forEach((n) => { | ||
options.names.push(n); | ||
}); | ||
} | ||
addMappings(options, sourcesOffset, namesOffset); | ||
} | ||
@@ -135,3 +156,2 @@ | ||
const names = []; | ||
const ignoreList = []; | ||
@@ -153,3 +173,2 @@ const lineOffset = 0; | ||
names, | ||
ignoreList, | ||
@@ -164,2 +183,3 @@ lineOffset, | ||
indexedMap.sourcesContent = sourcesContent; | ||
indexedMap.names = names; | ||
indexedMap.decodedMappings = decodedMappings; | ||
@@ -166,0 +186,0 @@ |
@@ -72,14 +72,75 @@ const Util = require('../utils/util.js'); | ||
// both v8 or c8 | ||
const hasIgnoreKey = (content) => { | ||
const v8Key = 'v8 ignore'; | ||
if (content.startsWith(v8Key)) { | ||
return v8Key.length; | ||
const getStartEndNextInfo = (content) => { | ||
content = content.trim(); | ||
const start = 'start'; | ||
const stop = 'stop'; | ||
const next = 'next'; | ||
if (content.startsWith(start)) { | ||
return { | ||
type: 'range', | ||
value: stop | ||
}; | ||
} | ||
const c8Key = 'c8 ignore'; | ||
if (content.startsWith(c8Key)) { | ||
return c8Key.length; | ||
if (content.startsWith(stop)) { | ||
return { | ||
type: 'range', | ||
value: stop | ||
}; | ||
} | ||
// istanbul ignore has different rules, can not support it | ||
if (content.startsWith(next)) { | ||
return { | ||
type: 'next', | ||
value: content.slice(next.length) | ||
}; | ||
} | ||
}; | ||
const getDisableEnableNextInfo = (content) => { | ||
content = content.trim(); | ||
const start = 'disable'; | ||
const stop = 'enable'; | ||
const next = 'ignore next'; | ||
if (content.startsWith(start)) { | ||
return { | ||
type: 'range', | ||
value: stop | ||
}; | ||
} | ||
if (content.startsWith(stop)) { | ||
return { | ||
type: 'range', | ||
value: stop | ||
}; | ||
} | ||
if (content.startsWith(next)) { | ||
return { | ||
type: 'next', | ||
value: content.slice(next.length) | ||
}; | ||
} | ||
}; | ||
const getIgnoreInfo = (content) => { | ||
content = content.trim(); | ||
const v8_ignore = 'v8 ignore'; | ||
if (content.startsWith(v8_ignore)) { | ||
return getStartEndNextInfo(content.slice(v8_ignore.length)); | ||
} | ||
const c8_ignore = 'c8 ignore'; | ||
if (content.startsWith(c8_ignore)) { | ||
return getStartEndNextInfo(content.slice(c8_ignore.length)); | ||
} | ||
const node_coverage = 'node:coverage'; | ||
if (content.startsWith(node_coverage)) { | ||
return getDisableEnableNextInfo(content.slice(node_coverage.length)); | ||
} | ||
}; | ||
const getIgnoredRanges = (locator, options) => { | ||
@@ -105,16 +166,15 @@ if (!options.v8Ignore) { | ||
} = item; | ||
let content = block ? text.slice(2, -2) : text.slice(2); | ||
content = content.trim(); | ||
const ignoreKey = hasIgnoreKey(content); | ||
if (!ignoreKey) { | ||
const content = block ? text.slice(2, -2) : text.slice(2); | ||
const ignoreInfo = getIgnoreInfo(content); | ||
if (!ignoreInfo) { | ||
return; | ||
} | ||
content = content.slice(ignoreKey).trim(); | ||
const { type, value } = ignoreInfo; | ||
if (ignoreStart) { | ||
// v-8 ignore stop | ||
if (content === 'stop') { | ||
ignoreStart.end = extendEnd(end, source, maxLength); | ||
if (type === 'range' && value === ignoreStart.value) { | ||
ignoreStart.ignoreData.end = extendEnd(end, source, maxLength); | ||
ignoreStart = null; | ||
@@ -126,18 +186,20 @@ } | ||
// v-8 ignore start | ||
if (content === 'start') { | ||
if (type === 'range') { | ||
// add first for sort by start | ||
ignoreStart = { | ||
type: 'start-stop', | ||
const ignoreData = { | ||
type, | ||
start: extendStart(start, source), | ||
end: start | ||
}; | ||
list.push(ignoreStart); | ||
list.push(ignoreData); | ||
ignoreStart = { | ||
ignoreData, | ||
value | ||
}; | ||
return; | ||
} | ||
// v-8 ignore next N | ||
const nextKey = 'next'; | ||
if (content.startsWith(nextKey)) { | ||
content = content.slice(nextKey.length).trim(); | ||
addNextIgnore(list, content, item, locator); | ||
// next N | ||
if (type === 'next') { | ||
addNextIgnore(list, value.trim(), item, locator); | ||
} | ||
@@ -144,0 +206,0 @@ |
@@ -19,4 +19,9 @@ const Util = require('../utils/util.js'); | ||
getRange() { | ||
getName(index) { | ||
return this.functionName || `(anonymous_${index})`; | ||
} | ||
getRange(index) { | ||
const range = { | ||
name: this.getName(index), | ||
start: this.start, | ||
@@ -55,6 +60,4 @@ end: this.end, | ||
const functionName = this.functionName || `(anonymous_${index})`; | ||
return { | ||
name: functionName, | ||
name: this.getName(index), | ||
decl: decl, | ||
@@ -61,0 +64,0 @@ loc: loc, |
const fs = require('fs'); | ||
const path = require('path'); | ||
const CG = require('console-grid'); | ||
const EC = require('eight-colors'); | ||
const { pathToFileURL, fileURLToPath } = require('url'); | ||
const EC = require('eight-colors'); | ||
const { minimatch } = require('./packages/monocart-coverage-vendor.js'); | ||
const Util = require('./utils/util.js'); | ||
const { convertV8List } = require('./converter/converter.js'); | ||
const { resolveSourceMap } = require('./converter/collect-source-maps.js'); | ||
// ======================================================================================================== | ||
// built-in reports | ||
// istanbul | ||
const { | ||
@@ -12,28 +20,60 @@ initIstanbulData, mergeIstanbulCoverage, saveIstanbulReports | ||
// v8 | ||
const { mergeV8Coverage, saveV8Report } = require('./v8/v8.js'); | ||
const { convertV8List } = require('./converter/converter.js'); | ||
const { resolveSourceMap } = require('./converter/collect-source-maps.js'); | ||
// both | ||
const { codecovReport } = require('./reports/codecov.js'); | ||
const { codacyReport } = require('./reports/codacy.js'); | ||
const { minimatch } = require('minimatch'); | ||
const { getGroupedRows } = require('./utils/snapshot.js'); | ||
const generateMarkdownGrid = require('./utils/markdown.js'); | ||
const { consoleDetailsReport } = require('./reports/console-details.js'); | ||
const { consoleSummaryReport } = require('./reports/console-summary.js'); | ||
// ======================================================================================================== | ||
const { markdownDetailsReport } = require('./reports/markdown-details.js'); | ||
const { markdownSummaryReport } = require('./reports/markdown-summary.js'); | ||
// maybe v8 or to istanbul reports | ||
const generateV8ListReports = async (v8list, coverageData, fileSources, options) => { | ||
let istanbulReportPath; | ||
// v8 to istanbul reports | ||
if (options.reportGroup.istanbul) { | ||
const istanbulCoverageResults = await saveIstanbulReports(coverageData, fileSources, options); | ||
istanbulReportPath = istanbulCoverageResults.reportPath; | ||
} | ||
const { rawReport } = require('./reports/raw.js'); | ||
// v8 reports and v8 coverage results | ||
// could be no v8 or v8-json, but requires v8 coverage results | ||
const v8CoverageResults = await saveV8Report(v8list, options, istanbulReportPath); | ||
return v8CoverageResults; | ||
const allBuiltInReports = { | ||
// v8 | ||
'v8': 'v8', | ||
'v8-json': 'v8', | ||
// istanbul | ||
'clover': 'istanbul', | ||
'cobertura': 'istanbul', | ||
'html': 'istanbul', | ||
'html-spa': 'istanbul', | ||
'json': 'istanbul', | ||
'json-summary': 'istanbul', | ||
'lcov': 'istanbul', | ||
'lcovonly': 'istanbul', | ||
'none': 'istanbul', | ||
'teamcity': 'istanbul', | ||
'text': 'istanbul', | ||
'text-lcov': 'istanbul', | ||
'text-summary': 'istanbul', | ||
// both | ||
'codecov': 'both', | ||
'codacy': 'both', | ||
'console-details': 'both', | ||
'console-summary': 'both', | ||
'markdown-details': 'both', | ||
'markdown-summary': 'both', | ||
'raw': 'both' | ||
}; | ||
const bothBuiltInReports = { | ||
'codecov': codecovReport, | ||
'codacy': codacyReport, | ||
'console-details': consoleDetailsReport, | ||
'console-summary': consoleSummaryReport, | ||
'markdown-details': markdownDetailsReport, | ||
'markdown-summary': markdownSummaryReport, | ||
'raw': rawReport | ||
}; | ||
// ======================================================================================================== | ||
@@ -73,38 +113,8 @@ | ||
const allBuildInReports = { | ||
// v8 | ||
'v8': 'v8', | ||
'v8-json': 'v8', | ||
// istanbul | ||
'clover': 'istanbul', | ||
'cobertura': 'istanbul', | ||
'html': 'istanbul', | ||
'html-spa': 'istanbul', | ||
'json': 'istanbul', | ||
'json-summary': 'istanbul', | ||
'lcov': 'istanbul', | ||
'lcovonly': 'istanbul', | ||
'none': 'istanbul', | ||
'teamcity': 'istanbul', | ||
'text': 'istanbul', | ||
'text-lcov': 'istanbul', | ||
'text-summary': 'istanbul', | ||
// both | ||
'codecov': 'both', | ||
'codacy': 'both', | ||
'console-details': 'both', | ||
'console-summary': 'both', | ||
'markdown-details': 'both', | ||
'markdown-summary': 'both', | ||
'raw': 'both' | ||
}; | ||
// group v8 and istanbul | ||
const reportGroup = {}; | ||
const groupMap = new Map(); | ||
Object.keys(reportMap).forEach((k) => { | ||
const options = reportMap[k]; | ||
let type = allBuildInReports[k]; | ||
let type = allBuiltInReports[k]; | ||
if (!type) { | ||
@@ -115,9 +125,9 @@ // for custom reporter | ||
let group = reportGroup[type]; | ||
let group = groupMap.get(type); | ||
if (!group) { | ||
group = {}; | ||
reportGroup[type] = group; | ||
group = new Map(); | ||
groupMap.set(type, group); | ||
} | ||
group[k] = options; | ||
group.set(k, options); | ||
@@ -127,9 +137,9 @@ }); | ||
// requires a default istanbul report if data is istanbul | ||
if (dataType === 'istanbul' && !reportGroup.istanbul) { | ||
reportGroup.istanbul = { | ||
html: {} | ||
}; | ||
if (dataType === 'istanbul' && !groupMap.has('istanbul')) { | ||
const istanbulGroup = new Map(); | ||
istanbulGroup.set('html', {}); | ||
groupMap.set('istanbul', istanbulGroup); | ||
} | ||
return reportGroup; | ||
return groupMap; | ||
}; | ||
@@ -139,402 +149,17 @@ | ||
const nFormatter = (v) => { | ||
if (typeof v === 'number') { | ||
return Util.NF(v); | ||
// maybe v8 or to istanbul reports | ||
const generateV8ListReports = async (v8list, coverageData, fileSources, options) => { | ||
let istanbulReportPath; | ||
// v8 to istanbul reports | ||
if (options.reportGroup.has('istanbul')) { | ||
const istanbulCoverageResults = await saveIstanbulReports(coverageData, fileSources, options); | ||
istanbulReportPath = istanbulCoverageResults.reportPath; | ||
} | ||
return v; | ||
}; | ||
const getRowData = (rowName, summary, metrics, color) => { | ||
const summaryRow = {}; | ||
let lowest = { | ||
pct: 100, | ||
status: 'high' | ||
}; | ||
metrics.map((k) => { | ||
const s = summary[k]; | ||
if (!s) { | ||
return; | ||
} | ||
const percent = s.pct; | ||
if (typeof percent !== 'number') { | ||
return; | ||
} | ||
summaryRow[k] = Util.getColorStrByStatus(Util.PSF(percent, 100, 2), s.status, color); | ||
if (percent < lowest.pct) { | ||
lowest = s; | ||
} | ||
}); | ||
summaryRow.nameStatus = lowest.status; | ||
summaryRow.name = rowName; | ||
return summaryRow; | ||
// v8 reports and v8 coverage results | ||
// could be no v8 or v8-json, but requires v8 coverage results | ||
const v8CoverageResults = await saveV8Report(v8list, options, istanbulReportPath); | ||
return v8CoverageResults; | ||
}; | ||
const getDetailsRows = (files, metrics, cdOptions, color) => { | ||
const skipPercent = cdOptions.skipPercent; | ||
if (typeof skipPercent === 'number' && skipPercent > 0) { | ||
files = files.filter((file) => { | ||
const { summary } = file; | ||
for (const k of metrics) { | ||
const percent = summary[k].pct; | ||
if (typeof percent === 'number' && percent < skipPercent) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
} | ||
const flatRows = []; | ||
files.forEach((file) => { | ||
// do NOT add debug file | ||
if (file.debug) { | ||
return; | ||
} | ||
const { sourcePath, summary } = file; | ||
const fileRow = getRowData(sourcePath, summary, metrics, color); | ||
fileRow.uncoveredLines = Util.getUncoveredLines(file.data.lines, color); | ||
flatRows.push(fileRow); | ||
}); | ||
return getGroupedRows(flatRows); | ||
}; | ||
const handleCodecovReport = async (reportData, reportOptions, options) => { | ||
const codecovOptions = { | ||
outputFile: 'codecov.json', | ||
... reportOptions | ||
}; | ||
const jsonPath = path.resolve(options.outputDir, codecovOptions.outputFile); | ||
// https://docs.codecov.com/docs/codecov-custom-coverage-format | ||
const coverage = {}; | ||
reportData.files.forEach((item) => { | ||
const { sourcePath, data } = item; | ||
coverage[sourcePath] = data.lines; | ||
}); | ||
const codecovData = { | ||
coverage | ||
}; | ||
await Util.writeFile(jsonPath, JSON.stringify(codecovData)); | ||
return Util.relativePath(jsonPath); | ||
}; | ||
const handleCodacyReport = async (reportData, reportOptions, options) => { | ||
const codacyOptions = { | ||
outputFile: 'codacy.json', | ||
... reportOptions | ||
}; | ||
const jsonPath = path.resolve(options.outputDir, codacyOptions.outputFile); | ||
// https://api.codacy.com/swagger#tocscoveragereport | ||
const fileReports = []; | ||
reportData.files.forEach((item) => { | ||
const { sourcePath, data } = item; | ||
const coverage = {}; | ||
for (const [key, value] of Object.entries(data.lines)) { | ||
if (typeof value === 'number') { | ||
coverage[key] = value; | ||
} else { | ||
// partial coverage not supported? | ||
coverage[key] = 0; | ||
} | ||
} | ||
fileReports.push({ | ||
filename: sourcePath, | ||
coverage | ||
}); | ||
}); | ||
const codacyData = { | ||
fileReports | ||
}; | ||
await Util.writeFile(jsonPath, JSON.stringify(codacyData)); | ||
return Util.relativePath(jsonPath); | ||
}; | ||
const handleConsoleDetailsReport = (reportData, reportOptions, options) => { | ||
const cdOptions = { | ||
maxCols: 50, | ||
skipPercent: 0, | ||
metrics: [], | ||
... reportOptions | ||
}; | ||
const { | ||
type, name, summary, files | ||
} = reportData; | ||
if (name) { | ||
Util.logInfo(EC.cyan(name)); | ||
} | ||
const color = 'ansicode'; | ||
const metrics = Util.getMetrics(cdOptions.metrics, type); | ||
const rows = getDetailsRows(files, metrics, cdOptions, color); | ||
const summaryRow = getRowData('Summary', summary, metrics, color); | ||
if (summaryRow.nameStatus) { | ||
summaryRow.name = Util.getColorStrByStatus(summaryRow.name, summaryRow.nameStatus, color); | ||
} | ||
// no rows if skipped all by skipPercent | ||
if (rows.length) { | ||
rows.push({ | ||
innerBorder: true | ||
}); | ||
} | ||
rows.push(summaryRow); | ||
const columns = [{ | ||
id: 'name', | ||
name: 'Name' | ||
}, ... metrics.map((m) => { | ||
return { | ||
id: m, | ||
name: Util.capitalizeFirstLetter(m), | ||
align: 'right' | ||
}; | ||
}), { | ||
id: 'uncoveredLines', | ||
name: 'Uncovered Lines' | ||
}]; | ||
return CG({ | ||
options: { | ||
silent: cdOptions.silent, | ||
nullPlaceholder: '', | ||
defaultMaxWidth: cdOptions.maxCols | ||
}, | ||
columns, | ||
rows | ||
}); | ||
}; | ||
const getSummaryColumns = (color) => { | ||
const columns = [{ | ||
id: 'name', | ||
name: 'Name' | ||
}, { | ||
id: 'pct', | ||
name: 'Coverage %', | ||
align: 'right', | ||
formatter: (v, row, column) => { | ||
if (typeof v === 'number') { | ||
return Util.getColorStrByStatus(Util.PSF(v, 100, 2), row.status, color); | ||
} | ||
return v; | ||
} | ||
}, { | ||
id: 'covered', | ||
name: 'Covered', | ||
align: 'right', | ||
formatter: nFormatter | ||
}, { | ||
id: 'uncovered', | ||
name: 'Uncovered', | ||
align: 'right', | ||
formatter: nFormatter | ||
}, { | ||
id: 'total', | ||
name: 'Total', | ||
align: 'right', | ||
formatter: nFormatter | ||
}]; | ||
return columns; | ||
}; | ||
const handleConsoleSummaryReport = (reportData, reportOptions, options) => { | ||
const csOptions = { | ||
metrics: [], | ||
... reportOptions | ||
}; | ||
const { | ||
summary, name, type | ||
} = reportData; | ||
if (name) { | ||
Util.logInfo(EC.cyan(name)); | ||
} | ||
const metrics = Util.getMetrics(csOptions.metrics, type); | ||
const rows = metrics.map((k) => { | ||
return { | ||
... summary[k], | ||
name: Util.capitalizeFirstLetter(k) | ||
}; | ||
}); | ||
const columns = getSummaryColumns('ansicode'); | ||
CG({ | ||
columns, | ||
rows | ||
}); | ||
}; | ||
const handleMarkdownDetailsReport = async (reportData, reportOptions, options) => { | ||
const mdOptions = { | ||
baseUrl: '', | ||
// unicode, html, or empty for no color | ||
color: 'unicode', | ||
skipPercent: 0, | ||
metrics: [], | ||
outputFile: 'coverage-details.md', | ||
... reportOptions | ||
}; | ||
const color = Util.normalizeColorType(mdOptions.color); | ||
const baseUrl = mdOptions.baseUrl; | ||
const mdPath = path.resolve(options.outputDir, mdOptions.outputFile); | ||
const metrics = Util.getMetrics(mdOptions.metrics, reportData.type); | ||
let files = reportData.files; | ||
const skipPercent = mdOptions.skipPercent; | ||
if (typeof skipPercent === 'number' && skipPercent > 0) { | ||
files = files.filter((file) => { | ||
const { summary } = file; | ||
for (const k of metrics) { | ||
const percent = summary[k].pct; | ||
if (typeof percent === 'number' && percent < skipPercent) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
} | ||
const rows = []; | ||
files.forEach((file) => { | ||
// do NOT add debug file | ||
if (file.debug) { | ||
return; | ||
} | ||
const { sourcePath, summary } = file; | ||
const fileRow = getRowData(sourcePath, summary, metrics, color); | ||
if (fileRow.nameStatus) { | ||
const nameColor = baseUrl && color === 'tex' ? '' : color; | ||
fileRow.name = Util.getColorStrByStatus(fileRow.name, fileRow.nameStatus, nameColor); | ||
} | ||
if (baseUrl) { | ||
fileRow.name = `[${fileRow.name}](${baseUrl + sourcePath})`; | ||
} | ||
fileRow.uncoveredLines = Util.getUncoveredLines(file.data.lines, color); | ||
rows.push(fileRow); | ||
}); | ||
const summaryRow = getRowData('Summary', reportData.summary, metrics, color); | ||
if (summaryRow.nameStatus) { | ||
summaryRow.name = Util.getColorStrByStatus(summaryRow.name, summaryRow.nameStatus, color); | ||
} | ||
rows.push(summaryRow); | ||
const columns = [{ | ||
id: 'name', | ||
name: 'Name' | ||
}, ... metrics.map((m) => { | ||
return { | ||
id: m, | ||
name: Util.capitalizeFirstLetter(m), | ||
align: 'right' | ||
}; | ||
}), { | ||
id: 'uncoveredLines', | ||
name: 'Uncovered Lines' | ||
}]; | ||
const markdownGrid = generateMarkdownGrid({ | ||
options: { | ||
name: reportData.name | ||
}, | ||
columns, | ||
rows | ||
}); | ||
await Util.writeFile(mdPath, markdownGrid); | ||
return Util.relativePath(mdPath); | ||
}; | ||
const handleMarkdownSummaryReport = async (reportData, reportOptions, options) => { | ||
const msOptions = { | ||
// unicode, html, or empty for no color | ||
color: 'unicode', | ||
metrics: [], | ||
outputFile: 'coverage-summary.md', | ||
... reportOptions | ||
}; | ||
const color = Util.normalizeColorType(msOptions.color); | ||
const mdPath = path.resolve(options.outputDir, msOptions.outputFile); | ||
const metrics = Util.getMetrics(msOptions.metrics, reportData.type); | ||
const rows = metrics.map((k) => { | ||
return { | ||
... reportData.summary[k], | ||
name: Util.capitalizeFirstLetter(k) | ||
}; | ||
}); | ||
const columns = getSummaryColumns(color); | ||
const markdownGrid = generateMarkdownGrid({ | ||
options: { | ||
name: reportData.name | ||
}, | ||
columns, | ||
rows | ||
}); | ||
await Util.writeFile(mdPath, markdownGrid); | ||
return Util.relativePath(mdPath); | ||
}; | ||
const handleRawReport = (reportData, reportOptions, options) => { | ||
const rawOptions = { | ||
outputDir: 'raw', | ||
... reportOptions | ||
}; | ||
const cacheDir = options.cacheDir; | ||
const rawDir = path.resolve(options.outputDir, rawOptions.outputDir); | ||
// console.log(rawDir, cacheDir); | ||
if (fs.existsSync(rawDir)) { | ||
Util.logError(`Failed to save raw report because the dir already exists: ${Util.relativePath(rawDir)}`); | ||
return; | ||
} | ||
const rawParent = path.dirname(rawDir); | ||
if (!fs.existsSync(rawParent)) { | ||
fs.mkdirSync(rawParent, { | ||
recursive: true | ||
}); | ||
} | ||
// just rename the cache folder name | ||
fs.renameSync(cacheDir, rawDir); | ||
}; | ||
// ======================================================================================================== | ||
const getCoverageResults = async (dataList, sourceCache, options) => { | ||
@@ -583,21 +208,9 @@ // get first and check v8list or istanbul data | ||
const buildInBothReports = { | ||
'codecov': handleCodecovReport, | ||
'codacy': handleCodacyReport, | ||
'console-details': handleConsoleDetailsReport, | ||
'console-summary': handleConsoleSummaryReport, | ||
'markdown-details': handleMarkdownDetailsReport, | ||
'markdown-summary': handleMarkdownSummaryReport, | ||
'raw': handleRawReport | ||
}; | ||
const bothGroup = options.reportGroup.both; | ||
if (bothGroup) { | ||
const bothReports = Object.keys(bothGroup); | ||
for (const reportName of bothReports) { | ||
const reportOptions = bothGroup[reportName]; | ||
const buildInHandler = buildInBothReports[reportName]; | ||
if (options.reportGroup.has('both')) { | ||
const bothGroup = options.reportGroup.get('both'); | ||
for (const [reportName, reportOptions] of bothGroup) { | ||
const builtInHandler = bothBuiltInReports[reportName]; | ||
const t1 = Date.now(); | ||
if (buildInHandler) { | ||
await buildInHandler(coverageResults, reportOptions, options); | ||
if (builtInHandler) { | ||
await builtInHandler(coverageResults, reportOptions, options); | ||
} else { | ||
@@ -604,0 +217,0 @@ await Util.runCustomReporter(reportName, coverageResults, reportOptions, options); |
@@ -132,2 +132,5 @@ declare namespace MCR { | ||
metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; | ||
filter?: string | { | ||
[pattern: string]: boolean; | ||
} | ((file: CoverageFile) => boolean); | ||
}] | | ||
@@ -145,4 +148,8 @@ ['markdown-summary'] | ['markdown-summary', { | ||
color: 'unicode' | 'html' | 'tex' | string; | ||
maxCols?: number; | ||
skipPercent?: number; | ||
metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; | ||
filter?: string | { | ||
[pattern: string]: boolean; | ||
} | ((file: CoverageFile) => boolean); | ||
/** | ||
@@ -195,4 +202,11 @@ * defaults to `coverage-details.md` | ||
count: number; | ||
/** ignored by special comment which starts with `v8 ignore` */ | ||
ignored?: boolean; | ||
/** | ||
* branch only, for example: | ||
* there is only `if` branch but no `else` branch, then `none` will be true, it shows `else path uncovered` | ||
*/ | ||
none?: boolean; | ||
/** function only, function name */ | ||
name?: boolean; | ||
} | ||
@@ -203,3 +217,5 @@ | ||
end: number; | ||
/** ignore type: `next` or `range` */ | ||
type: string; | ||
/** n lines for `next` type */ | ||
n?: number; | ||
@@ -253,2 +269,3 @@ } | ||
reportPath: string; | ||
version: string; | ||
name: string; | ||
@@ -323,3 +340,7 @@ watermarks: Watermarks; | ||
* */ | ||
sourcePath?: ((filePath: string, info: any) => string) | { | ||
sourcePath?: ((filePath: string, info: { | ||
/** the related dist file of current source file */ | ||
distFile?: string; | ||
[key: string]: any; | ||
}) => string) | { | ||
[key: string]: string; | ||
@@ -326,0 +347,0 @@ }; |
@@ -90,10 +90,12 @@ const fs = require('fs'); | ||
const istanbulGroup = options.reportGroup.istanbul; | ||
Object.keys(istanbulGroup).forEach((reportName) => { | ||
const t1 = Date.now(); | ||
const reportOptions = istanbulGroup[reportName]; | ||
const report = istanbulReports.create(reportName, reportOptions); | ||
report.execute(context); | ||
Util.logTime(`┌ [generate] saved report: ${reportName}`, t1); | ||
}); | ||
const istanbulGroup = options.reportGroup.get('istanbul'); | ||
// already has | ||
if (istanbulGroup) { | ||
for (const [reportName, reportOptions] of istanbulGroup) { | ||
const t1 = Date.now(); | ||
const report = istanbulReports.create(reportName, reportOptions); | ||
report.execute(context); | ||
Util.logTime(`┌ [generate] saved report: ${reportName}`, t1); | ||
} | ||
} | ||
@@ -113,2 +115,3 @@ // add watermarks and color | ||
reportPath, | ||
version: Util.version, | ||
name: options.name, | ||
@@ -115,0 +118,0 @@ watermarks: contextOptions.watermarks, |
@@ -29,2 +29,18 @@ const Util = { | ||
isNum: function(num) { | ||
if (typeof num !== 'number' || isNaN(num)) { | ||
return false; | ||
} | ||
const isInvalid = function(n) { | ||
if (n === Number.MAX_VALUE || n === Number.MIN_VALUE || n === Number.NEGATIVE_INFINITY || n === Number.POSITIVE_INFINITY) { | ||
return true; | ||
} | ||
return false; | ||
}; | ||
if (isInvalid(num)) { | ||
return false; | ||
} | ||
return true; | ||
}, | ||
toNum: function(num, toInt) { | ||
@@ -31,0 +47,0 @@ if (typeof (num) !== 'number') { |
@@ -0,0 +0,0 @@ const os = require('os'); |
@@ -11,6 +11,4 @@ const fs = require('fs'); | ||
const request = require('./request.js'); | ||
const { deflateSync } = require('lz-utils'); | ||
const version = require('../../package.json').version; | ||
const acornWalk = require('acorn-walk'); | ||
const { findUpSync, supportsColor } = require('../packages/monocart-coverage-vendor.js'); | ||
@@ -25,2 +23,4 @@ | ||
const Util = { | ||
version, | ||
... Share, | ||
@@ -154,38 +154,2 @@ | ||
resolveNodeModule: (id) => { | ||
// for deno npm module | ||
const mp = require.resolve(id); | ||
if (fs.existsSync(mp)) { | ||
return mp; | ||
} | ||
const p = `${it}/dist/${it}.js`; | ||
// root | ||
const cwd = path.resolve('node_modules', p); | ||
if (fs.existsSync(cwd)) { | ||
return cwd; | ||
} | ||
// sub node modules | ||
const sub = path.resolve(__dirname, '../../node_modules', p); | ||
if (fs.existsSync(sub)) { | ||
return sub; | ||
} | ||
// same level dep | ||
const dep = path.resolve(__dirname, '../../../', p); | ||
if (fs.existsSync(dep)) { | ||
return dep; | ||
} | ||
Util.logError(`Not found module: ${p}`); | ||
return cwd; | ||
}, | ||
resolvePackage: (p) => { | ||
return path.resolve(__dirname, '../packages', p); | ||
}, | ||
getCacheFileInfo: (type, id, cacheDir) => { | ||
@@ -225,72 +189,2 @@ const cacheName = `${type}-${id}.json`; | ||
saveHtmlReport: async (options) => { | ||
const { | ||
inline, | ||
reportData, | ||
jsFiles, | ||
assetsPath, | ||
outputDir, | ||
htmlFile, | ||
reportDataFile | ||
} = options; | ||
// report data | ||
const reportDataCompressed = deflateSync(JSON.stringify(reportData)); | ||
const reportDataStr = `window.reportData = '${reportDataCompressed}';`; | ||
// js libs | ||
const jsList = []; | ||
for (const jsFile of jsFiles) { | ||
const jsStr = await Util.readFile(jsFile); | ||
jsList.push({ | ||
filename: path.basename(jsFile), | ||
str: jsStr | ||
}); | ||
} | ||
// html content | ||
let htmlStr = ''; | ||
const EOL = Util.getEOL(); | ||
if (inline) { | ||
htmlStr = [ | ||
'<script>', | ||
reportDataStr, | ||
... jsList.map((it) => it.str), | ||
'</script>' | ||
].join(EOL); | ||
} else { | ||
await Util.writeFile(path.resolve(outputDir, reportDataFile), reportDataStr); | ||
const assetsDir = path.resolve(outputDir, assetsPath); | ||
const relAssetsDir = Util.relativePath(assetsDir, outputDir); | ||
for (const item of jsList) { | ||
const filePath = path.resolve(assetsDir, item.filename); | ||
if (!fs.existsSync(filePath)) { | ||
await Util.writeFile(filePath, item.str); | ||
} | ||
} | ||
htmlStr = [ | ||
`<script src="${reportDataFile}"></script>`, | ||
... jsList.map((it) => `<script src="${relAssetsDir}/${it.filename}"></script>`) | ||
].join(EOL); | ||
} | ||
// html | ||
const htmlPath = path.resolve(outputDir, htmlFile); | ||
const template = Util.getTemplate(path.resolve(__dirname, '../default/template.html')); | ||
const html = Util.replace(template, { | ||
title: reportData.title, | ||
content: htmlStr | ||
}); | ||
await Util.writeFile(htmlPath, html); | ||
return Util.relativePath(htmlPath); | ||
}, | ||
runCustomReporter: async (reportName, reportData, reportOptions, globalOptions) => { | ||
@@ -492,18 +386,2 @@ let CustomReporter; | ||
getTemplate: function(templatePath) { | ||
if (!Util.templateCache) { | ||
Util.templateCache = {}; | ||
} | ||
let template = Util.templateCache[templatePath]; | ||
if (!template) { | ||
template = Util.readFileSync(templatePath); | ||
if (template) { | ||
Util.templateCache[templatePath] = template; | ||
} else { | ||
Util.logError(`not found template: ${templatePath}`); | ||
} | ||
} | ||
return template; | ||
}, | ||
normalizeColorType: (color) => { | ||
@@ -513,2 +391,8 @@ return `${color}`.trim().toLowerCase(); | ||
normalizeMaxCols: (maxCols, min = 1) => { | ||
if (Util.isNum(maxCols)) { | ||
return Math.max(maxCols, min); | ||
} | ||
}, | ||
getColorStrByStatus: (str, status, color = '') => { | ||
@@ -554,3 +438,3 @@ | ||
'tex': () => { | ||
const texStr = str.replace('%', '\\\\%'); | ||
const texStr = str.replace(/%/g, '\\\\%'); | ||
if (status === 'low') { | ||
@@ -557,0 +441,0 @@ return `$\\color{red}{\\textsf{${texStr}}}$`; |
@@ -1,6 +0,3 @@ | ||
const path = require('path'); | ||
const EC = require('eight-colors'); | ||
const { minimatch } = require('minimatch'); | ||
const { mergeScriptCovs } = require('@bcoe/v8-coverage'); | ||
const Util = require('../utils/util.js'); | ||
@@ -13,4 +10,7 @@ const { getV8Summary } = require('./v8-summary.js'); | ||
const { collectSourceMaps } = require('../converter/collect-source-maps.js'); | ||
const version = require('../../package.json').version; | ||
const { minimatch } = require('../packages/monocart-coverage-vendor.js'); | ||
const { v8Report } = require('../reports/v8.js'); | ||
const { v8JsonReport } = require('../reports/v8-json.js'); | ||
const getWrapperSource = (offset, source) => { | ||
@@ -317,64 +317,2 @@ // NO \n because it break line number in mappings | ||
const handleV8JsonReport = async (reportData, reportOptions, options) => { | ||
const v8JsonOptions = { | ||
outputFile: 'coverage-report.json', | ||
... reportOptions | ||
}; | ||
// console.log(mergedOptions); | ||
const jsonPath = path.resolve(options.outputDir, v8JsonOptions.outputFile); | ||
await Util.writeFile(jsonPath, JSON.stringify(reportData)); | ||
return Util.relativePath(jsonPath); | ||
}; | ||
const handleV8HtmlReport = async (reportData, reportOptions, options) => { | ||
// V8 only options, merged with root options | ||
const v8HtmlOptions = { | ||
outputFile: options.outputFile, | ||
inline: options.inline, | ||
assetsPath: options.assetsPath, | ||
metrics: options.metrics, | ||
... reportOptions | ||
}; | ||
// add metrics to data for UI | ||
reportData.metrics = v8HtmlOptions.metrics; | ||
const { | ||
outputFile, inline, assetsPath | ||
} = v8HtmlOptions; | ||
// resolve full report path | ||
const reportPath = path.resolve(options.outputDir, outputFile); | ||
const outputDir = path.dirname(reportPath); | ||
const htmlFile = path.basename(reportPath); | ||
// deps | ||
const jsFiles = ['monocart-code-viewer', 'monocart-formatter', 'turbogrid'].map((id) => { | ||
return Util.resolveNodeModule(id); | ||
}); | ||
// package app ui | ||
jsFiles.push(Util.resolvePackage('monocart-coverage-app.js')); | ||
// console.log(jsFiles); | ||
const htmlOptions = { | ||
reportData, | ||
jsFiles, | ||
inline, | ||
assetsPath, | ||
outputDir, | ||
htmlFile, | ||
reportDataFile: 'coverage-data.js' | ||
}; | ||
const htmlPath = await Util.saveHtmlReport(htmlOptions); | ||
return htmlPath; | ||
}; | ||
const saveV8Report = async (v8list, options, istanbulReportPath) => { | ||
@@ -394,4 +332,7 @@ | ||
const reportData = { | ||
type: 'v8', | ||
// override with saved file path | ||
reportPath: '', | ||
version: Util.version, | ||
name: options.name, | ||
version, | ||
watermarks, | ||
@@ -404,13 +345,11 @@ summary, | ||
const buildInV8Reports = { | ||
'v8': handleV8HtmlReport, | ||
'v8-json': handleV8JsonReport | ||
'v8': v8Report, | ||
'v8-json': v8JsonReport | ||
}; | ||
const outputs = {}; | ||
const v8Group = options.reportGroup.v8; | ||
const v8Group = options.reportGroup.get('v8'); | ||
// could be no v8 only reports, but have `both` data reports | ||
if (v8Group) { | ||
const v8Reports = Object.keys(v8Group); | ||
for (const reportName of v8Reports) { | ||
const reportOptions = v8Group[reportName]; | ||
for (const [reportName, reportOptions] of v8Group) { | ||
const buildInHandler = buildInV8Reports[reportName]; | ||
@@ -438,3 +377,5 @@ const t1 = Date.now(); | ||
type: 'v8', | ||
// html or json | ||
reportPath, | ||
version: Util.version, | ||
name: options.name, | ||
@@ -441,0 +382,0 @@ watermarks, |
{ | ||
"name": "monocart-coverage-reports", | ||
"version": "2.9.3", | ||
"version": "2.10.0", | ||
"description": "A code coverage tool to generate native V8 reports or Istanbul reports.", | ||
@@ -57,2 +57,3 @@ "main": "./lib/index.js", | ||
"test-all": "node ./test/test.js && node ./scripts/docs.js", | ||
"test-pr": "node --inspect=9230 ./test/test-pr.js", | ||
"test": "npm run test-unit && npx mcr npm run test-all -c test/mcr.config.mcr.js", | ||
@@ -66,3 +67,2 @@ "test:snap": "cross-env TEST_SNAPSHOT=true npm run test", | ||
"workspaces": [ | ||
"packages/*", | ||
"test" | ||
@@ -87,3 +87,2 @@ ], | ||
"console-grid": "^2.2.2", | ||
"diff-sequences": "^29.6.3", | ||
"eight-colors": "^1.3.0", | ||
@@ -94,12 +93,11 @@ "foreground-child": "^3.2.1", | ||
"istanbul-reports": "^3.1.7", | ||
"lz-utils": "^2.0.2", | ||
"minimatch": "9.0.5", | ||
"monocart-code-viewer": "^1.1.4", | ||
"monocart-formatter": "^3.0.0", | ||
"monocart-locator": "^1.0.2", | ||
"turbogrid": "^3.2.0" | ||
"lz-utils": "^2.1.0", | ||
"monocart-locator": "^1.0.2" | ||
}, | ||
"devDependencies": { | ||
"async-tick": "^1.0.0", | ||
"convert-source-map": "^2.0.0", | ||
"diff-sequences": "^29.6.3", | ||
"esbuild": "^0.23.0", | ||
"eslint": "~9.7.0", | ||
"eslint": "~9.8.0", | ||
"eslint-config-plus": "^2.0.2", | ||
@@ -109,2 +107,6 @@ "eslint-plugin-html": "^8.1.1", | ||
"find-up": "^7.0.0", | ||
"minimatch": "^9.0.5", | ||
"monocart-code-viewer": "^1.1.4", | ||
"monocart-formatter": "^3.0.0", | ||
"postcss": "^8.4.40", | ||
"starfall-cli": "^2.0.20", | ||
@@ -115,4 +117,6 @@ "stylelint": "^16.7.0", | ||
"tsx": "^4.16.2", | ||
"turbogrid": "^3.2.0", | ||
"vine-ui": "^3.1.16", | ||
"ws": "^8.18.0" | ||
} | ||
} |
@@ -110,2 +110,3 @@ # Monocart Coverage Reports | ||
- Support for Native Byte Statistics | ||
- Support processing big data with high performance | ||
- Coverage for Any Runtime Code | ||
@@ -119,3 +120,4 @@ - CSS Coverage Support | ||
- `v8-json` | ||
- [V8 coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json) | ||
- Save `CoverageResults` to a json file | ||
- Preview [coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json) | ||
@@ -163,2 +165,3 @@ > Istanbul build-in reports (both V8 and Istanbul data): | ||
- `markdown-details` Save coverage details to a markdown file (defaults to `coverage-details.md`). | ||
- Preview in [runs](https://github.com/cenfun/monocart-coverage-reports/actions/workflows/ci.yml) | ||
@@ -165,0 +168,0 @@ - `raw` only keep all original data, which can be used for other reports input with `inputDir`. see [Merge Coverage Reports](#merge-coverage-reports) |
@@ -110,2 +110,3 @@ # Monocart Coverage Reports | ||
- 支持原生的Bytes覆盖率指标 | ||
- 支持高性能处理大数据 | ||
- 支持任何运行时代码的覆盖率(压缩后的) | ||
@@ -119,3 +120,4 @@ - 支持CSS代码覆盖率(用于分析CSS的冗余代码) | ||
- `v8-json` | ||
- [V8 coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json) | ||
- 保存 `CoverageResults` 到一个json文件 | ||
- 预览 [coverage-report.json](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json) | ||
@@ -163,2 +165,3 @@ > 内置Istanbul报告 (V8和Istanbul格式数据都支持): | ||
- `markdown-details` 保存覆盖率详情到markdown文件 (默认是 `coverage-details.md`) | ||
- 预览运行结果 [runs](https://github.com/cenfun/monocart-coverage-reports/actions/workflows/ci.yml) | ||
@@ -165,0 +168,0 @@ - `raw` 只是保存原始覆盖率数据, 用于使用`inputDir`参数来导入多个原始数据进行合并报告。参见 [合并覆盖率报告](#merge-coverage-reports) |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
935969
14
52
10879
2
1127
28
9
21
- Removeddiff-sequences@^29.6.3
- Removedminimatch@9.0.5
- Removedmonocart-code-viewer@^1.1.4
- Removedmonocart-formatter@^3.0.0
- Removedturbogrid@^3.2.0
- Removedbalanced-match@1.0.2(transitive)
- Removedbrace-expansion@2.0.1(transitive)
- Removeddiff-sequences@29.6.3(transitive)
- Removedminimatch@9.0.5(transitive)
- Removedmonocart-code-viewer@1.1.4(transitive)
- Removedmonocart-formatter@3.0.0(transitive)
- Removedturbogrid@3.2.0(transitive)
Updatedlz-utils@^2.1.0