syntax-tree / unist-util-is

Compare 8b10d91 ... +20 ... b938821

Coverage Reach
index.js

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.

Showing 1 of 18 files from the diff.
Other files ignored by Codecov
package.json has changed.
test/main.js has changed.
convert.js was deleted.
.gitignore has changed.
test/index.js has changed.
convert.d.ts was deleted.
.prettierignore has changed.
tslint.json was deleted.
.npmrc has changed.
tsconfig.json has changed.
test/property.js has changed.
index.d.ts was deleted.
readme.md has changed.

@@ -1,32 +1,264 @@
Loading
1 -
'use strict'
1 +
/**
2 +
 * @typedef {import('unist').Node} Node
3 +
 * @typedef {import('unist').Parent} Parent
4 +
 *
5 +
 * @typedef {string} Type
6 +
 * @typedef {Object<string, unknown>} Props
7 +
 *
8 +
 * @typedef {null|undefined|Type|Props|TestFunctionAnything|Array.<Type|Props|TestFunctionAnything>} Test
9 +
 */
2 10
3 -
var convert = require('./convert')
11 +
/**
12 +
 * Check if a node passes a test
13 +
 *
14 +
 * @callback TestFunctionAnything
15 +
 * @param {Node} node
16 +
 * @param {number|null|undefined} [index]
17 +
 * @param {Parent|null|undefined} [parent]
18 +
 * @returns {boolean|void}
19 +
 */
4 20
5 -
module.exports = is
21 +
/**
22 +
 * Check if a node passes a certain node test
23 +
 *
24 +
 * @template {Node} X
25 +
 * @callback TestFunctionPredicate
26 +
 * @param {Node} node
27 +
 * @param {number|null|undefined} [index]
28 +
 * @param {Parent|null|undefined} [parent]
29 +
 * @returns {node is X}
30 +
 */
6 31
7 -
is.convert = convert
32 +
/**
33 +
 * @callback AssertAnything
34 +
 * @param {unknown} [node]
35 +
 * @param {number|null|undefined} [index]
36 +
 * @param {Parent|null|undefined} [parent]
37 +
 * @returns {boolean}
38 +
 */
