diff options
Diffstat (limited to 'node_modules/istanbul-lib-report/lib')
-rw-r--r-- | node_modules/istanbul-lib-report/lib/context.js | 122 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/file-writer.js | 186 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/path.js | 161 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/summarizer.js | 284 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/tree.js | 167 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/watermarks.js | 14 | ||||
-rw-r--r-- | node_modules/istanbul-lib-report/lib/xml-writer.js | 87 |
7 files changed, 1021 insertions, 0 deletions
diff --git a/node_modules/istanbul-lib-report/lib/context.js b/node_modules/istanbul-lib-report/lib/context.js new file mode 100644 index 000000000..034a2b107 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/context.js @@ -0,0 +1,122 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +var FileWriter = require('./file-writer'), + XMLWriter = require('./xml-writer'), + tree = require('./tree'), + watermarks = require('./watermarks'), + fs = require('fs'); + +function defaultSourceLookup(path) { + try { + return fs.readFileSync(path, 'utf8'); + } catch (ex) { + throw new Error('Unable to lookup source: ' + path + '(' + ex.message + ')'); + } +} + +function mergeWatermarks(specified, defaults) { + specified = specified || {}; + Object.keys(defaults).forEach(function (k) { + var specValue = specified[k]; + if (!(specValue && Array.isArray(specValue) && specValue.length === 2)) { + specified[k] = defaults[k]; + } + }); + return specified; +} +/** + * A reporting context that is passed to report implementations + * @param {Object} [opts=null] opts options + * @param {String} [opts.dir='coverage'] opts.dir the reporting directory + * @param {Object} [opts.watermarks=null] opts.watermarks watermarks for + * statements, lines, branches and functions + * @param {Function} [opts.sourceFinder=fsLookup] opts.sourceFinder a + * function that returns source code given a file path. Defaults to + * filesystem lookups based on path. + * @constructor + */ +function Context(opts) { + opts = opts || {}; + this.dir = opts.dir || 'coverage'; + this.watermarks = mergeWatermarks(opts.watermarks, watermarks.getDefault()); + this.sourceFinder = opts.sourceFinder || defaultSourceLookup; + this.data = {}; +} + +Object.defineProperty(Context.prototype, 'writer', { + enumerable: true, + get: function () { + if (!this.data.writer) { + this.data.writer = new FileWriter(this.dir); + } + return this.data.writer; + } +}); + +/** + * returns a FileWriter implementation for reporting use. Also available + * as the `writer` property on the context. + * @returns {Writer} + */ +Context.prototype.getWriter = function () { + return this.writer; +}; + +/** + * returns the source code for the specified file path or throws if + * the source could not be found. + * @param {String} filePath the file path as found in a file coverage object + * @returns {String} the source code + */ +Context.prototype.getSource = function (filePath) { + return this.sourceFinder(filePath); +}; + +/** + * returns the coverage class given a coverage + * types and a percentage value. + * @param {String} type - the coverage type, one of `statements`, `functions`, + * `branches`, or `lines` + * @param {Number} value - the percentage value + * @returns {String} one of `high`, `medium` or `low` + */ +Context.prototype.classForPercent = function (type, value) { + var watermarks = this.watermarks[type]; + if (!watermarks) { + return 'unknown'; + } + if (value < watermarks[0]) { + return 'low'; + } + if (value >= watermarks[1]) { + return 'high'; + } + return 'medium'; +}; +/** + * returns an XML writer for the supplied content writer + * @param {ContentWriter} contentWriter the content writer to which the returned XML writer + * writes data + * @returns {XMLWriter} + */ +Context.prototype.getXMLWriter = function (contentWriter) { + return new XMLWriter(contentWriter); +}; +/** + * returns a full visitor given a partial one. + * @param {Object} partialVisitor a partial visitor only having the functions of + * interest to the caller. These functions are called with a scope that is the + * supplied object. + * @returns {Visitor} + */ +Context.prototype.getVisitor = function (partialVisitor) { + return new tree.Visitor(partialVisitor); +}; + +module.exports = { + create: function (opts) { + return new Context(opts); + } +}; diff --git a/node_modules/istanbul-lib-report/lib/file-writer.js b/node_modules/istanbul-lib-report/lib/file-writer.js new file mode 100644 index 000000000..3121fbfb6 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/file-writer.js @@ -0,0 +1,186 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +var util = require('util'), + path = require('path'), + fs = require('fs'), + mkdirp = require('mkdirp'), + supportsColor = require('supports-color'), + isAbsolute = path.isAbsolute || /* istanbul ignore next */ function (p) { + return path.resolve(p) === path.normalize(p); + }; + +/** + * abstract interface for writing content + * @class ContentWriter + * @constructor + */ +/* istanbul ignore next: abstract class */ +function ContentWriter() { +} + +/** + * writes a string as-is to the destination + * @param {String} str the string to write + */ +/* istanbul ignore next: abstract class */ +ContentWriter.prototype.write = function () { + throw new Error('write: must be overridden'); +}; + +/** + * returns the colorized version of a string. Typically, + * content writers that write to files will return the + * same string and ones writing to a tty will wrap it in + * appropriate escape sequences. + * @param {String} str the string to colorize + * @param {String} clazz one of `high`, `medium` or `low` + * @returns {String} the colorized form of the string + */ +ContentWriter.prototype.colorize = function (str /*, clazz*/) { + return str; +}; + +/** + * writes a string appended with a newline to the destination + * @param {String} str the string to write + */ +ContentWriter.prototype.println = function (str) { + this.write(str + '\n'); +}; + +/** + * closes this content writer. Should be called after all writes are complete. + */ +ContentWriter.prototype.close = function () { +}; + +/** + * a content writer that writes to a file + * @param {Number} fd - the file descriptor + * @extends ContentWriter + * @constructor + */ +function FileContentWriter(fd) { + this.fd = fd; +} +util.inherits(FileContentWriter, ContentWriter); + +FileContentWriter.prototype.write = function (str) { + fs.writeSync(this.fd, str); +}; + +FileContentWriter.prototype.close = function () { + fs.closeSync(this.fd); +}; + +/** + * a content writer that writes to the console + * @extends ContentWriter + * @constructor + */ +function ConsoleWriter() { +} +util.inherits(ConsoleWriter, ContentWriter); + +// allow stdout to be captured for tests. +var capture = false; +var output = ''; +ConsoleWriter.prototype.write = function (str) { + if (capture) { + output += str; + } else { + process.stdout.write(str); + } +}; + +ConsoleWriter.prototype.colorize = function (str, clazz) { + var colors = { + low: '31;1', + medium: '33;1', + high: '32;1' + }; + + /* istanbul ignore next: different modes for CI and local */ + if (supportsColor && colors[clazz]) { + return '\u001b[' + colors[clazz] + 'm' + str + '\u001b[0m'; + } + return str; +}; + +/** + * utility for writing files under a specific directory + * @class FileWriter + * @param {String} baseDir the base directory under which files should be written + * @constructor + */ +function FileWriter(baseDir) { + if (!baseDir) { + throw new Error('baseDir must be specified'); + } + mkdirp.sync(baseDir); + this.baseDir = baseDir; +} + +/** +* static helpers for capturing stdout report output; +* super useful for tests! +*/ +FileWriter.startCapture = function () { + capture = true; +}; +FileWriter.stopCapture = function () { + capture = false; +}; +FileWriter.getOutput = function () { + return output; +}; +FileWriter.resetOutput = function () { + output = ''; +}; + +/** + * returns a FileWriter that is rooted at the supplied subdirectory + * @param {String} subdir the subdirectory under which to root the + * returned FileWriter + * @returns {FileWriter} + */ +FileWriter.prototype.writerForDir = function (subdir) { + if (isAbsolute(subdir)) { + throw new Error('Cannot create subdir writer for absolute path: ' + subdir); + } + return new FileWriter(this.baseDir + '/' + subdir); +}; +/** + * copies a file from a source directory to a destination name + * @param {String} source path to source file + * @param {String} dest relative path to destination file + */ +FileWriter.prototype.copyFile = function (source, dest) { + if (isAbsolute(dest)) { + throw new Error('Cannot write to absolute path: ' + dest); + } + dest = path.resolve(this.baseDir, dest); + mkdirp.sync(path.dirname(dest)); + fs.writeFileSync(dest, fs.readFileSync(source)); +}; +/** + * returns a content writer for writing content to the supplied file. + * @param {String|null} file the relative path to the file or the special + * values `"-"` or `null` for writing to the console + * @returns {ContentWriter} + */ +FileWriter.prototype.writeFile = function (file) { + if (file === null || file === '-') { + return new ConsoleWriter(); + } + if (isAbsolute(file)) { + throw new Error('Cannot write to absolute path: ' + file); + } + file = path.resolve(this.baseDir, file); + mkdirp.sync(path.dirname(file)); + return new FileContentWriter(fs.openSync(file, 'w')); +}; + +module.exports = FileWriter; diff --git a/node_modules/istanbul-lib-report/lib/path.js b/node_modules/istanbul-lib-report/lib/path.js new file mode 100644 index 000000000..9d97e15e3 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/path.js @@ -0,0 +1,161 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var path = require('path'), + parsePath = require('path-parse'), + SEP = path.sep || /* istanbul ignore next */ '/', + origParser = parsePath, + origSep = SEP; + +function makeRelativeNormalizedPath(str, sep) { + var parsed = parsePath(str), + root = parsed.root, + dir, + file = parsed.base, + quoted, + pos; + + // handle a weird windows case separately + if (sep === '\\') { + pos = root.indexOf(':\\'); + if (pos >= 0) { + root = root.substring(0, pos + 2); + } + } + dir = parsed.dir.substring(root.length); + + if (str === '') { + return []; + } + + if (sep !== '/') { + quoted = new RegExp(sep.replace(/\W/g, '\\$&'), 'g'); + dir = dir.replace(quoted, '/'); + file = file.replace(quoted, '/'); // excessively paranoid? + } + + if (dir !== '') { + dir = dir + '/' + file; + } else { + dir = file; + } + if (dir.substring(0,1) === '/') { + dir = dir.substring(1); + } + dir = dir.split(/\/+/); + return dir; +} + +function Path(strOrArray) { + if (Array.isArray(strOrArray)) { + this.v = strOrArray; + } else if (typeof strOrArray === "string") { + this.v = makeRelativeNormalizedPath(strOrArray, SEP); + } else { + throw new Error('Invalid Path argument must be string or array:' + strOrArray); + } +} + +Path.prototype.toString = function () { + return this.v.join('/'); +}; + +Path.prototype.hasParent = function () { + return this.v.length > 0; +}; + +Path.prototype.parent = function () { + if (!this.hasParent()) { + throw new Error('Unable to get parent for 0 elem path'); + } + var p = this.v.slice(); + p.pop(); + return new Path(p); +}; + +Path.prototype.elements = function () { + return this.v.slice(); +}; + +Path.prototype.contains = function (other) { + var i; + if (other.length > this.length) { + return false; + } + for (i = 0; i < other.length; i += 1) { + if (this.v[i] !== other.v[i]) { + return false; + } + } + return true; +}; + +Path.prototype.ancestorOf = function (other) { + return other.contains(this) && other.length !== this.length; +}; + +Path.prototype.descendantOf = function (other) { + return this.contains(other) && other.length !== this.length; +}; + +Path.prototype.commonPrefixPath = function (other) { + var len = this.length > other.length ? other.length : this.length, + i, + ret = []; + + for (i = 0; i < len; i +=1 ) { + if (this.v[i] === other.v[i]) { + ret.push(this.v[i]); + } else { + break; + } + } + return new Path(ret); +}; + +['push', 'pop', 'shift', 'unshift', 'splice'].forEach(function (f) { + Path.prototype[f] = function () { + var args = Array.prototype.slice.call(arguments), + v = this.v; + return v[f].apply(v, args); + }; +}); + +Path.compare = function (a, b) { + var al = a.length, + bl = b.length, + astr, + bstr; + if (al < bl) { + return -1; + } + if (al > bl) { + return 1; + } + astr = a.toString(); + bstr = b.toString(); + return astr < bstr ? -1 : astr > bstr ? 1 : 0; +}; + +Object.defineProperty(Path.prototype, 'length', { + enumerable: true, + get: function () { + return this.v.length; + } +}); + +module.exports = Path; +Path.tester = { + setParserAndSep: function (p, sep) { + parsePath = p; + SEP = sep; + }, + reset: function () { + parsePath = origParser; + SEP = origSep; + } +}; + diff --git a/node_modules/istanbul-lib-report/lib/summarizer.js b/node_modules/istanbul-lib-report/lib/summarizer.js new file mode 100644 index 000000000..ee353b317 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/summarizer.js @@ -0,0 +1,284 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var Path = require('./path'), + util = require('util'), + tree = require('./tree'), + coverage = require('istanbul-lib-coverage'), + BaseNode = tree.Node, + BaseTree = tree.Tree; + +function ReportNode(path, fileCoverage) { + this.path = path; + this.parent = null; + this.fileCoverage = fileCoverage; + this.children = []; +} + +util.inherits(ReportNode, BaseNode); + +ReportNode.prototype.addChild = function (child) { + child.parent = this; + this.children.push(child); +}; + +ReportNode.prototype.asRelative = function (p) { + /* istanbul ignore if */ + if (p.substring(0,1) === '/') { + return p.substring(1); + } + return p; +}; + +ReportNode.prototype.getQualifiedName = function () { + return this.asRelative(this.path.toString()); +}; + +ReportNode.prototype.getRelativeName = function () { + var parent = this.getParent(), + myPath = this.path, + relPath, + i, + parentPath = parent ? parent.path : new Path([]); + if (parentPath.ancestorOf(myPath)) { + relPath = new Path(myPath.elements()); + for (i = 0; i < parentPath.length; i += 1) { + relPath.shift(); + } + return this.asRelative(relPath.toString()); + } + return this.asRelative(this.path.toString()); +}; + +ReportNode.prototype.getParent = function () { + return this.parent; +}; + +ReportNode.prototype.getChildren = function () { + return this.children; +}; + +ReportNode.prototype.isSummary = function () { + return !this.fileCoverage; +}; + +ReportNode.prototype.getFileCoverage = function () { + return this.fileCoverage; +}; + +ReportNode.prototype.getCoverageSummary = function (filesOnly) { + var cacheProp = 'c_' + (filesOnly ? 'files' : 'full'), + summary; + + if (this.hasOwnProperty(cacheProp)) { + return this[cacheProp]; + } + + if (!this.isSummary()) { + summary = this.getFileCoverage().toSummary(); + } else { + var count = 0; + summary = coverage.createCoverageSummary(); + this.getChildren().forEach(function (child) { + if (filesOnly && child.isSummary()) { + return; + } + count += 1; + summary.merge(child.getCoverageSummary(filesOnly)); + }); + if (count === 0 && filesOnly) { + summary = null; + } + } + this[cacheProp] = summary; + return summary; +}; + +function treeFor(root, childPrefix) { + var tree = new BaseTree(), + visitor, + maybePrefix = function (node) { + if (childPrefix && !node.isRoot()) { + node.path.unshift(childPrefix); + } + }; + tree.getRoot = function () { + return root; + }; + visitor = { + onDetail: function (node) { + maybePrefix(node); + }, + onSummary: function (node) { + maybePrefix(node); + node.children.sort(function (a, b) { + var astr = a.path.toString(), + bstr = b.path.toString(); + return astr < bstr ? -1 : astr > bstr ? 1: /* istanbul ignore next */ 0; + }); + } + }; + tree.visit(visitor); + return tree; +} + +function findCommonParent(paths) { + if (paths.length === 0) { + return new Path([]); + } + var common = paths[0], + i; + + for (i = 1; i < paths.length; i += 1) { + common = common.commonPrefixPath(paths[i]); + if (common.length === 0) { + break; + } + } + return common; +} + +function toInitialList(coverageMap) { + var ret = [], + commonParent; + coverageMap.files().forEach(function (filePath) { + var p = new Path(filePath), + coverage = coverageMap.fileCoverageFor(filePath); + ret.push({ + filePath: filePath, + path: p, + fileCoverage: coverage + }); + }); + commonParent = findCommonParent(ret.map(function (o) { return o.path.parent(); })); + if (commonParent.length > 0) { + ret.forEach(function (o) { + o.path.splice(0, commonParent.length); + }); + } + return { + list: ret, + commonParent: commonParent + }; +} + +function toDirParents(list) { + var nodeMap = {}, + parentNodeList = []; + list.forEach(function (o) { + var node = new ReportNode(o.path, o.fileCoverage), + parentPath = o.path.parent(), + parent = nodeMap[parentPath.toString()]; + + if (!parent) { + parent = new ReportNode(parentPath); + nodeMap[parentPath.toString()] = parent; + parentNodeList.push(parent); + } + parent.addChild(node); + }); + return parentNodeList; +} + +function foldIntoParents(nodeList) { + var ret = [], i, j; + + // sort by longest length first + nodeList.sort(function (a, b) { + return -1 * Path.compare(a.path , b.path); + }); + + for (i = 0; i < nodeList.length; i += 1) { + var first = nodeList[i], + inserted = false; + + for (j = i + 1; j < nodeList.length; j += 1) { + var second = nodeList[j]; + if (second.path.ancestorOf(first.path)) { + second.addChild(first); + inserted = true; + break; + } + } + + if (!inserted) { + ret.push(first); + } + } + return ret; +} + +function createRoot() { + return new ReportNode(new Path([])); +} + +function createNestedSummary(coverageMap) { + var flattened = toInitialList(coverageMap), + dirParents = toDirParents(flattened.list), + topNodes = foldIntoParents(dirParents), + root; + + if (topNodes.length === 0) { + return treeFor(new ReportNode([])); + } + + if (topNodes.length === 1) { + return treeFor(topNodes[0]); + } + + root = createRoot(); + topNodes.forEach(function (node) { + root.addChild(node); + }); + return treeFor(root); +} + +function createPackageSummary(coverageMap) { + var flattened = toInitialList(coverageMap), + dirParents = toDirParents(flattened.list), + common = flattened.commonParent, + prefix, + root; + + if (dirParents.length === 1) { + root = dirParents[0]; + } else { + root = createRoot(); + // if one of the dirs is itself the root, + // then we need to create a top-level dir + dirParents.forEach(function (dp) { + if (dp.path.length === 0) { + prefix = 'root'; + } + }); + if (prefix && common.length > 0) { + prefix = common.elements()[common.elements().length - 1]; + } + dirParents.forEach(function (node) { + root.addChild(node); + }); + } + return treeFor(root, prefix); +} + +function createFlatSummary(coverageMap) { + var flattened = toInitialList(coverageMap), + list = flattened.list, + root; + + root = createRoot(); + list.forEach(function (o) { + var node = new ReportNode(o.path, o.fileCoverage); + root.addChild(node); + }); + return treeFor(root); +} + +module.exports = { + createNestedSummary: createNestedSummary, + createPackageSummary: createPackageSummary, + createFlatSummary: createFlatSummary +}; diff --git a/node_modules/istanbul-lib-report/lib/tree.js b/node_modules/istanbul-lib-report/lib/tree.js new file mode 100644 index 000000000..190808d18 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/tree.js @@ -0,0 +1,167 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +"use strict"; + +var util = require('util'); +/** + * An object with methods that are called during the traversal of the coverage tree. + * A visitor has the following methods that are called during tree traversal. + * + * * `onStart(root, state)` - called before traversal begins + * * `onSummary(node, state)` - called for every summary node + * * `onDetail(node, state)` - called for every detail node + * * `onSummaryEnd(node, state)` - called after all children have been visited for + * a summary node. + * * `onEnd(root, state)` - called after traversal ends + * + * @param delegate - a partial visitor that only implements the methods of interest + * The visitor object supplies the missing methods as noops. For example, reports + * that only need the final coverage summary need implement `onStart` and nothing + * else. Reports that use only detailed coverage information need implement `onDetail` + * and nothing else. + * @constructor + */ +function Visitor(delegate) { + this.delegate = delegate; +} + +['Start', 'End', 'Summary', 'SummaryEnd', 'Detail' ].forEach(function (k) { + var f = 'on' + k; + Visitor.prototype[f] = function (node, state) { + if (this.delegate[f] && typeof this.delegate[f] === 'function') { + this.delegate[f].call(this.delegate, node, state); + } + }; +}); + +function CompositeVisitor(visitors) { + if (!Array.isArray(visitors)) { + visitors = [visitors]; + } + this.visitors = visitors.map(function (v) { + if (v instanceof Visitor) { + return v; + } + return new Visitor(v); + }); +} + +util.inherits(CompositeVisitor, Visitor); + +['Start', 'Summary', 'SummaryEnd', 'Detail', 'End'].forEach(function (k) { + var f = 'on' + k; + CompositeVisitor.prototype[f] = function (node, state) { + this.visitors.forEach(function (v) { + v[f](node, state); + }); + }; +}); + +function Node() { +} + +/* istanbul ignore next: abstract method */ +Node.prototype.getQualifiedName = function () { + throw new Error('getQualifiedName must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getRelativeName = function () { + throw new Error('getRelativeName must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.isRoot = function () { + return !this.getParent(); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getParent = function () { + throw new Error('getParent must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getChildren = function () { + throw new Error('getChildren must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.isSummary = function () { + throw new Error('isSummary must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getCoverageSummary = function (/* filesOnly */) { + throw new Error('getCoverageSummary must be overridden'); +}; + +/* istanbul ignore next: abstract method */ +Node.prototype.getFileCoverage = function () { + throw new Error('getFileCoverage must be overridden'); +}; +/** + * visit all nodes depth-first from this node down. Note that `onStart` + * and `onEnd` are never called on the visitor even if the current + * node is the root of the tree. + * @param visitor a full visitor that is called during tree traversal + * @param state optional state that is passed around + */ +Node.prototype.visit = function (visitor, state) { + + var that = this, + visitChildren = function () { + that.getChildren().forEach(function (child) { + child.visit(visitor, state); + }); + }; + + if (this.isSummary()) { + visitor.onSummary(this, state); + } else { + visitor.onDetail(this, state); + } + + visitChildren(); + + if (this.isSummary()) { + visitor.onSummaryEnd(this, state); + } +}; + +/** + * abstract base class for a coverage tree. + * @constructor + */ +function Tree() { +} + +/** + * returns the root node of the tree + */ +/* istanbul ignore next: abstract method */ +Tree.prototype.getRoot = function () { + throw new Error('getRoot must be overridden'); +}; + +/** + * visits the tree depth-first with the supplied partial visitor + * @param visitor - a potentially partial visitor + * @param state - the state to be passed around during tree traversal + */ +Tree.prototype.visit = function (visitor, state) { + if (!(visitor instanceof Visitor)) { + visitor = new Visitor(visitor); + } + visitor.onStart(this.getRoot(), state); + this.getRoot().visit(visitor, state); + visitor.onEnd(this.getRoot(), state); +}; + +module.exports = { + Tree: Tree, + Node: Node, + Visitor: Visitor, + CompositeVisitor: CompositeVisitor +}; diff --git a/node_modules/istanbul-lib-report/lib/watermarks.js b/node_modules/istanbul-lib-report/lib/watermarks.js new file mode 100644 index 000000000..a522129f1 --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/watermarks.js @@ -0,0 +1,14 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +module.exports = { + getDefault: function () { + return { + statements: [50, 80], + functions: [50, 80], + branches: [50, 80], + lines: [50, 80] + }; + } +}; diff --git a/node_modules/istanbul-lib-report/lib/xml-writer.js b/node_modules/istanbul-lib-report/lib/xml-writer.js new file mode 100644 index 000000000..7f372fb3c --- /dev/null +++ b/node_modules/istanbul-lib-report/lib/xml-writer.js @@ -0,0 +1,87 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +var INDENT = ' '; + +/** + * a utility class to produce well-formed, indented XML + * @param {ContentWriter} contentWriter the content writer that this utility wraps + * @constructor + */ +function XMLWriter(contentWriter) { + this.cw = contentWriter; + this.stack = []; +} + +function attrString(attrs) { + if (!attrs) { + return ''; + } + var ret = []; + Object.keys(attrs).forEach(function (k) { + var v = attrs[k]; + ret.push(k + '="' + v + '"'); + }); + return ret.length === 0 ? '' : ' ' + ret.join(' '); +} + +XMLWriter.prototype.indent = function (str) { + return this.stack.map(function () { return INDENT; }).join('') + str; +}; + +/** + * writes the opening XML tag with the supplied attributes + * @param {String} name tag name + * @param {Object} [attrs=null] attrs attributes for the tag + */ +XMLWriter.prototype.openTag = function (name, attrs) { + var str = this.indent('<' + name + attrString(attrs) + '>'); + this.cw.println(str); + this.stack.push(name); +}; + +/** + * closes an open XML tag. + * @param {String} name - tag name to close. This must match the writer's + * notion of the tag that is currently open. + */ +XMLWriter.prototype.closeTag = function (name) { + if (this.stack.length === 0) { + throw new Error('Attempt to close tag ' + name + ' when not opened'); + } + var stashed = this.stack.pop(), + str = '</' + name + '>'; + + if (stashed !== name) { + throw new Error('Attempt to close tag ' + name + ' when ' + stashed + ' was the one open'); + } + this.cw.println(this.indent(str)); +}; +/** + * writes a tag and its value opening and closing it at the same time + * @param {String} name tag name + * @param {Object} [attrs=null] attrs tag attributes + * @param {String} [content=null] content optional tag content + */ +XMLWriter.prototype.inlineTag = function (name, attrs, content) { + var str = '<' + name + attrString(attrs); + if (content) { + str += '>' + content + '</' + name + '>'; + } else { + str += '/>'; + } + str = this.indent(str); + this.cw.println(str); +}; +/** + * closes all open tags and ends the document + */ +XMLWriter.prototype.closeAll = function () { + var that = this; + this.stack.slice().reverse().forEach(function (name) { + that.closeTag(name); + }); +}; + +module.exports = XMLWriter; |