collect-your-stuff 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,6 +25,8 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
25
25
  private tailCache;
26
26
  /** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
27
27
  private countCache;
28
+ /** The node these linkers are the children of, remembered so that it is known even while the list is empty (undefined until it is known). */
29
+ private ownerNode;
28
30
  /**
29
31
  * Create the new LinkedTreeList instance, configure the list class.
30
32
  * @param {TreeLinker} [linkerClass=TreeLinker] The class used to wrap given data as tree linkers.
@@ -58,15 +60,17 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
58
60
  */
59
61
  get length(): number;
60
62
  /**
61
- * Get the parent of this tree list.
62
- * @return {TreeLinker}
63
+ * Get the parent of this tree list: the node these linkers are the children of (remembered even while the list is
64
+ * empty), or null for the linkers at the top of a tree.
65
+ * @return {TreeLinker|null}
63
66
  */
64
- get parent(): TreeLinker;
67
+ get parent(): TreeLinker | null;
65
68
  /**
66
- * Set the parent of this tree list
67
- * @param {TreeLinker} parent The new node to use as the parent for this group of children
69
+ * Set the parent of this tree list: every linker in it gets the node as its parent, and the node gets this list as its
70
+ * children. Linkers added to the list later get this parent too.
71
+ * @param {TreeLinker|null} parent The new node to use as the parent for this group of children
68
72
  */
69
- set parent(parent: TreeLinker);
73
+ set parent(parent: TreeLinker | null);
70
74
  /**
71
75
  * Return the root parent of the entire tree.
72
76
  * @return {TreeLinker}
@@ -74,24 +78,31 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
74
78
  get rootParent(): TreeLinker;
75
79
  /**
76
80
  * Set the children on a parent item.
77
- * @param {TreeLinker} item The TreeLinker node that will be the parent of the children
78
- * @param {LinkedTreeList} children The LinkedTreeList which has the child nodes to use
81
+ * @param {TreeLinker} item The TreeLinker node (one of the linkers of this list) that will be the parent of the children
82
+ * @param {LinkedTreeList|null} [children=null] The LinkedTreeList which has the child nodes to use, or null to remove the children of the item
83
+ * @throws {Error} When the item is not one of the linkers of this list
79
84
  */
80
- setChildren(item: TreeLinker, children?: LinkedTreeList): void;
85
+ setChildren(item: TreeLinker, children?: LinkedTreeList | null): void;
81
86
  /**
82
- * Insert a new node (or data) after a node.
83
- * @param {TreeLinker|*} node The existing node as reference
87
+ * Make a linker of the given node (or data) and make this list's parent its parent.
88
+ * @param {TreeLinker|*} newNode The node (or data) which is being added to this list
89
+ * @returns {TreeLinker}
90
+ */
91
+ private adopt;
92
+ /**
93
+ * Insert a new node (or data) after a node. The new node gets the parent of this list.
94
+ * @param {TreeLinker|*} node The existing node as reference, or null to insert at the start of the list
84
95
  * @param {TreeLinker|*} newNode The new node to go after the existing node
85
96
  * @returns {LinkedTreeList}
86
97
  */
87
- insertAfter(node: TreeLinker, newNode: TreeLinker | any): LinkedTreeList;
98
+ insertAfter(node: TreeLinker | null, newNode: TreeLinker | any): LinkedTreeList;
88
99
  /**
89
- * Insert a new node (or data) before a node.
90
- * @param {TreeLinker|*} node The existing node as reference
100
+ * Insert a new node (or data) before a node. The new node gets the parent of this list.
101
+ * @param {TreeLinker|*} node The existing node as reference, or null to insert at the end of the list
91
102
  * @param {TreeLinker|*} newNode The new node to go before the existing node
92
103
  * @returns {LinkedTreeList}
93
104
  */
94
- insertBefore(node: TreeLinker, newNode: TreeLinker | any): LinkedTreeList;
105
+ insertBefore(node: TreeLinker | null, newNode: TreeLinker | any): LinkedTreeList;
95
106
  /**
96
107
  * Add a node (or data) after the given (or last) node in the list.
97
108
  * @param {TreeLinker|*} node The new node to add to the end of the list
@@ -107,11 +118,11 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
107
118
  */
