feat: Add Be and tbd skill, also added Roadmap file

This commit is contained in:
2026-05-10 16:32:12 -04:00
parent 3500ade13f
commit 0bb8885802
29587 changed files with 10611695 additions and 0 deletions

545
Skills/@be/node_modules/jibo-node-xml/src/Node.ts generated vendored Normal file
View File

@@ -0,0 +1,545 @@
/**
* @enum {String}
*/
export class NodeType {
static TEXT = 'TEXT';
static ROOT = 'ROOT';
}
export interface NodeHandler {
(n: Node): void;
}
export interface NodeFilter {
(n: Node): boolean;
}
export type AttType = string | boolean | number;
export default class Node { // jshint ignore:line
children: Node[] = [];
/**
* Ancestor nodes of the current node. Can possess multiple
* parents.
* @type {Array.<Node>}
*/
parents: Node[] = [];
/**
* Attributes of the node, defined in XML as `<tag attribute="value">`,
* where the key is the attribute name.
* @type {Object.<String:String>}
*/
att = new Map<string, AttType>();
/**
* The name of the tag. e.g. `<foo/>` would return `foo`.
* Only set on nodes that are parsed from XML text
* @type {String}
*/
tagName: string = null;
/**
* @param {NodeType} type The type the current node is.
* @param {String} value The value stored in this current node.
* @constructor
*/
constructor(public type: string, public value?: string) {
}
/**
* @param {NodeType} type The type of node being created.
* @param {String} value The value stored in this node.
*/
cloneShallow() {
let n = new Node(this.type);
this.att.forEach( (val, key) => {
n.setAttribute(key, val);
});
return n;
}
/**
* @return {Node} A copy of the current node its entire sub-tree.
*/
cloneDeep() {
let n = new Node(this.type);
this.att.forEach( (val, key) => {
n.setAttribute(key, val);
});
this.children.forEach(c => {
let newC = c.cloneDeep();
n.addChild(newC);
});
return n;
}
/**
* Returns the value of an attribute given its name.
* @param {String} name The name of the attribute.
* @return {AttType} The value of the attribute.
*/
getAttribute(name:string): AttType {
return this.att.get(name);
}
/**
* Returns a numeric attribute.
* @param {String} name The name of the attribute.
* @return {number} The value of the attribute.
*/
getNumberAtt(name:string): number {
let val = this.att.get(name);
let type = typeof val;
if (type === 'string') {
return Number.parseFloat(val as string);
}
else {
return (val as number);
}
}
/**
* Returns the value of an attribute given its name.
* @param {String} name The name of the attribute.
* @param {String} value The name of the attribute.
*/
setAttribute(name:string, value: AttType) {
this.att.set(name, value);
}
/**
* Returns the value of an attribute given its name.
* @param {String} name The name of the attribute.
* @param {Function.<AttType>} modifier A modifier function.
*/
modifyAttribute(name:string, modifier: (oldVal:AttType) => AttType) {
let oldVal = this.getAttribute(name);
let newVal = modifier(oldVal);
this.setAttribute(name, newVal);
}
/**
* Whether or not the current node is a terminal leaf node without any
* children.
* @return {Boolean} If the current node is a terminal leaf node.
*/
isLeaf() {
return this.children.length === 0;
}
/**
* Attaches a child node to the current one.
* @param {Node} node Node to attach as a child.
*/
addChild(node) {
this.children.push(node);
node.parents.push(this);
}
/**
* Removes all the parents to the current node.
*/
clearParents() {
this.parents = [];
}
/**
* Disconnects all the child nodes from this current node.
*/
removeAllChildren() {
// Remove us as parent of all children
this.children.forEach(c => {
let found = false;
for (let i = 0; i < c.parents.length; i++) {
if (c.parents[i] === this) {
c.parents.splice(i, 1);
found = true;
break;
}
}
if (!found) {
throw Error('Didn\'t find this in child\'s parent list');
}
});
this.children = [];
}
/**
* Removes a child node from the current node.
* @param {Node} child Child node to remove.
*/
removeChild(child) {
// Remove child
let found = false;
for (let i = 0; i < this.children.length; i++) {
if (this.children[i] === child) {
this.children.splice(i, 1);
found = true;
break;
}
}
if (!found) {
throw Error('Didn\'t find child children list');
}
// Remove parent
found = false;
for (let i = 0; i < child.parents.length; i++) {
if (child.parents[i] === this) {
child.parents.splice(i, 1);
found = true;
break;
}
}
if (!found) {
throw Error('Didn\'t find this in child\'s parent list');
}
}
/**
* Returns the first child that matches a given filter criteria.
* @param {Function} filter Function to determine if child meets criteria.
* @return {?Node} The first child node to meet the criteria or none.
*/
findFirstChild(filter: NodeFilter): Node {
for (let i = 0; i < this.children.length; i++) {
let node = this.children[i];
if (filter(node)) { return node; }
}
}
findFirstChildType(type: string, filter?: NodeFilter): Node {
if (filter) {
return this.findFirstChild(n => n.type === type && filter(n));
}
else {
return this.findFirstChild(n => n.type === type);
}
}
findFirstDescendant(filter: NodeFilter): Node {
for (let i = 0; i < this.children.length; i++) {
let node = this.children[i];
let res = node._findFirstDescendantRec(filter);
if (res) {
return res;
}
}
}
_findFirstDescendantRec(filter: NodeFilter): Node {
if (filter(this)) {
return this;
}
for (let i = 0; i < this.children.length; i++) {
let node = this.children[i];
let res = node._findFirstDescendantRec(filter);
if (res) { return res; }
}
}
findFirstDescendantType(type: string, filter?: NodeFilter): Node {
if (filter) {
return this.findFirstDescendant(n => n.type === type && filter(n));
}
else {
return this.findFirstDescendant(n => n.type === type);
}
}
findFirstParent(filter: NodeFilter): Node {
for (let i = 0; i < this.parents.length; i++) {
let node = this.parents[i];
if (filter(node)) {
return node;
}
}
}
findFirstParentType(type: string, filter?: NodeFilter): Node {
if (filter) {
return this.findFirstParent(n => n.type === type && filter(n));
}
else {
return this.findFirstParent(n => n.type === type);
}
}
findFirstAncestor(filter: NodeFilter): Node {
for (let i = 0; i < this.parents.length; i++) {
let node = this.parents[i];
let res = node._findFirstAncestorRec(filter);
if (res) {
return res;
}
}
}
_findFirstAncestorRec(filter: NodeFilter): Node {
if (filter(this)) {
return this;
}
for (let i = 0; i < this.parents.length; i++) {
let node = this.parents[i];
let res = node._findFirstAncestorRec(filter);
if (res) {
return res;
}
}
}
findFirstAncestorType(type: string, filter?: NodeFilter): Node {
if (filter) {
return this.findFirstAncestor(n => n.type === type && filter(n));
}
else {
return this.findFirstAncestor(n => n.type === type);
}
}
forEachAncestor(handler: NodeHandler, filter?: NodeFilter) {
for (let i = 0; i < this.parents.length; i++) {
this.parents[i]._forEachAncestorRecursive(handler, filter);
}
}
_forEachAncestorRecursive(handler: NodeHandler, filter?: NodeFilter) {
if (!filter || filter(this)){
handler(this);
}
for (let i = 0; i < this.parents.length; i++) {
this.parents[i]._forEachAncestorRecursive(handler, filter);
}
}
forEachAncestorType(type: string, handler: NodeHandler, filter?: NodeFilter) {
if (filter){
this.forEachAncestor(handler, n => (n.type === type) && filter(n));
}
else {
this.forEachAncestor(handler, n => n.type === type);
}
}
/**
* Iterates through all Descendants of node
* @param {Function} handler
* @param {Function} [filter]
*/
forEachDescendant(handler: NodeHandler, filter?: NodeFilter) {
for (let i = 0; i < this.children.length; i++) {
this.children[i]._forEachDescendantRecursive(handler, filter);
}
}
_forEachDescendantRecursive(handler: NodeHandler, filter?: NodeFilter) {
if (!filter || filter(this)){
handler(this);
}
for (let i = 0; i < this.children.length; i++) {
this.children[i]._forEachDescendantRecursive(handler, filter);
}
}
forEachDescendantType(type: string, handler: NodeHandler, filter?: NodeFilter) {
if (filter){
this.forEachDescendant(handler, n => (n.type === type) && filter(n));
}
else {
this.forEachDescendant(handler, n => n.type === type);
}
}
gatherChildren(filter?: NodeFilter): Node[] {
let out = [];
this.forEachChild(node => {
out.push(node);
}, filter);
return out;
}
gatherChildrenType(type: string, filter?: NodeFilter): Node[] {
if (filter) {
return this.gatherChildren(n => n.type === type && filter(n));
} else {
return this.gatherChildren(n => n.type === type);
}
}
/**
* @param {Function} filter Filtering function to apply to each node to
* determine if the node should be included in the returned list by
* returning true.
* @return {List.<Node>}
*/
gatherDescendants(filter?: NodeFilter): Node[] {
let out = [];
this.forEachDescendant(node => {
out.push(node);
}, filter);
return out;
}
gatherDescendantsType(type: string, filter?: NodeFilter): Node[] {
if (filter) {
return this.gatherDescendants(n => n.type === type && filter(n));
} else {
return this.gatherDescendants(n => n.type === type);
}
}
gatherParents(filter?: NodeFilter): Node[] {
let out = [];
this.forEachParent(node => {
out.push(node);
}, filter);
return out;
}
gatherParentsType(type: string, filter?: NodeFilter): Node[] {
if (filter) {
return this.gatherParents(n => n.type === type && filter(n));
} else {
return this.gatherParents(n => n.type === type);
}
}
gatherAncestors(filter?: NodeFilter): Node[] {
let out = [];
this.forEachAncestor(node => {
out.push(node);
}, filter);
return out;
}
gatherAncestorsType(type: string, filter?: NodeFilter): Node[] {
if (filter) {
return this.gatherAncestors(n => n.type === type && filter(n));
} else {
return this.gatherAncestors(n => n.type === type);
}
}
forEachChildType(type: string, handler: NodeHandler, filter?: NodeFilter) {
if (filter) {
this.forEachChild(handler, n => n.type === type && filter(n));
} else {
this.forEachChild(handler, n => n.type === type);
}
}
forEachChild(handler: NodeHandler, filter?: NodeFilter) {
for (let i = 0; i < this.children.length; i++) {
let o = this.children[i];
if (!filter || filter(o)) {
handler(o);
}
}
}
forEachParentType(type: string, handler: NodeHandler, filter?: NodeFilter) {
if (filter) {
this.forEachParent(handler, n => n.type === type && filter(n));
} else {
this.forEachParent(handler, n => n.type === type);
}
}
forEachParent(handler: NodeHandler, filter?: NodeFilter) {
for (let i = 0; i < this.parents.length; i++) {
let o = this.parents[i];
if (!filter || filter(o)) {
handler(o);
}
}
}
toStringClosingTag() {
return `</${this.type}>`;
}
toStringTagOnly(indents = 0) {
let str = '';
for (let i = 0; i < indents; i++ ) {
str += ' ';
}
str += `<${this.type}`;
this.att.forEach( (value, key) => {
str += ` ${key}="${value}"`;
});
if(this.value) {
str += ` value="${this.value}"`;
}
if (!this.children.length) {
str += `/>`;
}
else {
str += `>`;
}
return str;
}
/**
* Prints the current tree.
* @param {Boolean} [hierarchy]
* @param {Number} [indents]
* @return {String}
* @override
*/
toString(hierarchy=false, indents=0) {
//let str = `<type='${this.type}', numChildren=${this.children.length}`;
let str = this.toStringTagOnly(indents);
if (this.children.length) {
this.children.forEach(c => {
if (hierarchy) { str += '\n'; }
str += c.toString(hierarchy, indents+4);
});
if (hierarchy){
str += '\n';
for (let i = 0; i < indents; i++ ) { str += ' '; }
}
str += this.toStringClosingTag();
}
return str;
}
toStringHierarchy() {
let lines = [];
this._toStringHierarchy(0, lines);
return lines.join('\n');
}
_toStringHierarchy(indents, lines) {
let str = '';
for (let i = 0; i < indents; i++ ) { str += ' '; }
str += this.toString();
if (this.children.length) {
str += ', children=';
lines.push(str);
this.children.forEach(c => c._toStringHierarchy(indents+4, lines));
}
else {
lines.push(str);
}
}
}

