From f3764170422730c09ffa91a431ff218cb1c8a143 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Sat, 30 Apr 2022 15:55:05 -0300 Subject: [PATCH 1/5] New generic types --- .gitignore | 3 ++- complex-types.d.ts | 19 +++++++++++++++++++ index.js | 28 +++++----------------------- package.json | 2 +- 4 files changed, 27 insertions(+), 25 deletions(-) create mode 100644 complex-types.d.ts diff --git a/.gitignore b/.gitignore index c977c85..e149f7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store -*.d.ts +index.d.ts +test.d.ts *.log coverage/ node_modules/ diff --git a/complex-types.d.ts b/complex-types.d.ts new file mode 100644 index 0000000..c0cc00d --- /dev/null +++ b/complex-types.d.ts @@ -0,0 +1,19 @@ +import type {Node, Parent} from 'unist' + +export type NodeOfTree< + Tree extends Node = never, + Found = void +> = Tree extends Parent + ? + | Tree + | NodeOfTree< + Exclude, + Found | Tree + > + : Tree + +export type MapFunction = ( + node: NodeOfTree, + index: number | null, + parent: NodeOfTree | null +) => NodeOfTree diff --git a/index.js b/index.js index 7855ec1..2c815f6 100644 --- a/index.js +++ b/index.js @@ -1,36 +1,19 @@ /** - * @typedef {import('unist').Parent} Parent - * @typedef {import('unist').Position} Position * @typedef {import('unist').Node} Node - * @typedef {Record & {type: string, position?: Position|undefined}} NodeLike - */ - -/** - * Function called with a node to produce a new node. - * - * @callback MapFunction - * @param {NodeLike|Node} node Current node being processed - * @param {number} [index] Index of `node`, or `null` - * @param {Parent} [parent] Parent of `node`, or `null` - * @returns {NodeLike|Node} Node to be used in the new tree. Its children are not used: if the original node has children, those are mapped. */ /** * Unist utility to create a new tree by mapping all nodes with the given function. * - * @param {NodeLike|Node} tree Tree to map - * @param {MapFunction} iteratee Function that returns a new node - * @returns {NodeLike|Node} New mapped tree. + * @param tree Tree to map + * @param iteratee Function that returns a new node + * + * @type {(tree: Tree, iteratee: import('./complex-types').MapFunction) => Tree} */ export function map(tree, iteratee) { return preorder(tree, null, null) - /** - * @param {NodeLike|Node} node - * @param {number} [index] - * @param {Parent} [parent] - * @returns {Node} - */ + /** @type {import('./complex-types').MapFunction} */ function preorder(node, index, parent) { var newNode = Object.assign({}, iteratee(node, index, parent)) @@ -40,7 +23,6 @@ export function map(tree, iteratee) { /** @type {Node} */ child, /** @type {number} */ index ) { - // @ts-expect-error Looks like a parent. return preorder(child, index, node) }) } diff --git a/package.json b/package.json index d063c4a..b7b1d3c 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ }, "scripts": { "prepack": "npm run build && npm run format", - "build": "rimraf \"*.d.ts\" && tsc && type-coverage", + "build": "rimraf \"{index,test}.d.ts\" && tsc && type-coverage", "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", "test-api": "node test.js", "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test.js", From d822927fbf6c93b2a62280a67d3dc6fe0f9393f3 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Sat, 30 Apr 2022 16:02:23 -0300 Subject: [PATCH 2/5] Fixed test types --- test.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test.js b/test.js index 8c24349..aab69ff 100644 --- a/test.js +++ b/test.js @@ -1,5 +1,8 @@ /** - * @typedef {import('unist').Node} Node + * @typedef {{type: 'leaf', value: string}} Leaf + * @typedef {{type: 'node', children: (Node | Leaf)[]}} Node + * @typedef {{type: 'root', children: (Node | Leaf)[]}} Root + * @typedef {Root | Node | Leaf} AnyNode */ import test from 'tape' @@ -15,13 +18,14 @@ test('unist-util-map', function (t) { t.deepEqual( map( - { + /** @type {Root} */ + ({ type: 'root', children: [ {type: 'node', children: [{type: 'leaf', value: '1'}]}, {type: 'leaf', value: '2'} ] - }, + }), changeLeaf ), u('root', [u('node', [u('leaf', 'CHANGED')]), u('leaf', 'CHANGED')]), @@ -45,8 +49,8 @@ test('unist-util-map', function (t) { t.end() /** - * @param {Node} node - * @returns {Node} + * @param {AnyNode} node + * @returns {AnyNode} */ function changeLeaf(node) { return node.type === 'leaf' @@ -55,8 +59,8 @@ test('unist-util-map', function (t) { } /** - * @param {Node} node - * @returns {Node?} + * @param {AnyNode} node + * @returns {AnyNode?} */ function nullLeaf(node) { return node.type === 'leaf' ? null : node From af48989c691ca5471cd10a71d9e1af89fb95f756 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Sat, 30 Apr 2022 16:13:37 -0300 Subject: [PATCH 3/5] Type-coverage --- index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 2c815f6..0718042 100644 --- a/index.js +++ b/index.js @@ -5,22 +5,23 @@ /** * Unist utility to create a new tree by mapping all nodes with the given function. * - * @param tree Tree to map - * @param iteratee Function that returns a new node - * - * @type {(tree: Tree, iteratee: import('./complex-types').MapFunction) => Tree} + * @template {Node} Tree + * @param {Tree} tree Tree to map + * @param {import('./complex-types').MapFunction} iteratee Function that returns a new node + * @returns {Tree} New mapped tree. */ export function map(tree, iteratee) { + // @ts-expect-error Looks like a children. return preorder(tree, null, null) - /** @type {import('./complex-types').MapFunction} */ + /** @type {import('./complex-types').MapFunction} */ function preorder(node, index, parent) { var newNode = Object.assign({}, iteratee(node, index, parent)) if ('children' in node) { // @ts-expect-error Looks like a parent. newNode.children = node.children.map(function ( - /** @type {Node} */ child, + /** @type {import('./complex-types').NodeOfTree} */ child, /** @type {number} */ index ) { return preorder(child, index, node) From b77bcaf16d2af8df4f86fa7a02d8dc162ab084cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Seery?= Date: Mon, 2 May 2022 09:54:59 -0300 Subject: [PATCH 4/5] Array<> instead of [] Co-authored-by: Titus --- test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test.js b/test.js index aab69ff..6e059d1 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,7 @@ /** * @typedef {{type: 'leaf', value: string}} Leaf - * @typedef {{type: 'node', children: (Node | Leaf)[]}} Node - * @typedef {{type: 'root', children: (Node | Leaf)[]}} Root + * @typedef {{type: 'node', children: Array}} Node + * @typedef {{type: 'root', children: Array}} Root * @typedef {Root | Node | Leaf} AnyNode */ From 40a41e10af54ea957f0c7c57f3fa1e4ee4931e75 Mon Sep 17 00:00:00 2001 From: JuanM04 Date: Mon, 2 May 2022 09:56:03 -0300 Subject: [PATCH 5/5] InclusiveDescendant --- complex-types.d.ts | 14 +++++++++----- index.js | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/complex-types.d.ts b/complex-types.d.ts index c0cc00d..28ccd7a 100644 --- a/complex-types.d.ts +++ b/complex-types.d.ts @@ -1,19 +1,23 @@ import type {Node, Parent} from 'unist' -export type NodeOfTree< +/** + * Internal utility to collect all descendants of in `Tree`. + * @see https://github.com/syntax-tree/unist-util-visit-parents/blob/18d36ad/complex-types.d.ts#L43 + */ +export type InclusiveDescendant< Tree extends Node = never, Found = void > = Tree extends Parent ? | Tree - | NodeOfTree< + | InclusiveDescendant< Exclude, Found | Tree > : Tree export type MapFunction = ( - node: NodeOfTree, + node: InclusiveDescendant, index: number | null, - parent: NodeOfTree | null -) => NodeOfTree + parent: InclusiveDescendant | null +) => InclusiveDescendant diff --git a/index.js b/index.js index 0718042..ecc78d5 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,7 @@ export function map(tree, iteratee) { if ('children' in node) { // @ts-expect-error Looks like a parent. newNode.children = node.children.map(function ( - /** @type {import('./complex-types').NodeOfTree} */ child, + /** @type {import('./complex-types').InclusiveDescendant} */ child, /** @type {number} */ index ) { return preorder(child, index, node)