108
119
  prepend(node: TreeLinker | any, before?: TreeLinker): LinkedTreeList;
109
120
  /**
110
- * Remove a linker from this linked list.
121
+ * Remove a linker from this linked list. The removed node no longer has a parent.
111
122
  * @param {TreeLinker} node The node we wish to remove (and it will be returned after removal)
112
- * @return {TreeLinker}
123
+ * @return {TreeLinker|null} The removed node, or null when there was nothing to remove
113
124
  */
114
- remove(node: TreeLinker): TreeLinker;
125
+ remove(node: TreeLinker): TreeLinker | null;
115
126
  /**
116
127
  * Refresh all references (the head, the end and the length) by walking the list once, and return the head. The
117
128
  * list's own methods keep these up to date, so this is only needed after linkers were changed directly.
@@ -132,7 +143,8 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
132
143
  */
133
144
  forEach(callback: forEachCallback, thisArg?: LinkedTreeList): LinkedTreeList;
134
145
  /**
135
- * Be able to iterate over this class.
146
+ * Be able to iterate over this class: the linkers of this list and everything below them (left-first). It stays within
147
+ * this list (it does not start at, or climb up to, the parents), use the parseTree service to parse a whole tree.
136
148
  * @returns {Iterator}
137
149
  */
138
150
  [Symbol.iterator](): Iterator<TreeLinker>;
@@ -4,6 +4,8 @@ Object.defineProperty(exports, '__esModule', {
4
4
  value: true
5
5
  })
6
6
  exports.LinkedTreeList = void 0
7
+ require('core-js/modules/esnext.iterator.constructor.js')
8
+ require('core-js/modules/esnext.iterator.for-each.js')
7
9
  var _TreeLinker = require('./TreeLinker')
8
10
  var _TreeLinkerIterator = require('../../recipes/TreeLinkerIterator')
9
11
  var _DoublyLinkedList = require('../doubly-linked-list/DoublyLinkedList')
@@ -41,6 +43,8 @@ class LinkedTreeList {
41
43
  this.tailCache = null
42
44
  /** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
43
45
  this.countCache = null
46
+ /** The node these linkers are the children of, remembered so that it is known even while the list is empty (undefined until it is known). */
47
+ this.ownerNode = undefined
44
48
  this.linkerClass = linkerClass
45
49
  }
46
50
 
@@ -93,22 +97,25 @@ class LinkedTreeList {
93
97
  }
94
98
 
95
99
  /**
96
- * Get the parent of this tree list.
97
- * @return {TreeLinker}
100
+ * Get the parent of this tree list: the node these linkers are the children of (remembered even while the list is
101
+ * empty), or null for the linkers at the top of a tree.
102
+ * @return {TreeLinker|null}
98
103
  */