111
Skills/@be/node_modules/jibo-node-xml/src/Parser.ts generated vendored Normal file
View File

@@ -0,0 +1,111 @@
import Node from './Node';
import { NodeType } from './Node';
export enum PhraseType { END, START, TEXT };
export class Phrase {
constructor(public type: PhraseType, public value: string) { }
}
export default class Parser {
/**
* Parses an XML string to produce a tree structure.
* @param {String} input XML string input to transform into a tree.
* @return {Node} The tree containing the parsed XML.
*/
static parseXML(input: string): Node {
let terms = input.split('<');
let firstText = terms[0].trim();
let phrases: Phrase[] = [];
if (firstText.length) {
phrases.push(new Phrase(PhraseType.TEXT, firstText));
}
for (let i = 1; i < terms.length; i++) {
let terms2 = terms[i].split('>');
if (terms2.length !== 2) { throw Error('Parsing error'); }
let tag = terms2[0];
let text = terms2[1];
if (tag[0] === '/') {
phrases.push(new Phrase(PhraseType.END, tag.substr(1)));
}
else {
phrases.push(new Phrase(PhraseType.START, tag));
}
if (text.length) {
phrases.push(new Phrase(PhraseType.TEXT, text));
}
}
let root = new Node(NodeType.ROOT);
Parser._parseXMLInternal(phrases, 0, undefined, root);
return root;
}
static _parseXMLInternal(phrases: Phrase[], index: number, inputTagName: string, parent: Node): number {
for (let i = index; i < phrases.length; i++) {
let phrase = phrases[i];
if (phrase.type === PhraseType.START) {
// If this is a closing tag also
let isClosing = phrase.value[phrase.value.length-1] === '/';
if (isClosing) {
phrase.value = phrase.value.substr(0, phrase.value.length - 1).trim();
}
// Break up the tag
let tagNameMatches = phrase.value.match(/([\w-]+)(?=\b)/g);
let tagName = (tagNameMatches && tagNameMatches.length > 0) ? tagNameMatches[0] : '';
let terms = phrase.value.match(/(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g) || [];
let newNode = new Node(tagName);
newNode.tagName = tagName.trim();
// Parse att
for (let k = 0; k < terms.length; k++) {
let keyVal = terms[k].trim().split('=');
if (keyVal.length !== 2) {
throw Error('Parsing error, incorrect key value pair');
}
let attVal = keyVal[1];
if ((attVal[0] === '"' || attVal[0] === '\'') &&
(attVal[attVal.length-1] === '"' || attVal[attVal.length-1] === '\'')) {
attVal = attVal.substr(1,attVal.length-2);
}
newNode.att.set(keyVal[0], attVal);
}
parent.addChild(newNode);
if (isClosing) {
//i;
}
else {
i = Parser._parseXMLInternal(phrases, i + 1, newNode.type, newNode);
}
}
else if (phrase.type === PhraseType.END) {
if (phrase.value === inputTagName) {
return i;
}
// Otherwise we have a parsing error
else {
throw Error(`Parsing error: Found orphaned closing tag '</${phrase.value}>'`);
}
}
else if (phrase.type === PhraseType.TEXT) {
// We don't accept empty string text nodes (with white space)
let trimmed = phrase.value.trim();
if (trimmed.length > 0) {
parent.addChild(new Node(NodeType.TEXT, phrase.value));
}
}
else {
throw Error(`Shouldn't happen`);
}
}
}
}

11
Skills/@be/node_modules/jibo-node-xml/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import Node from './Node';
import { NodeType, AttType } from './Node';
import Parser from './Parser';
export {
NodeType,
Parser,
AttType
}
export default Node;