Files
nodejs.esm-library/source/text/basic-tree.mjs

65 lines
2.0 KiB
JavaScript

import { string_has_contents, indented_line_iterator } from '@efforting.tech/data/string-utilities';
export class Text_Node {
constructor(text_settings, line=undefined, indent=0, line_no=undefined, index=undefined, raw=undefined, parent=undefined) {
Object.assign(this, { text_settings, line, indent, line_no, index, raw, parent, children: [] });
}
static from_string(text_settings, str) {
const root = new this(text_settings);
// NOTE: This first Text_Node is not added to the tree, it serves as an initial cursor only.
let current = new this(root.text_settings, undefined, 0, undefined, undefined, undefined, root);
for (const line_info of indented_line_iterator(text_settings, str)) {
// TODO: Implement other variants than inherit-from-previous
const indent = string_has_contents(line_info.line) ? line_info.indent : current.indent;
const delta_indent = indent - current.indent;
if (delta_indent == 0) {
const pending = new Text_Node(current.text_settings, undefined, current.indent, undefined, undefined, undefined, current.parent); // Partial insertion - same level
if (current.parent) {
current.parent.children.push(pending);
}
current = pending;
} else if (delta_indent > 0) {
for (let i=0; i<delta_indent; i++) {
const pending = new Text_Node(current.text_settings, undefined, current.indent + 1, undefined, undefined, undefined, current); // Partial insertion
current.children.push(pending);
current = pending;
}
} else {
for (let i=0; i>delta_indent; i--) {
current = current.parent;
}
const pending = new Text_Node(current.text_settings, undefined, current.indent, undefined, undefined, undefined, current.parent); // Partial insertion - same level
if (current.parent) {
current.parent.children.push(pending);
}
current = pending;
}
// Fill in partial insertion
Object.assign(current, {
line: line_info.line,
line_no: line_info.line_no,
index: line_info.index,
raw: line_info.raw,
});
}
return root;
}
}