99
104
  get parent () {
100
- const first = this.first
101
- if (first === null) {
102
- return null
105
+ if (this.ownerNode !== undefined) {
106
+ return this.ownerNode
103
107
  }
104
- return this.first.parent
108
+ const first = this.first
109
+ return first === null ? null : first.parent
105
110
  }
106
111
 
107
112
  /**
108
- * Set the parent of this tree list
109
- * @param {TreeLinker} parent The new node to use as the parent for this group of children
113
+ * Set the parent of this tree list: every linker in it gets the node as its parent, and the node gets this list as its
114
+ * children. Linkers added to the list later get this parent too.
115
+ * @param {TreeLinker|null} parent The new node to use as the parent for this group of children
110
116
  */
111
117
  set parent (parent) {
118
+ this.ownerNode = parent
112
119
  let current = this.first
113
120
  while (current !== null) {
114
121
  current.parent = parent
@@ -138,34 +145,57 @@ class LinkedTreeList {
138
145
 
139
146
  /**
140
147
  * Set the children on a parent item.
141
- * @param {TreeLinker} item The TreeLinker node that will be the parent of the children
142
- * @param {LinkedTreeList} children The LinkedTreeList which has the child nodes to use
148
+ * @param {TreeLinker} item The TreeLinker node (one of the linkers of this list) that will be the parent of the children
149
+ * @param {LinkedTreeList|null} [children=null] The LinkedTreeList which has the child nodes to use, or null to remove the children of the item
150
+ * @throws {Error} When the item is not one of the linkers of this list
143
151
  */
144
152
  setChildren (item, children = null) {
145
- if (Array.from(this).indexOf(item) < 0) {
146
- console.error('item is not a child of this')
153
+ // The item must be one of the linkers of this list (only the siblings are checked, not the whole tree)
154
+ let isChild = false
155
+ this.forEach(linker => {
156
+ if (linker === item) {
157
+ isChild = true
158
+ }
159
+ })
160
+ if (!isChild) {
161
+ throw new Error('The item is not one of the linkers of this list.')
162
+ }
163
+ if (children === null || typeof children === 'undefined') {
164
+ item.children = null
165
+ return
147
166
  }
148
167
  children.parent = item
149
168
  }
150
169
 
151
170
  /**
152
- * Insert a new node (or data) after a node.
153
- * @param {TreeLinker|*} node The existing node as reference
171
+ * Make a linker of the given node (or data) and make this list's parent its parent.
172
+ * @param {TreeLinker|*} newNode The node (or data) which is being added to this list
173
+ * @returns {TreeLinker}
174
+ */
175
+ adopt (newNode) {
176
+ const linker = this.linkerClass.make(newNode, this.linkerClass)
177
+ linker.parent = this.parent
178
+ return linker
179
+ }
180
+
181
+ /**
182
+ * Insert a new node (or data) after a node. The new node gets the parent of this list.
183
+ * @param {TreeLinker|*} node The existing node as reference, or null to insert at the start of the list
154
184
  * @param {TreeLinker|*} newNode The new node to go after the existing node
155
185
  * @returns {LinkedTreeList}
156
186
  */
157
187
  insertAfter (node, newNode) {
158
- return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this, node, newNode)
188
+ return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this, node, this.adopt(newNode))
159
189
  }
160
190
 
161
191
  /**
162
- * Insert a new node (or data) before a node.
163
- * @param {TreeLinker|*} node The existing node as reference
192
+ * Insert a new node (or data) before a node. The new node gets the parent of this list.
193
+ * @param {TreeLinker|*} node The existing node as reference, or null to insert at the end of the list
164
194
  * @param {TreeLinker|*} newNode The new node to go before the existing node
165
195
  * @returns {LinkedTreeList}
166
196
  */
167
197
  insertBefore (node, newNode) {
168
- return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this, node, newNode)
198
+ return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this, node, this.adopt(newNode))
169
199
  }
170
200
 
171
201
  /**
@@ -189,12 +219,19 @@ class LinkedTreeList {
189
219
  }
190
220
 
191
221
  /**
192
- * Remove a linker from this linked list.
222
+ * Remove a linker from this linked list. The removed node no longer has a parent.
193
223
  * @param {TreeLinker} node The node we wish to remove (and it will be returned after removal)
194
- * @return {TreeLinker}
224
+ * @return {TreeLinker|null} The removed node, or null when there was nothing to remove
195
225
  */
196
226
  remove (node) {
197
- return _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this, node)
227
+ const owner = this.parent
228
+ const removed = _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this, node)
229
+ if (removed && removed.parent === owner) {
230
+ // Remember whose children these are (the list may now be empty), the removed node no longer has that parent
231
+ this.ownerNode = owner
232
+ removed.parent = null
233
+ }
234
+ return removed
198
235
  }
199
236
 
200
237
  /**
@@ -233,12 +270,14 @@ class LinkedTreeList {
233
270
  }
234
271
 
235
272
  /**
236
- * Be able to iterate over this class.
273
+ * Be able to iterate over this class: the linkers of this list and everything below them (left-first). It stays within
274
+ * this list (it does not start at, or climb up to, the parents), use the parseTree service to parse a whole tree.
237
275
  * @returns {Iterator}
238
276
  */
239
277
  [Symbol.iterator] () {
240
- const root = this.rootParent
241
- return new _TreeLinkerIterator.TreeLinkerIterator(root)
278
+ // The linkers of this list and everything below them, left-first. It stays within this list: it does not start at,
279
+ // or climb up to, the parents (use the parseTree service to parse a whole tree)
280
+ return new _TreeLinkerIterator.TreeLinkerIterator(this.first, this.parent)
242
281
  }
243
282
  }
