.
This commit is contained in:
		
							
								
								
									
										305
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/annotator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/annotator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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, '&')
 | 
			
		||||
        .replace(RE_LT, '<')
 | 
			
		||||
        .replace(RE_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()) || ' '
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        lineCoverageArray = structured.map(item => ({
 | 
			
		||||
            covered: item.covered,
 | 
			
		||||
            hits: item.hits > 0 ? item.hits + 'x' : ' '
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        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
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/base.css
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/base.css
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/block-navigation.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/block-navigation.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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) > `
 | 
			
		||||
 | 
			
		||||
    // Selector 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);
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/favicon.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/favicon.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 445 B  | 
							
								
								
									
										
											BIN
										
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/sort-arrow-sprite.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/sort-arrow-sprite.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 138 B  | 
							
								
								
									
										209
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/sorter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/sorter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
        // Try to create a RegExp from the searchValue. If it fails (invalid regex),
 | 
			
		||||
        // it will be treated as a plain text search
 | 
			
		||||
        let searchRegex;
 | 
			
		||||
        try {
 | 
			
		||||
            searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            searchRegex = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < rows.length; i++) {
 | 
			
		||||
            const row = rows[i];
 | 
			
		||||
            let isMatch = false;
 | 
			
		||||
 | 
			
		||||
            if (searchRegex) {
 | 
			
		||||
                // If a valid regex was created, use it for matching
 | 
			
		||||
                isMatch = searchRegex.test(row.textContent);
 | 
			
		||||
            } else {
 | 
			
		||||
                // Otherwise, fall back to the original plain text search
 | 
			
		||||
                isMatch = row.textContent
 | 
			
		||||
                    .toLowerCase()
 | 
			
		||||
                    .includes(searchValue.toLowerCase());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            row.style.display = isMatch ? '' : '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);
 | 
			
		||||
							
								
								
									
										1
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.css
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.css
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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}
 | 
			
		||||
							
								
								
									
										1
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/assets/vendor/prettify.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										421
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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>      
 | 
			
		||||
            </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;
 | 
			
		||||
							
								
								
									
										114
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/insertion-text.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								qwen/nodejs/node_modules/istanbul-reports/lib/html/insertion-text.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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;
 | 
			
		||||
		Reference in New Issue
	
	Block a user