hast-util-is-element
Advanced tools
Comparing version 1.1.0 to 2.0.0
236
index.js
@@ -1,35 +0,229 @@ | ||
'use strict' | ||
/** | ||
* @typedef {import('unist').Node} Node | ||
* @typedef {import('unist').Parent} Parent | ||
* @typedef {import('hast').Element} Element | ||
* | ||
* @typedef {string} TagName | ||
*/ | ||
var convert = require('./convert') | ||
/** | ||
* Check if an element passes a test | ||
* | ||
* @callback TestFunctionAnything | ||
* @param {Element} element | ||
* @param {number} [index] | ||
* @param {Parent} [parent] | ||
* @returns {boolean|void} | ||
*/ | ||
module.exports = isElement | ||
/** | ||
* Check if an element passes a certain node test | ||
* | ||
* @template {Element} X | ||
* @callback TestFunctionPredicate | ||
* @param {X} element | ||
* @param {number} [index] | ||
* @param {Parent} [parent] | ||
* @returns {element is X} | ||
*/ | ||
isElement.convert = convert | ||
/** | ||
* Check if a node is an element and passes a certain node test | ||
* | ||
* @template {Element} Y | ||
* @callback AssertPredicate | ||
* @param {unknown} [node] | ||
* @param {number} [index] | ||
* @param {Parent} [parent] | ||
* @returns {node is Y} | ||
*/ | ||
// Check if if `node` is an `element` and whether it passes the given test. | ||
function isElement(node, test, index, parent, context) { | ||
var hasParent = parent !== null && parent !== undefined | ||
var hasIndex = index !== null && index !== undefined | ||
var check = convert(test) | ||
// Check if `node` is an `element` and whether it passes the given test. | ||
export const isElement = | ||
/** | ||
* Check if a node is an element and passes a test. | ||
* When a `parent` node is known the `index` of node should also be given. | ||
* | ||
* @type {( | ||
* (<T extends Element>(node: unknown, test: T['tagName']|TestFunctionPredicate<T>|Array.<T['tagName']|TestFunctionPredicate<T>>, index?: number, parent?: Parent, context?: unknown) => node is T) & | ||
* ((node?: unknown, test?: null|undefined|TagName|TestFunctionAnything|Array.<TagName|TestFunctionAnything>, index?: number, parent?: Parent, context?: unknown) => node is Element) | ||
* )} | ||
*/ | ||
( | ||
/** | ||
* Check if a node passes a test. | ||
* When a `parent` node is known the `index` of node should also be given. | ||
* | ||
* @param {unknown} [node] Node to check | ||
* @param {null|undefined|TagName|TestFunctionAnything|Array.<TagName|TestFunctionAnything>} [test] | ||
* When nullish, checks if `node` is a `Node`. | ||
* When `string`, works like passing `function (node) {return node.type === test}`. | ||
* When `function` checks if function passed the node is true. | ||
* When `array`, checks any one of the subtests pass. | ||
* @param {number} [index] Position of `node` in `parent` | ||
* @param {Parent} [parent] Parent of `node` | ||
* @param {unknown} [context] Context object to invoke `test` with | ||
* @returns {boolean} Whether test passed and `node` is an `Element` (object with `type` set to `element` and `tagName` set to a non-empty string). | ||
*/ | ||
// eslint-disable-next-line max-params | ||
function (node, test, index, parent, context) { | ||
var check = convertElement(test) | ||
if ( | ||
hasIndex && | ||
(typeof index !== 'number' || index < 0 || index === Infinity) | ||
) { | ||
throw new Error('Expected positive finite index for child node') | ||
} | ||
if ( | ||
index !== undefined && | ||
index !== null && | ||
(typeof index !== 'number' || | ||
index < 0 || | ||
index === Number.POSITIVE_INFINITY) | ||
) { | ||
throw new Error('Expected positive finite index for child node') | ||
} | ||
if (hasParent && (!parent.type || !parent.children)) { | ||
throw new Error('Expected parent node') | ||
if ( | ||
parent !== undefined && | ||
parent !== null && | ||
(!parent.type || !parent.children) | ||
) { | ||
throw new Error('Expected parent node') | ||
} | ||
// @ts-ignore Looks like a node. | ||
if (!node || !node.type || typeof node.type !== 'string') { | ||
return false | ||
} | ||
if ( | ||
(parent === undefined || parent === null) !== | ||
(index === undefined || index === null) | ||
) { | ||
throw new Error('Expected both parent and index') | ||
} | ||
return check.call(context, node, index, parent) | ||
} | ||
) | ||
export const convertElement = | ||
/** | ||
* @type {( | ||
* (<T extends Element>(test: T['tagName']|TestFunctionPredicate<T>) => AssertPredicate<T>) & | ||
* ((test?: null|undefined|TagName|TestFunctionAnything|Array.<TagName|TestFunctionAnything>) => AssertPredicate<Element>) | ||
* )} | ||
*/ | ||
( | ||
/** | ||
* Generate an assertion from a check. | ||
* @param {null|undefined|TagName|TestFunctionAnything|Array.<TagName|TestFunctionAnything>} [test] | ||
* When nullish, checks if `node` is a `Node`. | ||
* When `string`, works like passing `function (node) {return node.type === test}`. | ||
* When `function` checks if function passed the node is true. | ||
* When `object`, checks that all keys in test are in node, and that they have (strictly) equal values. | ||
* When `array`, checks any one of the subtests pass. | ||
* @returns {AssertPredicate<Element>} | ||
*/ | ||
function (test) { | ||
if (test === undefined || test === null) { | ||
return element | ||
} | ||
if (typeof test === 'string') { | ||
return tagNameFactory(test) | ||
} | ||
if (typeof test === 'object') { | ||
return anyFactory(test) | ||
} | ||
if (typeof test === 'function') { | ||
return castFactory(test) | ||
} | ||
throw new Error('Expected function, string, or array as test') | ||
} | ||
) | ||
/** | ||
* @param {Array.<TagName|TestFunctionAnything>} tests | ||
* @returns {AssertPredicate<Element>} | ||
*/ | ||
function anyFactory(tests) { | ||
/** @type {Array.<AssertPredicate<Element>>} */ | ||
var checks = [] | ||
var index = -1 | ||
while (++index < tests.length) { | ||
checks[index] = convertElement(tests[index]) | ||
} | ||
if (!node || !node.type || typeof node.type !== 'string') { | ||
return castFactory(any) | ||
/** | ||
* @this {unknown} | ||
* @param {unknown[]} parameters | ||
* @returns {node is Element} | ||
*/ | ||
function any(...parameters) { | ||
var index = -1 | ||
while (++index < checks.length) { | ||
if (checks[index].call(this, ...parameters)) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
} | ||
if (hasParent !== hasIndex) { | ||
throw new Error('Expected both parent and index') | ||
/** | ||
* Utility to convert a string into a function which checks a given nodeβs tag | ||
* name for said string. | ||
* | ||
* @param {TagName} check | ||
* @returns {AssertPredicate<Element>} | ||
*/ | ||
function tagNameFactory(check) { | ||
return tagName | ||
/** | ||
* @param {Node} node | ||
* @returns {node is Element} | ||
*/ | ||
function tagName(node) { | ||
return element(node) && node.tagName === check | ||
} | ||
} | ||
return check.call(context, node, index, parent) | ||
/** | ||
* @param {TestFunctionAnything} check | ||
* @returns {AssertPredicate<Element>} | ||
*/ | ||
function castFactory(check) { | ||
return assertion | ||
/** | ||
* @this {unknown} | ||
* @param {Node} node | ||
* @param {Array.<unknown>} parameters | ||
* @returns {node is Element} | ||
*/ | ||
function assertion(node, ...parameters) { | ||
return element(node) && Boolean(check.call(this, node, ...parameters)) | ||
} | ||
} | ||
/** | ||
* Utility to return true if this is an element. | ||
* @param {unknown} node | ||
* @returns {node is Element} | ||
*/ | ||
function element(node) { | ||
return Boolean( | ||
node && | ||
typeof node === 'object' && | ||
// @ts-ignore Looks like a node. | ||
node.type === 'element' && | ||
// @ts-ignore Looks like an element. | ||
typeof node.tagName === 'string' | ||
) | ||
} |
{ | ||
"name": "hast-util-is-element", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"description": "hast utility to check if a node is a (certain) element", | ||
@@ -26,25 +26,35 @@ "license": "MIT", | ||
], | ||
"sideEffects": false, | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"convert.js", | ||
"index.d.ts", | ||
"index.js" | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"@types/hast": "^2.0.0", | ||
"@types/unist": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"browserify": "^16.0.0", | ||
"nyc": "^15.0.0", | ||
"@types/tape": "^4.0.0", | ||
"c8": "^7.0.0", | ||
"prettier": "^2.0.0", | ||
"remark-cli": "^8.0.0", | ||
"remark-preset-wooorm": "^7.0.0", | ||
"remark-cli": "^9.0.0", | ||
"remark-preset-wooorm": "^8.0.0", | ||
"rimraf": "^3.0.0", | ||
"tape": "^5.0.0", | ||
"tinyify": "^3.0.0", | ||
"xo": "^0.33.0" | ||
"tsd": "^0.14.0", | ||
"type-coverage": "^2.0.0", | ||
"typescript": "^4.0.0", | ||
"unified": "^9.0.0", | ||
"xo": "^0.38.0" | ||
}, | ||
"scripts": { | ||
"format": "remark . -qfo && prettier . --write && xo --fix", | ||
"build-bundle": "browserify . -s hastUtilIsElement > hast-util-is-element.js", | ||
"build-mangle": "browserify . -s hastUtilIsElement -p tinyify > hast-util-is-element.min.js", | ||
"build": "npm run build-bundle && npm run build-mangle", | ||
"test-api": "node test", | ||
"test-coverage": "nyc --reporter lcov tape test.js", | ||
"test": "npm run format && npm run build && npm run test-coverage" | ||
"prepack": "npm run build && npm run format", | ||
"build": "rimraf \"*.d.ts\" && tsc && tsd && 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", | ||
"test": "npm run build && npm run format && npm run test-coverage" | ||
}, | ||
@@ -61,18 +71,7 @@ "prettier": { | ||
"prettier": true, | ||
"esnext": false, | ||
"rules": { | ||
"max-params": "off", | ||
"unicorn/prefer-includes": "off", | ||
"unicorn/prefer-reflect-apply": "off" | ||
}, | ||
"ignores": [ | ||
"hast-util-is-element.js" | ||
] | ||
"no-var": "off", | ||
"prefer-arrow-callback": "off" | ||
} | ||
}, | ||
"nyc": { | ||
"check-coverage": true, | ||
"lines": 100, | ||
"functions": 100, | ||
"branches": 100 | ||
}, | ||
"remarkConfig": { | ||
@@ -82,3 +81,8 @@ "plugins": [ | ||
] | ||
}, | ||
"typeCoverage": { | ||
"atLeast": 100, | ||
"detail": true, | ||
"strict": true | ||
} | ||
} |
@@ -16,2 +16,5 @@ # hast-util-is-element | ||
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): | ||
Node 12+ is needed to use it and it must be `import`ed instead of `require`d. | ||
[npm][]: | ||
@@ -26,9 +29,9 @@ | ||
```js | ||
var is = require('hast-util-is-element') | ||
import {isElement} from 'hast-util-is-element' | ||
is({type: 'text', value: 'foo'}) // => false | ||
isElement({type: 'text', value: 'foo'}) // => false | ||
is({type: 'element', tagName: 'a'}, 'a') // => true | ||
isElement({type: 'element', tagName: 'a'}, 'a') // => true | ||
is({type: 'element', tagName: 'a'}, ['a', 'area']) // => true | ||
isElement({type: 'element', tagName: 'a'}, ['a', 'area']) // => true | ||
``` | ||
@@ -38,2 +41,5 @@ | ||
This package exports the following identifiers: `isElement`, `convertElement`. | ||
There is no default export. | ||
### `isElement(node[, test[, index, parent[, context]]])` | ||
@@ -77,3 +83,3 @@ | ||
### `isElement.convert(test)` | ||
### `convertElement(test)` | ||
@@ -88,4 +94,2 @@ Create a test function from `test`, that can later be called with a `node`, | ||
Can also be accessed with `require('hast-util-is-element/convert')`. | ||
## Security | ||
@@ -145,5 +149,5 @@ | ||
[build-badge]: https://img.shields.io/travis/syntax-tree/hast-util-is-element.svg | ||
[build-badge]: https://github.com/syntax-tree/hast-util-is-element/workflows/main/badge.svg | ||
[build]: https://travis-ci.org/syntax-tree/hast-util-is-element | ||
[build]: https://github.com/syntax-tree/hast-util-is-element/actions | ||
@@ -150,0 +154,0 @@ [coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/hast-util-is-element.svg |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18882
301
195
Yes
2
12
1
+ Added@types/hast@^2.0.0
+ Added@types/unist@^2.0.0
+ Added@types/hast@2.3.10(transitive)
+ Added@types/unist@2.0.11(transitive)