244
283
  /**
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0;var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");const borrowedGetter=(e,t)=>Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype,e).get.call(t);class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return borrowedGetter("first",this)}get last(){return borrowedGetter("last",this)}get length(){return borrowedGetter("length",this)}get parent(){return null===this.first?null:this.first.parent}set parent(e){let t=this.first;for(;null!==t;)t.parent=e,t=t.next;e&&(e.children=this)}get rootParent(){let e=this.first;if(!e)return null;let t=this.first.parent;for(;null!==t;)e=t,t=e.parent;return e}setChildren(e,t=null){Array.from(this).indexOf(e)<0&&console.error("item is not a child of this"),t.parent=e}insertAfter(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this,e,t)}insertBefore(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this,e,t)}append(e,t=this.last){return _DoublyLinkedList.DoublyLinkedList.prototype.append.call(this,e,t)}prepend(e,t=this.first){return _DoublyLinkedList.DoublyLinkedList.prototype.prepend.call(this,e,t)}remove(e){return _DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this,e)}reset(){return _DoublyLinkedList.DoublyLinkedList.prototype.reset.call(this)}item(e){return _DoublyLinkedList.DoublyLinkedList.prototype.item.call(this,e)}forEach(e,t=this){let r=0,i=t.first;for(;null!==i;)e(i,r,t),i=i.next,++r;return t}[Symbol.iterator](){let e=this.rootParent;return new _TreeLinkerIterator.TreeLinkerIterator(e)}}exports.LinkedTreeList=LinkedTreeList,LinkedTreeList.fromArray=(e=[],t=_TreeLinker.TreeLinker,r=LinkedTreeList)=>new r(t).initialize(t.fromArray(e).head);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedTreeList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _TreeLinker=require("./TreeLinker"),_TreeLinkerIterator=require("../../recipes/TreeLinkerIterator"),_DoublyLinkedList=require("../doubly-linked-list/DoublyLinkedList");const borrowedGetter=(e,t)=>Object.getOwnPropertyDescriptor(_DoublyLinkedList.DoublyLinkedList.prototype,e).get.call(t);class LinkedTreeList{constructor(e=_TreeLinker.TreeLinker){this.classType=LinkedTreeList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.ownerNode=void 0,this.linkerClass=e}initialize(e){return this.initialized?(console.warn("Attempt to initialize LinkedTreeList which is not empty."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return borrowedGetter("first",this)}get last(){return borrowedGetter("last",this)}get length(){return borrowedGetter("length",this)}get parent(){if(void 0!==this.ownerNode)return this.ownerNode;const e=this.first;return null===e?null:e.parent}set parent(e){this.ownerNode=e;let t=this.first;for(;null!==t;)t.parent=e,t=t.next;e&&(e.children=this)}get rootParent(){let e=this.first;if(!e)return null;let t=this.first.parent;for(;null!==t;)e=t,t=e.parent;return e}setChildren(e,t=null){let r=!1;if(this.forEach((t=>{t===e&&(r=!0)})),!r)throw new Error("The item is not one of the linkers of this list.");null!=t?t.parent=e:e.children=null}adopt(e){const t=this.linkerClass.make(e,this.linkerClass);return t.parent=this.parent,t}insertAfter(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertAfter.call(this,e,this.adopt(t))}insertBefore(e,t){return _DoublyLinkedList.DoublyLinkedList.prototype.insertBefore.call(this,e,this.adopt(t))}append(e,t=this.last){return _DoublyLinkedList.DoublyLinkedList.prototype.append.call(this,e,t)}prepend(e,t=this.first){return _DoublyLinkedList.DoublyLinkedList.prototype.prepend.call(this,e,t)}remove(e){const t=this.parent,r=_DoublyLinkedList.DoublyLinkedList.prototype.remove.call(this,e);return r&&r.parent===t&&(this.ownerNode=t,r.parent=null),r}reset(){return _DoublyLinkedList.DoublyLinkedList.prototype.reset.call(this)}item(e){return _DoublyLinkedList.DoublyLinkedList.prototype.item.call(this,e)}forEach(e,t=this){let r=0,i=t.first;for(;null!==i;)e(i,r,t),i=i.next,++r;return t}[Symbol.iterator](){return new _TreeLinkerIterator.TreeLinkerIterator(this.first,this.parent)}}exports.LinkedTreeList=LinkedTreeList,LinkedTreeList.fromArray=(e=[],t=_TreeLinker.TreeLinker,r=LinkedTreeList)=>new r(t).initialize(t.fromArray(e).head);
@@ -43,7 +43,9 @@ export declare class TreeLinker implements IsTreeNode {
43
43
  listClass?: any;
44
44
  });
45
45
  /**
46
- * Create the children for this tree from an array.
46
+ * Create the children for this tree from an array. Each child becomes a tree linker with this node as its parent: an
47
+ * existing linker is kept as it is, an object with a data property gives the settings of the linker, and anything
48
+ * else is the data of the linker.
47
49
  * @param {Array|null} children Provide an array of data / linker references to be children of this tree node.
48
50
  * @param {IsArrayable<IsTreeNode>} listClass Give the type of list to use for storing the children
49
51
  * @return {LinkedTreeList|null}
@@ -51,7 +51,9 @@ class TreeLinker {
51
51
  }
52
52
 
53
53
  /**
54
- * Create the children for this tree from an array.
54
+ * Create the children for this tree from an array. Each child becomes a tree linker with this node as its parent: an
55
+ * existing linker is kept as it is, an object with a data property gives the settings of the linker, and anything
56
+ * else is the data of the linker.
55
57
  * @param {Array|null} children Provide an array of data / linker references to be children of this tree node.
56
58
  * @param {IsArrayable<IsTreeNode>} listClass Give the type of list to use for storing the children
57
59
  * @return {LinkedTreeList|null}
@@ -60,10 +62,17 @@ class TreeLinker {
60
62
  if (children === null) {
61
63
  return null
62
64
  }
63
- // Creates a linked-tree-list to store the children.
64
- return listClass.fromArray(children.map(child => Object.assign({}, child, {
65
- parent: this
66
- })), this.classType)
65
+ // Every child is made into a tree linker (an existing one is kept as it is, and a plain value is the data) and is
66
+ // given this node as its parent
67
+ const nodes = children.map(child => {
68
+ const linker = this.classType.make(child, this.classType)
69
+ linker.parent = this
70
+ return linker
71
+ })
72
+ // Creates a linked-tree-list to store the children, which remembers this node as its parent even when it is empty
73
+ const list = listClass.fromArray(nodes, this.classType)
74
+ list.parent = this
75
+ return list
67
76
  }
68
77
  }
69
78
  /**
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TreeLinker=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js");var _DoubleLinker=require("../doubly-linked-list/DoubleLinker"),_LinkedTreeList=require("./LinkedTreeList");class TreeLinker{constructor({data:e=null,next:r=null,prev:i=null,children:n=null,parent:t=null,listClass:l=_LinkedTreeList.LinkedTreeList}={}){this.classType=TreeLinker,this.data=null,this.next=null,this.prev=null,this.parent=null,this.children=null,this.data=e,this.next=r,this.prev=i,this.parent=t,this.children=this.childrenFromArray(n,l)}childrenFromArray(e=null,r=_LinkedTreeList.LinkedTreeList){return null===e?null:r.fromArray(e.map((e=>Object.assign({},e,{parent:this}))),this.classType)}}exports.TreeLinker=TreeLinker,TreeLinker.make=(e,r=TreeLinker)=>_DoubleLinker.DoubleLinker.make(e,r),TreeLinker.fromArray=(e=[],r=TreeLinker)=>_DoubleLinker.DoubleLinker.fromArray(e,r);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TreeLinker=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js");var _DoubleLinker=require("../doubly-linked-list/DoubleLinker"),_LinkedTreeList=require("./LinkedTreeList");class TreeLinker{constructor({data:e=null,next:r=null,prev:i=null,children:n=null,parent:t=null,listClass:s=_LinkedTreeList.LinkedTreeList}={}){this.classType=TreeLinker,this.data=null,this.next=null,this.prev=null,this.parent=null,this.children=null,this.data=e,this.next=r,this.prev=i,this.parent=t,this.children=this.childrenFromArray(n,s)}childrenFromArray(e=null,r=_LinkedTreeList.LinkedTreeList){if(null===e)return null;const i=e.map((e=>{const r=this.classType.make(e,this.classType);return r.parent=this,r})),n=r.fromArray(i,this.classType);return n.parent=this,n}}exports.TreeLinker=TreeLinker,TreeLinker.make=(e,r=TreeLinker)=>_DoubleLinker.DoubleLinker.make(e,r),TreeLinker.fromArray=(e=[],r=TreeLinker)=>_DoubleLinker.DoubleLinker.fromArray(e,r);
package/dist/main.d.ts CHANGED
@@ -63,7 +63,7 @@ declare const collectYourStuff: {
63
63
  };
64
64
  services: {
65
65
  parseTree: (tree: import("./main").IsTree, callback: import("./main").forEachCallback) => import("./main").IsTree;
66
- parseTreeNext: (treeNode: import("./main").IsTreeNode) => import("./main").IsTreeNode | null;
66
+ parseTreeNext: (treeNode: import("./main").IsTreeNode, boundaryParent?: import("./main").IsTreeNode | null) => import("./main").IsTreeNode | null;
67
67
  };
68
68
  };
69
69
  export default collectYourStuff;
@@ -4,11 +4,13 @@ import { IsTreeNode } from './IsTreeNode';
4
4
  */
