diff --git a/types/symbol-tree/index.d.ts b/types/symbol-tree/index.d.ts new file mode 100644 index 0000000000..eea83196b4 --- /dev/null +++ b/types/symbol-tree/index.d.ts @@ -0,0 +1,7 @@ +// Type definitions for symbol-tree 3.2 +// Project: https://github.com/jsdom/js-symbol-tree#symbol-tree +// Definitions by: ExE Boss +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import SymbolTree = require('./lib/SymbolTree'); +export = SymbolTree; diff --git a/types/symbol-tree/lib/SymbolTree.d.ts b/types/symbol-tree/lib/SymbolTree.d.ts new file mode 100644 index 0000000000..955923d0b6 --- /dev/null +++ b/types/symbol-tree/lib/SymbolTree.d.ts @@ -0,0 +1,325 @@ +import TreeIterator = require('./TreeIterator'); +import TreePosition = require('./TreePosition'); + +declare namespace SymbolTree { + interface SiblingOptions { + /** + * Used to constrain the operation to a subtree. + * + * When `null`, the whole tree is walked to the real root. + * + * @default null + */ + root?: T | null; + + /** + * If set, ignore the children of `object` + * + * @default false + */ + skipChildren?: boolean; + } + + interface ToArrayOptions { + /** + * The array to initialize the operation with. + * + * @default + * ```ts + * new Array(0); + * ``` + */ + array?: T[]; + + /** + * Function to test each object before it is added to the array. + * Invoked with arguments (object). + * + * Should return `true` if an object is to be included. + * + * @param object + */ + filter?(object: T): any; + + /** Value to use as `this` when executing `filter`. */ + thisArg?: any; + } + + interface IteratorOptions { + /** + * Whether to iterate in reverse tree order. + * + * @default false + */ + reverse?: boolean; + } +} + +declare class SymbolTree { + static readonly TreePosition: typeof TreePosition; + + /** + * @param [description='SymbolTree data'] Description used for the Symbol + * + * **Default:** `'SymbolTree data'` + */ + constructor(description?: string); + + /** + * You can use this function to (optionally) initialize an object right after its creation, + * to take advantage of V8's fast properties. Also useful if you would like to + * freeze your object. + * + * * `O(1)` + */ + initialize(object: O): O; + + /** + * Returns `true` if the object has any children. Otherwise it returns `false`. + * + * * `O(1)` + */ + hasChildren(object: T): boolean; + + /** + * Returns the first child of the given object. + * + * * `O(1)` + */ + firstChild(object: T): T | null; + + /** + * Returns the last child of the given object. + * + * * `O(1)` + */ + lastChild(object: T): T | null; + + /** + * Returns the previous sibling of the given object. + * + * * `O(1)` + */ + previousSibling(object: T): T | null; + + /** + * Returns the next sibling of the given object. + * + * * `O(1)` + */ + nextSibling(object: T): T | null; + + /** + * Return the parent of the given object. + * + * * `O(1)` + */ + parent(object: T): T | null; + + /** + * Find the inclusive descendant that is last in tree order of the given object. + * + * * `O(n)` (worst case) where `n` is the depth of the subtree of `object` + */ + lastInclusiveDescendant(object: T): T | null; + + /** + * Find the preceding object (A) of the given object (B). + * An object A is preceding an object B if A and B are in the same tree + * and A comes before B in tree order. + * + * * `O(n)` (worst case) + * * `O(1)` (amortized when walking the entire tree) + */ + preceding(object: T, options?: SymbolTree.SiblingOptions): T | null; + + /** + * Find the following object (A) of the given object (B). + * An object A is following an object B if A and B are in the same tree + * and A comes after B in tree order. + * + * * `O(n)` (worst case) where `n` is the amount of objects in the entire tree + * * `O(1)` (amortized when walking the entire tree) + */ + following(object: T, options?: SymbolTree.SiblingOptions): T | null; + + /** + * Append all children of the given object to an array. + * + * * `O(n)` where `n` is the amount of children of the given `parent` + */ + childrenToArray( + parent: T, + options?: SymbolTree.ToArrayOptions & { + thisArg: THIS; + filter(this: THIS, object: T): any; + }, + ): T[]; + childrenToArray(parent: T, options?: SymbolTree.ToArrayOptions): T[]; + + /** + * Append all inclusive ancestors of the given object to an array. + * + * * `O(n)` where `n` is the amount of ancestors of the given `object` + */ + ancestorsToArray( + object: T, + options?: SymbolTree.ToArrayOptions & { + thisArg: THIS; + filter(this: THIS, object: T): any; + }, + ): T[]; + ancestorsToArray(object: T, options?: SymbolTree.ToArrayOptions): T[]; + + /** + * Append all descendants of the given object to an array (in tree order). + * + * * `O(n)` where `n` is the amount of objects in the sub-tree of the given `object` + */ + treeToArray( + object: T, + options?: SymbolTree.ToArrayOptions & { + thisArg: THIS; + filter(this: THIS, object: T): any; + }, + ): T[]; + treeToArray(object: T, options?: SymbolTree.ToArrayOptions): T[]; + + /** + * Iterate over all children of the given object + * + * * `O(1)` for a single iteration + * + * @return An iterable iterator (ES6) + */ + childrenIterator(parent: T, options?: SymbolTree.IteratorOptions): TreeIterator; + + /** + * Iterate over all the previous siblings of the given object. (in reverse tree order) + * + * * `O(1)` for a single iteration + * + * @return An iterable iterator (ES6) + */ + previousSiblingsIterator(object: T): TreeIterator; + + /** + * Iterate over all the next siblings of the given object. (in tree order) + * + * * `O(1)` for a single iteration + * + * @return An iterable iterator (ES6) + */ + nextSiblingsIterator(object: T): TreeIterator; + + /** + * Iterate over all inclusive ancestors of the given object + * + * * `O(1)` for a single iteration + * + * @return An iterable iterator (ES6) + */ + ancestorsIterator(object: T): TreeIterator; + + /** + * Iterate over all descendants of the given object (in tree order). + * + * Where `n` is the amount of objects in the sub-tree of the given `root`: + * + * * `O(n)` (worst case for a single iteration) + * * `O(n)` (amortized, when completing the iterator) + * + * @return An iterable iterator (ES6) + */ + treeIterator(object: T, options?: SymbolTree.IteratorOptions): TreeIterator; + + /** + * Find the index of the given object (the number of preceding siblings). + * + * * `O(n)` where `n` is the amount of preceding siblings + * * `O(1)` (amortized, if the tree is not modified) + * + * @return The number of preceding siblings, or -1 if the object has no parent + */ + index(object: T): number; + + /** + * Calculate the number of children. + * + * * `O(n)` where `n` is the amount of children + * * `O(1)` (amortized, if the tree is not modified) + */ + childrenCount(object: T): number; + + /** + * Compare the position of an object relative to another object. A bit set is returned: + * + *
    + *
  • DISCONNECTED : 1
  • + *
  • PRECEDING : 2
  • + *
  • FOLLOWING : 4
  • + *
  • CONTAINS : 8
  • + *
  • CONTAINED_BY : 16
  • + *
