syntax-tree / unist-util-is
Showing 1 of 8 files from the diff.
Other files ignored by Codecov
package.json has changed.
test/main.js has changed.
.gitignore has changed.
tsconfig.json has changed.
test/property.js has changed.
index.d.ts was deleted.

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