lines-builder
Version:
Tool and model to handle string lines and indentation.
205 lines • 7.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.lines = exports.resetDefaultOptions = exports.setDefaultOptions = exports.LinesBuilder = exports.splitToLines = void 0;
const os = require("os");
const debug = require("debug");
const log = debug("lines-builder");
function splitToLines(s) {
return s.split(/\r?\n\r?/g);
}
exports.splitToLines = splitToLines;
const DEFAULT_OPTIONS = {
indent: null,
trimLeft: true,
trimRight: true,
indentEmpty: false,
skipFirstLevelIndent: false,
skipEmpty: false,
eol: null,
};
class LinesBuilder {
get length() {
return this.lines.length;
}
constructor(...args) {
this.lines = [];
log("LinesBuilder(args: %o)", args);
let options;
if (args[0] && typeof args[0] === "object" && !(args[0] instanceof LinesBuilder)) {
options = args.shift();
}
this.options = Object.assign(Object.assign({}, LinesBuilder.DEFAULT_OPTIONS), (options || {}));
log("LinesBuilder.options: %o", this.options);
if (typeof this.options.indent === "number") {
this.options.indent = " ".repeat(Math.max(0, this.options.indent));
}
log("LinesBuilder.options: %o", this.options);
this.lines = this.parseLines(args);
log("LinesBuilder.lines: %o", this.lines);
}
static resetDefaultOptions() {
log("resetDefaultOptions.prev: %o", LinesBuilder.DEFAULT_OPTIONS);
LinesBuilder.DEFAULT_OPTIONS = Object.assign({}, DEFAULT_OPTIONS);
log("resetDefaultOptions.new: %o", LinesBuilder.DEFAULT_OPTIONS);
return LinesBuilder.DEFAULT_OPTIONS;
}
static setDefaultOptions(options) {
log("setDefaultOptions(options: %o)", options);
if (typeof options !== "object" || !options) {
throw new TypeError("Options must be a LinesBuilderOptions!");
}
log("setDefaultOptions.prev: %o", LinesBuilder.DEFAULT_OPTIONS);
LinesBuilder.DEFAULT_OPTIONS = Object.assign(Object.assign({}, LinesBuilder.DEFAULT_OPTIONS), options);
log("setDefaultOptions.next: %o", LinesBuilder.DEFAULT_OPTIONS);
return LinesBuilder.DEFAULT_OPTIONS;
}
parseLines(ls) {
log("parseLines(ls: %o)", ls);
const parsedLines = [];
for (const line of ls) {
log("parseLines.line: %o", line);
if (typeof line === "string") {
let splitedLines = splitToLines(line);
if (this.options.trimLeft) {
splitedLines = splitedLines.map(l => l.trimLeft());
}
if (this.options.trimRight) {
splitedLines = splitedLines.map(l => l.trimRight());
}
parsedLines.push(...splitedLines);
}
else if (line instanceof LinesBuilder || line === null) {
parsedLines.push(line);
}
log("parseLines.parsedLines: %o", parsedLines);
}
return parsedLines;
}
toString() {
var _a;
log("toString:lines: %o", this.lines);
const ls = [];
const indent = (_a = this.options.indent) !== null && _a !== void 0 ? _a : "";
const firstIndent = this.options.skipFirstLevelIndent ? "" : indent;
log("toString.indent: %o", indent);
for (const line of this.lines) {
log("toString.line: %o", line);
if (typeof line === "string" && line) {
ls.push(`${firstIndent}${line}`);
}
else if (line instanceof LinesBuilder) {
const nestedLines = splitToLines(line.toString());
for (const l of nestedLines) {
if (l) {
ls.push(`${indent}${l}`);
}
else if (!this.options.skipEmpty) {
ls.push(this.options.indentEmpty ? indent : "");
}
}
}
else if (!this.options.skipEmpty) {
ls.push(this.options.indentEmpty ? indent : "");
}
log("toString.ls: %o", ls);
}
let eol = this.options.eol;
if (!eol) {
log("toString.platform: %s", os.platform());
eol = os.platform() == "win32" ? "\r\n" : "\n";
}
log("toString.eol: %o", eol);
return ls.join(eol);
}
copy() {
log("copy:lines: %o", this.lines);
const copied = new LinesBuilder(this.options);
for (const line of this.lines) {
log("copy.line: %o", line);
if (line instanceof LinesBuilder) {
copied.append(line.copy());
}
else {
copied.append(line);
}
}
return copied;
}
append(...ls) {
log("append(ls: %o)", ls);
log("append.#lines: %d", this.lines.length);
ls = this.parseLines(ls);
this.lines.push(...ls);
log("append.#lines: %d", this.lines.length);
return this;
}
prepend(...ls) {
log("prepend(ls: %o)", ls);
log("prepend.#lines: %d", this.lines.length);
ls = this.parseLines(ls);
this.lines.unshift(...ls);
log("prepend.#lines: %d", this.lines.length);
return this;
}
filter(matcher, reverse = false, inPlace = true) {
log("filter(matcher: %o, reverse: %b, inPlace: %b)", matcher, reverse, inPlace);
if (!matcher) {
throw new TypeError("Matcher must be set!");
}
if (typeof matcher === "string") {
matcher = new RegExp(matcher, "i");
}
let matcherFn;
if (matcher instanceof RegExp) {
matcherFn = (line, _) => matcher.test(line);
}
else {
matcherFn = matcher;
}
const toFilter = inPlace ? this : this.copy();
toFilter.lines = toFilter.lines.filter((line, i) => {
if (line instanceof LinesBuilder) {
log("filter.nested(original: %d)", line.length);
line.filter(matcherFn, reverse);
log("filter.nested(result: %d)", line.length);
return line.length > 0;
}
const result = matcherFn(line, i);
log("filter.string(result: %b)", result);
return !!result !== !!reverse;
});
return toFilter;
}
internalMap(mapper, level) {
log("internalMap(mapper: %o, level: %d)", mapper, level);
this.lines = this.lines.map((line, i) => {
if (line instanceof LinesBuilder) {
log("internalMap.nested(original: %d)", line.length);
line.internalMap(mapper, level + 1);
return line;
}
return mapper(line, i, level);
});
}
map(mapper, inPlace = true) {
log("map(mapper: %o, inPlace: %b)", mapper, inPlace);
if (!mapper) {
throw new TypeError("Mapper must be set!");
}
if (typeof mapper !== "function") {
throw new TypeError("Mapper must be a function!");
}
const toMap = inPlace ? this : this.copy();
toMap.internalMap(mapper, 0);
return toMap;
}
}
exports.LinesBuilder = LinesBuilder;
LinesBuilder.DEFAULT_OPTIONS = Object.assign({}, DEFAULT_OPTIONS);
exports.setDefaultOptions = LinesBuilder.setDefaultOptions;
exports.resetDefaultOptions = LinesBuilder.resetDefaultOptions;
function lines(...args) {
return new LinesBuilder(...args);
}
exports.lines = lines;
//# sourceMappingURL=index.js.map