8 39
9 -
// Assert if `test` passes for `node`.
10 -
// When a `parent` node is known the `index` of node should also be given.
11 -
function is(node, test, index, parent, context) {
12 -
  var check = convert(test)
40 +
/**
41 +
 * Check if a node passes a certain node test
42 +
 *
43 +
 * @template {Node} Y
44 +
 * @callback AssertPredicate
45 +
 * @param {unknown} [node]
46 +
 * @param {number|null|undefined} [index]
47 +
 * @param {Parent|null|undefined} [parent]
48 +
 * @returns {node is Y}
49 +
 */
13 50
14 -
  if (
15 -
    index != null &&
16 -
    (typeof index !== 'number' || index < 0 || index === Infinity)
17 -
  ) {
18 -
    throw new Error('Expected positive finite index')
51 +
/**
52 +
 * Check if a node passes a test.
53 +
 * When a `parent` node is known the `index` of node should also be given.
54 +
 *
55 +
 * @param node
56 +
 *   Node to check, can be anything.
57 +
 * @param test
58 +
 *   *   When nullish, checks if `node` is a `Node`.
59 +
 *   *   When `string`, works like passing `(node) => node.type === test`.
60 +
 *   *   When `function` checks if function passed the node is true.
61 +
 *   *   When `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
62 +
 *   *   When `array`, checks any one of the subtests pass.
63 +
 * @param index
64 +
 *   Position of `node` in `parent`, must be a number if `parent` is also given.
65 +
 * @param parent
66 +
 *   Parent of `node`, must be given if `index` is also given.
67 +
 * @param context
68 +
 *   Context object to invoke `test` with, optional
69 +
 * @returns
70 +
 *   Whether test passed and `node` is a `Node` (object with `type` set to
71 +
 *   non-empty `string`).
72 +
 */
73 +
export const is =
74 +
  /**
75 +
   * @type {(
76 +
   *   (<ExplicitNode extends Node>(node: unknown, test: ExplicitNode['type']|Partial<ExplicitNode>|TestFunctionPredicate<ExplicitNode>|Array.<ExplicitNode['type']|Partial<ExplicitNode>|TestFunctionPredicate<ExplicitNode>>, index: number, parent: Parent, context?: unknown) => node is ExplicitNode) &
77 +
   *   (<ExplicitNode extends Node>(node: unknown, test: ExplicitNode['type']|Partial<ExplicitNode>|TestFunctionPredicate<ExplicitNode>|Array.<ExplicitNode['type']|Partial<ExplicitNode>|TestFunctionPredicate<ExplicitNode>>, index?: null|undefined, parent?: null|undefined, context?: unknown) => node is ExplicitNode) &
78 +
   *   ((node: unknown, test: Test, index: number, parent: Parent, context?: unknown) => boolean) &
79 +
   *   ((node?: unknown, test?: Test, index?: null|undefined, parent?: null|undefined, context?: unknown) => boolean)
80 +
   * )}
81 +
   */
82 +
  (
83 +
    /**
84 +
     * @param {unknown} [node]
85 +
     * @param {Test} [test]
86 +
     * @param {number|null|undefined} [index]
87 +
     * @param {Parent|null|undefined} [parent]
88 +
     * @param {unknown} [context]
89 +
     * @returns {boolean}
90 +
     */
91 +
    // eslint-disable-next-line max-params
92 +
    function is(node, test, index, parent, context) {
93 +
      const check = convert(test)
94 +
95 +
      if (
96 +
        index !== undefined &&
97 +
        index !== null &&
98 +
        (typeof index !== 'number' ||
99 +
          index < 0 ||
100 +
          index === Number.POSITIVE_INFINITY)
101 +
      ) {
102 +
        throw new Error('Expected positive finite index')
103 +
      }
104 +
105 +
      if (
106 +
        parent !== undefined &&
107 +
        parent !== null &&
108 +
        (!is(parent) || !parent.children)
109 +
      ) {
110 +
        throw new Error('Expected parent node')
111 +
      }
112 +
113 +
      if (
114 +
        (parent === undefined || parent === null) !==
115 +
        (index === undefined || index === null)
116 +
      ) {
117 +
        throw new Error('Expected both parent and index')
118 +
      }
119 +
120 +
      // @ts-expect-error Looks like a node.
121 +
      return node && node.type && typeof node.type === 'string'
122 +
        ? Boolean(check.call(context, node, index, parent))
123 +
        : false
124 +
    }
125 +
  )
126 +
127 +
export const convert =
128 +
  /**
129 +
   * @type {(
130 +
   *   (<ExplicitNode extends Node>(test: ExplicitNode['type']|Partial<ExplicitNode>|TestFunctionPredicate<ExplicitNode>) => AssertPredicate<ExplicitNode>) &
131 +
   *   ((test?: Test) => AssertAnything)
132 +
   * )}
133 +
   */
134 +
  (
135 +
    /**
136 +
     * Generate an assertion from a check.
137 +
     * @param {Test} [test]
138 +
     * When nullish, checks if `node` is a `Node`.
139 +
     * When `string`, works like passing `function (node) {return node.type === test}`.
140 +
     * When `function` checks if function passed the node is true.
141 +
     * When `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
142 +
     * When `array`, checks any one of the subtests pass.
143 +
     * @returns {AssertAnything}
144 +
     */
145 +
    function (test) {
146 +
      if (test === undefined || test === null) {
147 +
        return ok
148 +
      }
149 +
150 +
      if (typeof test === 'string') {
151 +
        return typeFactory(test)
152 +
      }
153 +
154 +
      if (typeof test === 'object') {
155 +
        return Array.isArray(test) ? anyFactory(test) : propsFactory(test)
156 +
      }
157 +
158 +
      if (typeof test === 'function') {
159 +
        return castFactory(test)
160 +
      }
161 +
162 +
      throw new Error('Expected function, string, or object as test')
163 +
    }
164 +
  )
165 +
/**
166 +
 * @param {Array.<Type|Props|TestFunctionAnything>} tests
167 +
 * @returns {AssertAnything}
168 +
 */
169 +
function anyFactory(tests) {
170 +
  /** @type {Array.<AssertAnything>} */
171 +
  const checks = []
172 +
  let index = -1
173 +
174 +
  while (++index < tests.length) {
175 +
    checks[index] = convert(tests[index])
176 +
  }
177 +
178 +
  return castFactory(any)
179 +
180 +
  /**
181 +
   * @this {unknown}
182 +
   * @param {unknown[]} parameters
183 +
   * @returns {boolean}
184 +
   */
185 +
  function any(...parameters) {
186 +
    let index = -1
187 +
188 +
    while (++index < checks.length) {
189 +
      if (checks[index].call(this, ...parameters)) return true
190 +
    }
191 +
192 +
    return false
19 193
  }
194 +
}
195 +
196 +
/**
197 +
 * Utility to assert each property in `test` is represented in `node`, and each
198 +
 * values are strictly equal.
199 +
 *
200 +
 * @param {Props} check
201 +
 * @returns {AssertAnything}
202 +
 */
203 +
function propsFactory(check) {
204 +
  return castFactory(all)
20 205
21 -
  if (parent != null && (!is(parent) || !parent.children)) {
22 -
    throw new Error('Expected parent node')
206 +
  /**
207 +
   * @param {Node} node
208 +
   * @returns {boolean}
209 +
   */
210 +
  function all(node) {
211 +
    /** @type {string} */
212 +
    let key
213 +
214 +
    for (key in check) {
215 +
      // @ts-expect-error: hush, it sure works as an index.
216 +
      if (node[key] !== check[key]) return false
217 +
    }
218 +
219 +
    return true
23 220
  }
221 +
}
24 222
25 -
  if ((parent == null) !== (index == null)) {
26 -
    throw new Error('Expected both parent and index')
223 +
/**
224 +
 * Utility to convert a string into a function which checks a given node’s type
225 +
 * for said string.
226 +
 *
227 +
 * @param {Type} check
228 +
 * @returns {AssertAnything}
229 +
 */
230 +
function typeFactory(check) {
231 +
  return castFactory(type)
232 +
233 +
  /**
234 +
   * @param {Node} node
235 +
   */
236 +
  function type(node) {
237 +
    return node && node.type === check
238 +
  }
239 +
}
240 +
241 +
/**
242 +
 * Utility to convert a string into a function which checks a given node’s type
243 +
 * for said string.
244 +
 * @param {TestFunctionAnything} check
245 +
 * @returns {AssertAnything}
246 +
 */
247 +
function castFactory(check) {
248 +
  return assertion
249 +
250 +
  /**
251 +
   * @this {unknown}
252 +
   * @param {Array.<unknown>} parameters
253 +
   * @returns {boolean}
254 +
   */
255 +
  function assertion(...parameters) {
256 +
    // @ts-expect-error: spreading is fine.
257 +
    return Boolean(check.call(this, ...parameters))
27 258
  }
259 +
}
28 260
29 -
  return node && node.type && typeof node.type === 'string'
30 -
    ? Boolean(check.call(context, node, index, parent))
31 -
    : false
261 +
// Utility to return true.
262 +
function ok() {
263 +
  return true
32 264
}

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Coverage
index.js 100.00%
Project Totals (1 files) 100.00%
Loading