sec-edgar-api
Version:
Fetch and parse SEC earnings reports and other filings. Useful for financial analysis.
188 lines (187 loc) • 9.44 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.RowNode = void 0;
var ColNode_1 = require("./ColNode");
var XMLNode_1 = require("./XMLNode");
var RowNode = /** @class */ (function (_super) {
__extends(RowNode, _super);
function RowNode() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.isHeader = false;
_this.isEmpty = null;
return _this;
}
RowNode.prototype.getIsEmpty = function () {
if (this.isEmpty !== null)
return this.isEmpty;
this.isEmpty = this.toArray().filter(Boolean).length === 0;
return Boolean(this.isEmpty);
};
RowNode.prototype.clone = function () {
var clone = new RowNode({ attributesStr: this.getAttributesStr(), path: this.getPath() });
clone.setText(this.getText());
this.getChildren().forEach(function (child) {
var childNew = new ColNode_1.ColNode({ attributesStr: child.getAttributesStr(), path: child.getPath() });
var prevChild = clone.getChildren()[clone.getChildren().length - 1];
childNew.setText(child.getText());
childNew.setIndex(child.getIndex());
prevChild === null || prevChild === void 0 ? void 0 : prevChild.setNextSibling(childNew);
clone.addChild(childNew);
});
return clone;
};
RowNode.prototype.setIsHeader = function (isHeader) {
this.isHeader = isHeader;
};
RowNode.prototype.getIsHeader = function () {
return this.isHeader;
};
RowNode.prototype.getChildren = function () {
return _super.prototype.getChildren.call(this);
};
RowNode.prototype.getParent = function () {
return _super.prototype.getParent.call(this);
};
RowNode.prototype.getNextSibling = function () {
return _super.prototype.getNextSibling.call(this);
};
RowNode.prototype.getPreviousSibling = function () {
return _super.prototype.getPreviousSibling.call(this);
};
/**
* Uses the columns in this row to build a table. Each column is also an array since cols can touch
* multiple other cells on the top and bottom due to colspan.
*
* ```ts
* const returnExample = [
* [ [ColNode, ColNode], [ColNode], [ColNode, ColNode, ColNode] ]
* [ [ColNode], [ColNode], [ColNode] ], // this row
* [ [ColNode], [ColNode], [ColNode, ColNode] ],
* ]
* ```
*/
RowNode.prototype.getTableFromCols = function () {
var _a, _b, _c;
var colIndexRanges = this.getChildren().map(function (col) { return [col.getIndex(), col.getIndex() + col.getColSpan()]; });
var rows = this.getParent().getChildren();
var tableRowCols = rows.map(function () { return colIndexRanges.map(function () { return []; }); });
for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
var row = rows[rowIndex];
var colsShift = 0;
var _loop_1 = function (col) {
var _e = [col.getIndex(), col.getIndex() + col.getColSpan()], indexStart = _e[0], indexEnd = _e[1];
// // TODO: Instead of shifting cols here, just shift them in XMLParser when they are created
while ((_a = tableRowCols[rowIndex][colsShift]) === null || _a === void 0 ? void 0 : _a.some(function (c) { return c.getParent() !== col.getParent(); })) {
colsShift++;
}
// tableRowCols
for (var i = 0; i < colIndexRanges.length; i++) {
var _f = colIndexRanges[i], boundaryStart = _f[0], boundaryEnd = _f[1];
if (indexEnd <= boundaryStart || indexStart >= boundaryEnd)
continue;
for (var j = rowIndex; j < rowIndex + col.getRowSpan(); j++) {
(_c = (_b = tableRowCols[j]) === null || _b === void 0 ? void 0 : _b[i + colsShift]) === null || _c === void 0 ? void 0 : _c.push(col);
}
}
};
for (var _i = 0, _d = row.getChildren(); _i < _d.length; _i++) {
var col = _d[_i];
_loop_1(col);
}
}
return tableRowCols;
};
RowNode.prototype.toTable = function (parseValues) {
var _a, _b, _c;
if (parseValues === void 0) { parseValues = true; }
var table = this.getTableFromCols();
var tableTextArr = [];
var headerRowIndex = (_a = this.getParent().getHeaderRowIndex()) !== null && _a !== void 0 ? _a : -1;
for (var rowIndex = 0; rowIndex < table.length; rowIndex++) {
var row = table[rowIndex];
var colTextArr = [];
for (var _i = 0, row_1 = row; _i < row_1.length; _i++) {
var colArr = row_1[_i];
var colText = colArr.reduce(function (acc, col) { return "".concat(acc, " ").concat(col.getText()); }, '');
// skip rows that are titles within the table body
var isTitleRow = colArr.length === 1 &&
colArr[0].getColSpan() >= this.getChildren().length &&
rowIndex > headerRowIndex;
if (isTitleRow)
continue;
if (!parseValues) {
colTextArr.push(colText.trim());
continue;
}
// sometimes there is a rogue percent sign that is not in a column, so we need to check the next column
var nextCol = (_b = colArr[colArr.length - 1]) === null || _b === void 0 ? void 0 : _b.getNextSibling();
var isMissingPercentSign = (nextCol === null || nextCol === void 0 ? void 0 : nextCol.getText().includes('%')) && nextCol.parseValue() === null;
var isMissingParenthesis = (nextCol === null || nextCol === void 0 ? void 0 : nextCol.getText().includes(')')) && colText.includes('(') && !colText.includes(')');
var colValue = isMissingParenthesis ? "".concat(colText.trim(), ")") : colText.trim();
colValue = isMissingPercentSign ? "".concat(colText.trim(), "%") : colText.trim();
colValue = this.parseValue(colValue);
colValue = typeof colValue === 'string' ? colValue.replace(/\s+/g, ' ') : colValue;
colTextArr.push(colValue);
}
tableTextArr.push(colTextArr);
}
if (!parseValues)
return tableTextArr;
var emptyColIndexes = new Set();
cols: for (var colIndex = 0; colIndex < tableTextArr[0].length; colIndex++) {
for (var rowIndex = 1; rowIndex < tableTextArr.length; rowIndex++) {
if (Boolean(tableTextArr[rowIndex][colIndex]) && tableTextArr[rowIndex][colIndex] !== '%') {
continue cols;
}
}
emptyColIndexes.add(colIndex);
}
tableTextArr.forEach(function (row, i) {
tableTextArr[i] = row.filter(function (_, i) { return !emptyColIndexes.has(i); });
});
var tableTextArrFiltered = [];
for (var rowIndex = 0; rowIndex < tableTextArr.length; rowIndex++) {
var row = tableTextArr[rowIndex];
var isEmpty = !row.some(Boolean);
// if is empty before the header or empty next to another empty row, continue
if (isEmpty && (rowIndex < headerRowIndex || !((_c = tableTextArr[rowIndex - 1]) === null || _c === void 0 ? void 0 : _c.some(Boolean)))) {
continue;
}
tableTextArrFiltered.push(row);
}
return tableTextArr.filter(function (row, i) {
var rowPrev = tableTextArr[i - 1];
var isEmpty = !row.some(Boolean);
var isLast = i === tableTextArr.length - 1;
// empty rows cannot be before header, last in array, or next to another empty row
return !(isEmpty && (i < headerRowIndex || !(rowPrev === null || rowPrev === void 0 ? void 0 : rowPrev.some(Boolean)) || isLast));
});
};
RowNode.prototype.toArray = function (parseValues) {
var _this = this;
if (parseValues === void 0) { parseValues = true; }
var cols = [];
this.getChildren().forEach(function (col) {
cols.push(parseValues ? _this.parseValue(col.getText()) : col.getText());
Array.from({ length: col.getColSpan() - 1 }).forEach(function () { return cols.push(null); });
});
return cols;
};
return RowNode;
}(XMLNode_1.XMLNode));
exports.RowNode = RowNode;