diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-14 14:46:37 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-14 14:46:37 -0800 |
| commit | afa87af01c79a9baa539f2992d32154d2a4739bd (patch) | |
| tree | 92c7416db734270a2fee1d72ee9cc119379ff8e1 /vanilla/node_modules/istanbul-lib-report/lib | |
| parent | 3b927e84d200402281f68181cd4253bc77e5528d (diff) | |
| download | neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.gz neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.bz2 neko-afa87af01c79a9baa539f2992d32154d2a4739bd.zip | |
task: delete vanilla js prototype\n\n- Removed vanilla/ directory and web/dist/vanilla directory\n- Updated Makefile, Dockerfile, and CI workflow to remove vanilla references\n- Cleaned up web/web.go to remove vanilla embed and routes\n- Verified build and tests pass\n\nCloses NK-2tcnmq
Diffstat (limited to 'vanilla/node_modules/istanbul-lib-report/lib')
8 files changed, 0 insertions, 1032 deletions
diff --git a/vanilla/node_modules/istanbul-lib-report/lib/context.js b/vanilla/node_modules/istanbul-lib-report/lib/context.js deleted file mode 100644 index fbb30bc..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/context.js +++ /dev/null @@ -1,132 +0,0 @@ -'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 FileWriter = require('./file-writer'); -const XMLWriter = require('./xml-writer'); -const tree = require('./tree'); -const watermarks = require('./watermarks'); -const SummarizerFactory = require('./summarizer-factory'); - -function defaultSourceLookup(path) { - try { - return fs.readFileSync(path, 'utf8'); - } catch (ex) { - throw new Error(`Unable to lookup source: ${path} (${ex.message})`); - } -} - -function normalizeWatermarks(specified = {}) { - Object.entries(watermarks.getDefault()).forEach(([k, value]) => { - const specValue = specified[k]; - if (!Array.isArray(specValue) || specValue.length !== 2) { - specified[k] = value; - } - }); - - 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 - */ -class Context { - constructor(opts) { - this.dir = opts.dir || 'coverage'; - this.watermarks = normalizeWatermarks(opts.watermarks); - this.sourceFinder = opts.sourceFinder || defaultSourceLookup; - this._summarizerFactory = new SummarizerFactory( - opts.coverageMap, - opts.defaultSummarizer - ); - this.data = {}; - } - - /** - * returns a FileWriter implementation for reporting use. Also available - * as the `writer` property on the context. - * @returns {Writer} - */ - getWriter() { - 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 - */ - getSource(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` - */ - classForPercent(type, value) { - const 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} - */ - getXMLWriter(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} - */ - getVisitor(partialVisitor) { - return new tree.Visitor(partialVisitor); - } - - getTree(name = 'defaultSummarizer') { - return this._summarizerFactory[name]; - } -} - -Object.defineProperty(Context.prototype, 'writer', { - enumerable: true, - get() { - if (!this.data.writer) { - this.data.writer = new FileWriter(this.dir); - } - return this.data.writer; - } -}); - -module.exports = Context; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/file-writer.js b/vanilla/node_modules/istanbul-lib-report/lib/file-writer.js deleted file mode 100644 index de1154b..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/file-writer.js +++ /dev/null @@ -1,189 +0,0 @@ -'use strict'; -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -const path = require('path'); -const fs = require('fs'); -const mkdirp = require('make-dir'); -const supportsColor = require('supports-color'); - -/** - * Base class for writing content - * @class ContentWriter - * @constructor - */ -class ContentWriter { - /** - * 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 - */ - colorize(str /*, clazz*/) { - return str; - } - - /** - * writes a string appended with a newline to the destination - * @param {String} str the string to write - */ - println(str) { - this.write(`${str}\n`); - } - - /** - * closes this content writer. Should be called after all writes are complete. - */ - close() {} -} - -/** - * a content writer that writes to a file - * @param {Number} fd - the file descriptor - * @extends ContentWriter - * @constructor - */ -class FileContentWriter extends ContentWriter { - constructor(fd) { - super(); - - this.fd = fd; - } - - write(str) { - fs.writeSync(this.fd, str); - } - - close() { - fs.closeSync(this.fd); - } -} - -// allow stdout to be captured for tests. -let capture = false; -let output = ''; - -/** - * a content writer that writes to the console - * @extends ContentWriter - * @constructor - */ -class ConsoleWriter extends ContentWriter { - write(str) { - if (capture) { - output += str; - } else { - process.stdout.write(str); - } - } - - colorize(str, clazz) { - const colors = { - low: '31;1', - medium: '33;1', - high: '32;1' - }; - - /* istanbul ignore next: different modes for CI and local */ - if (supportsColor.stdout && 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 - */ -class FileWriter { - constructor(baseDir) { - if (!baseDir) { - throw new Error('baseDir must be specified'); - } - this.baseDir = baseDir; - } - - /** - * static helpers for capturing stdout report output; - * super useful for tests! - */ - static startCapture() { - capture = true; - } - - static stopCapture() { - capture = false; - } - - static getOutput() { - return output; - } - - static resetOutput() { - 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} - */ - writerForDir(subdir) { - if (path.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 - * @param {String} [header=undefined] optional text to prepend to destination - * (e.g., an "this file is autogenerated" comment, copyright notice, etc.) - */ - copyFile(source, dest, header) { - if (path.isAbsolute(dest)) { - throw new Error(`Cannot write to absolute path: ${dest}`); - } - dest = path.resolve(this.baseDir, dest); - mkdirp.sync(path.dirname(dest)); - let contents; - if (header) { - contents = header + fs.readFileSync(source, 'utf8'); - } else { - contents = fs.readFileSync(source); - } - fs.writeFileSync(dest, contents); - } - - /** - * 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} - */ - writeFile(file) { - if (file === null || file === '-') { - return new ConsoleWriter(); - } - if (path.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/vanilla/node_modules/istanbul-lib-report/lib/path.js b/vanilla/node_modules/istanbul-lib-report/lib/path.js deleted file mode 100644 index c928b17..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/path.js +++ /dev/null @@ -1,169 +0,0 @@ -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -'use strict'; - -const path = require('path'); -let parsePath = path.parse; -let SEP = path.sep; -const origParser = parsePath; -const origSep = SEP; - -function makeRelativeNormalizedPath(str, sep) { - const parsed = parsePath(str); - let root = parsed.root; - let dir; - let file = parsed.base; - let quoted; - let 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; -} - -class Path { - constructor(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}` - ); - } - } - - toString() { - return this.v.join('/'); - } - - hasParent() { - return this.v.length > 0; - } - - parent() { - if (!this.hasParent()) { - throw new Error('Unable to get parent for 0 elem path'); - } - const p = this.v.slice(); - p.pop(); - return new Path(p); - } - - elements() { - return this.v.slice(); - } - - name() { - return this.v.slice(-1)[0]; - } - - contains(other) { - let 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; - } - - ancestorOf(other) { - return other.contains(this) && other.length !== this.length; - } - - descendantOf(other) { - return this.contains(other) && other.length !== this.length; - } - - commonPrefixPath(other) { - const len = this.length > other.length ? other.length : this.length; - let i; - const 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); - } - - static compare(a, b) { - const al = a.length; - const bl = b.length; - - if (al < bl) { - return -1; - } - - if (al > bl) { - return 1; - } - - const astr = a.toString(); - const bstr = b.toString(); - return astr < bstr ? -1 : astr > bstr ? 1 : 0; - } -} - -['push', 'pop', 'shift', 'unshift', 'splice'].forEach(fn => { - Object.defineProperty(Path.prototype, fn, { - value(...args) { - return this.v[fn](...args); - } - }); -}); - -Object.defineProperty(Path.prototype, 'length', { - enumerable: true, - get() { - return this.v.length; - } -}); - -module.exports = Path; -Path.tester = { - setParserAndSep(p, sep) { - parsePath = p; - SEP = sep; - }, - reset() { - parsePath = origParser; - SEP = origSep; - } -}; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/report-base.js b/vanilla/node_modules/istanbul-lib-report/lib/report-base.js deleted file mode 100644 index 96de750..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/report-base.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -// TODO: switch to class private field when targetting node.js 12 -const _summarizer = Symbol('ReportBase.#summarizer'); - -class ReportBase { - constructor(opts = {}) { - this[_summarizer] = opts.summarizer; - } - - execute(context) { - context.getTree(this[_summarizer]).visit(this, context); - } -} - -module.exports = ReportBase; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/summarizer-factory.js b/vanilla/node_modules/istanbul-lib-report/lib/summarizer-factory.js deleted file mode 100644 index 5e8acd9..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/summarizer-factory.js +++ /dev/null @@ -1,284 +0,0 @@ -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -'use strict'; - -const coverage = require('istanbul-lib-coverage'); -const Path = require('./path'); -const { BaseNode, BaseTree } = require('./tree'); - -class ReportNode extends BaseNode { - constructor(path, fileCoverage) { - super(); - - this.path = path; - this.parent = null; - this.fileCoverage = fileCoverage; - this.children = []; - } - - static createRoot(children) { - const root = new ReportNode(new Path([])); - - children.forEach(child => { - root.addChild(child); - }); - - return root; - } - - addChild(child) { - child.parent = this; - this.children.push(child); - } - - asRelative(p) { - if (p.substring(0, 1) === '/') { - return p.substring(1); - } - return p; - } - - getQualifiedName() { - return this.asRelative(this.path.toString()); - } - - getRelativeName() { - const parent = this.getParent(); - const myPath = this.path; - let relPath; - let i; - const 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()); - } - - getParent() { - return this.parent; - } - - getChildren() { - return this.children; - } - - isSummary() { - return !this.fileCoverage; - } - - getFileCoverage() { - return this.fileCoverage; - } - - getCoverageSummary(filesOnly) { - const cacheProp = `c_${filesOnly ? 'files' : 'full'}`; - let summary; - - if (Object.prototype.hasOwnProperty.call(this, cacheProp)) { - return this[cacheProp]; - } - - if (!this.isSummary()) { - summary = this.getFileCoverage().toSummary(); - } else { - let count = 0; - summary = coverage.createCoverageSummary(); - this.getChildren().forEach(child => { - if (filesOnly && child.isSummary()) { - return; - } - count += 1; - summary.merge(child.getCoverageSummary(filesOnly)); - }); - if (count === 0 && filesOnly) { - summary = null; - } - } - this[cacheProp] = summary; - return summary; - } -} - -class ReportTree extends BaseTree { - constructor(root, childPrefix) { - super(root); - - const maybePrefix = node => { - if (childPrefix && !node.isRoot()) { - node.path.unshift(childPrefix); - } - }; - this.visit({ - onDetail: maybePrefix, - onSummary(node) { - maybePrefix(node); - node.children.sort((a, b) => { - const astr = a.path.toString(); - const bstr = b.path.toString(); - return astr < bstr - ? -1 - : astr > bstr - ? 1 - : /* istanbul ignore next */ 0; - }); - } - }); - } -} - -function findCommonParent(paths) { - return paths.reduce( - (common, path) => common.commonPrefixPath(path), - paths[0] || new Path([]) - ); -} - -function findOrCreateParent(parentPath, nodeMap, created = () => {}) { - let parent = nodeMap[parentPath.toString()]; - - if (!parent) { - parent = new ReportNode(parentPath); - nodeMap[parentPath.toString()] = parent; - created(parentPath, parent); - } - - return parent; -} - -function toDirParents(list) { - const nodeMap = Object.create(null); - list.forEach(o => { - const parent = findOrCreateParent(o.path.parent(), nodeMap); - parent.addChild(new ReportNode(o.path, o.fileCoverage)); - }); - - return Object.values(nodeMap); -} - -function addAllPaths(topPaths, nodeMap, path, node) { - const parent = findOrCreateParent( - path.parent(), - nodeMap, - (parentPath, parent) => { - if (parentPath.hasParent()) { - addAllPaths(topPaths, nodeMap, parentPath, parent); - } else { - topPaths.push(parent); - } - } - ); - - parent.addChild(node); -} - -function foldIntoOneDir(node, parent) { - const { children } = node; - if (children.length === 1 && !children[0].fileCoverage) { - children[0].parent = parent; - return foldIntoOneDir(children[0], parent); - } - node.children = children.map(child => foldIntoOneDir(child, node)); - return node; -} - -function pkgSummaryPrefix(dirParents, commonParent) { - if (!dirParents.some(dp => dp.path.length === 0)) { - return; - } - - if (commonParent.length === 0) { - return 'root'; - } - - return commonParent.name(); -} - -class SummarizerFactory { - constructor(coverageMap, defaultSummarizer = 'pkg') { - this._coverageMap = coverageMap; - this._defaultSummarizer = defaultSummarizer; - this._initialList = coverageMap.files().map(filePath => ({ - filePath, - path: new Path(filePath), - fileCoverage: coverageMap.fileCoverageFor(filePath) - })); - this._commonParent = findCommonParent( - this._initialList.map(o => o.path.parent()) - ); - if (this._commonParent.length > 0) { - this._initialList.forEach(o => { - o.path.splice(0, this._commonParent.length); - }); - } - } - - get defaultSummarizer() { - return this[this._defaultSummarizer]; - } - - get flat() { - if (!this._flat) { - this._flat = new ReportTree( - ReportNode.createRoot( - this._initialList.map( - node => new ReportNode(node.path, node.fileCoverage) - ) - ) - ); - } - - return this._flat; - } - - _createPkg() { - const dirParents = toDirParents(this._initialList); - if (dirParents.length === 1) { - return new ReportTree(dirParents[0]); - } - - return new ReportTree( - ReportNode.createRoot(dirParents), - pkgSummaryPrefix(dirParents, this._commonParent) - ); - } - - get pkg() { - if (!this._pkg) { - this._pkg = this._createPkg(); - } - - return this._pkg; - } - - _createNested() { - const nodeMap = Object.create(null); - const topPaths = []; - this._initialList.forEach(o => { - const node = new ReportNode(o.path, o.fileCoverage); - addAllPaths(topPaths, nodeMap, o.path, node); - }); - - const topNodes = topPaths.map(node => foldIntoOneDir(node)); - if (topNodes.length === 1) { - return new ReportTree(topNodes[0]); - } - - return new ReportTree(ReportNode.createRoot(topNodes)); - } - - get nested() { - if (!this._nested) { - this._nested = this._createNested(); - } - - return this._nested; - } -} - -module.exports = SummarizerFactory; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/tree.js b/vanilla/node_modules/istanbul-lib-report/lib/tree.js deleted file mode 100644 index 7c18204..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/tree.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -'use strict'; - -/** - * 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 - */ -class Visitor { - constructor(delegate) { - this.delegate = delegate; - } -} - -['Start', 'End', 'Summary', 'SummaryEnd', 'Detail'] - .map(k => `on${k}`) - .forEach(fn => { - Object.defineProperty(Visitor.prototype, fn, { - writable: true, - value(node, state) { - if (typeof this.delegate[fn] === 'function') { - this.delegate[fn](node, state); - } - } - }); - }); - -class CompositeVisitor extends Visitor { - constructor(visitors) { - super(); - - if (!Array.isArray(visitors)) { - visitors = [visitors]; - } - this.visitors = visitors.map(v => { - if (v instanceof Visitor) { - return v; - } - return new Visitor(v); - }); - } -} - -['Start', 'Summary', 'SummaryEnd', 'Detail', 'End'] - .map(k => `on${k}`) - .forEach(fn => { - Object.defineProperty(CompositeVisitor.prototype, fn, { - value(node, state) { - this.visitors.forEach(v => { - v[fn](node, state); - }); - } - }); - }); - -class BaseNode { - isRoot() { - return !this.getParent(); - } - - /** - * 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 - */ - visit(visitor, state) { - if (this.isSummary()) { - visitor.onSummary(this, state); - } else { - visitor.onDetail(this, state); - } - - this.getChildren().forEach(child => { - child.visit(visitor, state); - }); - - if (this.isSummary()) { - visitor.onSummaryEnd(this, state); - } - } -} - -/** - * abstract base class for a coverage tree. - * @constructor - */ -class BaseTree { - constructor(root) { - this.root = root; - } - - /** - * returns the root node of the tree - */ - getRoot() { - return this.root; - } - - /** - * 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 - */ - visit(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 = { - BaseTree, - BaseNode, - Visitor, - CompositeVisitor -}; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/watermarks.js b/vanilla/node_modules/istanbul-lib-report/lib/watermarks.js deleted file mode 100644 index fb76082..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/watermarks.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -module.exports = { - getDefault() { - return { - statements: [50, 80], - functions: [50, 80], - branches: [50, 80], - lines: [50, 80] - }; - } -}; diff --git a/vanilla/node_modules/istanbul-lib-report/lib/xml-writer.js b/vanilla/node_modules/istanbul-lib-report/lib/xml-writer.js deleted file mode 100644 index a32550e..0000000 --- a/vanilla/node_modules/istanbul-lib-report/lib/xml-writer.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; -/* - Copyright 2012-2015, Yahoo Inc. - Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -const INDENT = ' '; - -function attrString(attrs) { - return Object.entries(attrs || {}) - .map(([k, v]) => ` ${k}="${v}"`) - .join(''); -} - -/** - * a utility class to produce well-formed, indented XML - * @param {ContentWriter} contentWriter the content writer that this utility wraps - * @constructor - */ -class XMLWriter { - constructor(contentWriter) { - this.cw = contentWriter; - this.stack = []; - } - - indent(str) { - return this.stack.map(() => 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 - */ - openTag(name, attrs) { - const 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. - */ - closeTag(name) { - if (this.stack.length === 0) { - throw new Error(`Attempt to close tag ${name} when not opened`); - } - const stashed = this.stack.pop(); - const 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 - */ - inlineTag(name, attrs, content) { - let 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 - */ - closeAll() { - this.stack - .slice() - .reverse() - .forEach(name => { - this.closeTag(name); - }); - } -} - -module.exports = XMLWriter; |