5
5
  export declare class TreeLinkerIterator implements Iterator<IsTreeNode> {
6
6
  private current;
7
+ private readonly boundaryParent;
7
8
  /**
8
9
  * Create an iterator starting at the given item.
9
10
  * @param {IsTreeNode} current The item to start from.
11
+ * @param {IsTreeNode|null} [boundaryParent] The parent of the nodes to stay within (null for the top of a tree), the whole tree when not given.
10
12
  */
11
- constructor(current: IsTreeNode);
13
+ constructor(current: IsTreeNode, boundaryParent?: IsTreeNode | null);
12
14
  /**
13
15
  * Get the current item and move on to the following one (left-first, down each branch).
14
16
  * @param {*} [value] Not used, present to match the Iterator interface.
@@ -12,9 +12,11 @@ class TreeLinkerIterator {
12
12
  /**
13
13
  * Create an iterator starting at the given item.
14
14
  * @param {IsTreeNode} current The item to start from.
15
+ * @param {IsTreeNode|null} [boundaryParent] The parent of the nodes to stay within (null for the top of a tree), the whole tree when not given.
15
16
  */
16
- constructor (current) {
17
+ constructor (current, boundaryParent) {
17
18
  this.current = current
19
+ this.boundaryParent = boundaryParent
18
20
  }
19
21
 
20
22
  /**
@@ -27,7 +29,7 @@ class TreeLinkerIterator {
27
29
  value: this.current,
28
30
  done: !this.current
29
31
  }
30
- this.current = (0, _parseTreeNext.parseTreeNext)(this.current)
32
+ this.current = (0, _parseTreeNext.parseTreeNext)(this.current, this.boundaryParent)
31
33
  return result
32
34
  }
33
35
  }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TreeLinkerIterator=void 0;var _parseTreeNext=require("../services/parseTreeNext");class TreeLinkerIterator{constructor(e){this.current=e}next(e){const r={value:this.current,done:!this.current};return this.current=(0,_parseTreeNext.parseTreeNext)(this.current),r}}exports.TreeLinkerIterator=TreeLinkerIterator;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TreeLinkerIterator=void 0;var _parseTreeNext=require("../services/parseTreeNext");class TreeLinkerIterator{constructor(e,r){this.current=e,this.boundaryParent=r}next(e){const r={value:this.current,done:!this.current};return this.current=(0,_parseTreeNext.parseTreeNext)(this.current,this.boundaryParent),r}}exports.TreeLinkerIterator=TreeLinkerIterator;
@@ -8,7 +8,10 @@ import { IsTreeNode } from '../recipes/IsTreeNode';
8
8
  * 5. Repeat 3
9
9
  * 6. If no next child, return to parent and repeat 3
10
10
  * 7. Stop at root (next is null and parent is null
11
+ * A boundary can be given to parse only part of a tree: going back up to the parents stops at the boundary, so the
12
+ * parsing stays within the nodes whose parent is the boundary (and everything below them).
11
13
  * @param {IsTreeNode} treeNode Provide a node in a tree and get the next node (left-first approach)
14
+ * @param {IsTreeNode|null} [boundaryParent] The parent of the nodes to stay within, null for the nodes at the top of a tree. When it is not given the whole tree is parsed.
12
15
  * @returns {IsTreeNode|null}
13
16
  */
14
- export declare const parseTreeNext: (treeNode: IsTreeNode) => IsTreeNode | null;
17
+ export declare const parseTreeNext: (treeNode: IsTreeNode, boundaryParent?: IsTreeNode | null) => IsTreeNode | null;
@@ -13,35 +13,30 @@ exports.parseTreeNext = void 0
13
13
  * 5. Repeat 3
14
14
  * 6. If no next child, return to parent and repeat 3
15
15
  * 7. Stop at root (next is null and parent is null
16
+ * A boundary can be given to parse only part of a tree: going back up to the parents stops at the boundary, so the
17
+ * parsing stays within the nodes whose parent is the boundary (and everything below them).
16
18
  * @param {IsTreeNode} treeNode Provide a node in a tree and get the next node (left-first approach)
19
+ * @param {IsTreeNode|null} [boundaryParent] The parent of the nodes to stay within, null for the nodes at the top of a tree. When it is not given the whole tree is parsed.
17
20
  * @returns {IsTreeNode|null}
18
21
  */
19
- const parseTreeNext = treeNode => {
22
+ const parseTreeNext = (treeNode, boundaryParent) => {
20
23
  if (!treeNode) {
21
24
  return null
22
25
  }
23
- let test = null
24
26
  if (treeNode.children && treeNode.children.length) {
25
- // Go down the left side of the tree
26
- test = treeNode.children.first
27
+ return treeNode.children.first
27
28
  }
28
- if (!test) {
29
- // Reached the bottom, go the next node on the right
30
- test = treeNode.next
29
+ if (treeNode.next) {
30
+ return treeNode.next
31
31
  }
32
- if (!test && treeNode.parent) {
33
- // No more child nodes, return to parent and check parent sibling on the right
34
- let parentNext = treeNode.parent.next
35
- let parent = treeNode.parent
36
- while (parent && !parentNext) {
37
- parentNext = parent.next
38
- // Keep checking parent next, until there are no more parents, or we find the parent sibling
39
- parent = parent.parent
32
+ // Nothing more below or beside this node, so go back up until there is a node which has a next (or the boundary)
33
+ let parent = treeNode.parent
34
+ while (parent && parent !== boundaryParent) {
35
+ if (parent.next) {
36
+ return parent.next
40
37
  }
41
- // This may be the parent sibling, or it could be null indicating we are done
42
- test = parentNext
38
+ parent = parent.parent
43
39
  }
44
- // Finally, either use the node we found, or it may be null
45
- return test
40
+ return null
46
41
  }
47
42
  exports.parseTreeNext = parseTreeNext
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseTreeNext=void 0;const parseTreeNext=e=>{if(!e)return null;let r=null;if(e.children&&e.children.length&&(r=e.children.first),r||(r=e.next),!r&&e.parent){let t=e.parent.next,n=e.parent;for(;n&&!t;)t=n.next,n=n.parent;r=t}return r};exports.parseTreeNext=parseTreeNext;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseTreeNext=void 0;const parseTreeNext=(e,r)=>{if(!e)return null;if(e.children&&e.children.length)return e.children.first;if(e.next)return e.next;let t=e.parent;for(;t&&t!==r;){if(t.next)return t.next;t=t.parent}return null};exports.parseTreeNext=parseTreeNext;
@@ -9,5 +9,5 @@
9
9
  */
10
10
  export declare const services: {
11
11
  parseTree: (tree: import("../main").IsTree, callback: import("../main").forEachCallback) => import("../main").IsTree;
12
- parseTreeNext: (treeNode: import("../main").IsTreeNode) => import("../main").IsTreeNode | null;
12
+ parseTreeNext: (treeNode: import("../main").IsTreeNode, boundaryParent?: import("../main").IsTreeNode | null) => import("../main").IsTreeNode | null;
13
13
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "collect-your-stuff",
3
3
  "description": "Use a variety of collections to collect your stuff when building code.",
4
- "version": "2.0.0",
4
+ "version": "2.1.0",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
7
7
  "author": "Joshua Heagle",