+ * + * The semantics are the same as compareDocumentPosition in DOM, with the exception that + * DISCONNECTED never occurs with any other bit. + * + * where `n` and `m` are the amount of ancestors of `left` and `right`; + * where `o` is the amount of children of the lowest common ancestor of `left` and `right`: + * + * * `O(n + m + o)` (worst case) + * * `O(n + m)` (amortized, if the tree is not modified) + */ + compareTreePosition(left: T, right: T): number; + + /** + * Remove the object from this tree. + * Has no effect if already removed. + * + * * `O(1)` + */ + remove(object: U): U; + + /** + * Insert the given object before the reference object. + * `newObject` is now the previous sibling of `referenceObject`. + * + * * `O(1)` + * + * @throws {Error} If the newObject is already present in this SymbolTree + */ + insertBefore(referenceObject: T, newObject: U): U; + + /** + * Insert the given object after the reference object. + * `newObject` is now the next sibling of `referenceObject`. + * + * * `O(1)` + * + * @throws {Error} If the newObject is already present in this SymbolTree + */ + insertAfter(referenceObject: T, newObject: U): U; + + /** + * Insert the given object as the first child of the given reference object. + * `newObject` is now the first child of `referenceObject`. + * + * * `O(1)` + * + * @throws {Error} If the newObject is already present in this SymbolTree + */ + prependChild(referenceObject: T, newObject: U): U; + + /** + * Insert the given object as the last child of the given reference object. + * `newObject` is now the last child of `referenceObject`. + * + * * `O(1)` + * + * @throws {Error} If the newObject is already present in this SymbolTree + */ + appendChild(referenceObject: T, newObject: U): U; +} + +export = SymbolTree; diff --git a/types/symbol-tree/lib/TreeIterator.d.ts b/types/symbol-tree/lib/TreeIterator.d.ts new file mode 100644 index 0000000000..aa831aac0b --- /dev/null +++ b/types/symbol-tree/lib/TreeIterator.d.ts @@ -0,0 +1,44 @@ +import SymbolTree = require('./SymbolTree'); + +declare namespace TreeIterator { + /** + * The iteration function to use. + * + * - `1`: Iterate previous sibling nodes. + * - `2`: Iterate next sibling nodes. + * - `3`: Iterate ancestor nodes. + * - `4`: Iterate all tree-inclusive preceding nodes. + * - `5`: Iterate all tree-inclusive following nodes. + */ + type IterateFunction = 1 | 2 | 3 | 4 | 5; + + interface TreeIteratorResult { + done: boolean; + value: T; + } +} + +declare class TreeIterator implements IterableIterator { + constructor(tree: SymbolTree, root: T, firstResult: T, iterateFunction: TreeIterator.IterateFunction); + + next(): TreeIterator.TreeIteratorResult; + + [Symbol.iterator](): this; + + /** Iterate previous sibling nodes. */ + static readonly PREV: 1; + + /** Iterate next sibling nodes. */ + static readonly NEXT: 2; + + /** Iterate ancestor nodes. */ + static readonly PARENT: 3; + + /** Iterate all tree-inclusive preceding nodes. */ + static readonly PRECEDING: 4; + + /** Iterate all tree-inclusive following nodes. */ + static readonly FOLLOWING: 5; +} + +export = TreeIterator; diff --git a/types/symbol-tree/lib/TreePosition.d.ts b/types/symbol-tree/lib/TreePosition.d.ts new file mode 100644 index 0000000000..08d619450e --- /dev/null +++ b/types/symbol-tree/lib/TreePosition.d.ts @@ -0,0 +1,6 @@ +// same as DOM DOCUMENT_POSITION_ +export const DISCONNECTED: 1; +export const PRECEDING: 2; +export const FOLLOWING: 4; +export const CONTAINS: 8; +export const CONTAINED_BY: 16; diff --git a/types/symbol-tree/test/symbol-tree.test.ts b/types/symbol-tree/test/symbol-tree.test.ts new file mode 100644 index 0000000000..83d3897c36 --- /dev/null +++ b/types/symbol-tree/test/symbol-tree.test.ts @@ -0,0 +1,44 @@ +import SymbolTree = require('symbol-tree'); +import TreePosition = require('symbol-tree/lib/TreePosition'); + +/** + * The `expectType` function from https://www.npmjs.com/package/tsd, + * except instead of returning `void`, it returns `T`. + */ +declare function expectType(value: T): T; + +TreePosition.DISCONNECTED; // $ExpectType 1 +TreePosition.PRECEDING; // $ExpectType 2 +TreePosition.FOLLOWING; // $ExpectType 4 +TreePosition.CONTAINS; // $ExpectType 8 +TreePosition.CONTAINED_BY; // $ExpectType 16 + +expectType(SymbolTree.TreePosition); + +interface Foo { + doStuff(): void; +} + +interface Bar extends Foo { + bar: boolean; +} + +interface Baz extends Foo { + baz: number; +} + +declare const foo: Foo; +declare const bar: Bar; +declare const baz: Baz; + +// $ExpectType SymbolTree +const tree = new SymbolTree(); + +tree.appendChild(foo, bar); // $ExpectType Bar +tree.appendChild(foo, baz); // $ExpectType Baz + +tree.compareTreePosition(foo, bar); // $ExpectType number +tree.compareTreePosition(foo, baz); // $ExpectType number +tree.compareTreePosition(bar, baz); // $ExpectType number + +tree.treeIterator(foo); // $ExpectType TreeIterator diff --git a/types/symbol-tree/tsconfig.json b/types/symbol-tree/tsconfig.json new file mode 100644 index 0000000000..b400b88dbc --- /dev/null +++ b/types/symbol-tree/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es2015"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": ["../"], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "test/symbol-tree.test.ts", + "index.d.ts" + ] +} diff --git a/types/symbol-tree/tslint.json b/types/symbol-tree/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/symbol-tree/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }