From 4c74f03f685e964ba57c2ac1973b4b646557f6ae Mon Sep 17 00:00:00 2001 From: Titus Date: Mon, 16 Jan 2023 16:28:15 +0100 Subject: [PATCH 01/10] Use Node 16 in Actions Signed-off-by: Titus --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ee318ca..fb63387 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,5 +17,5 @@ jobs: strategy: matrix: node: - - lts/hydrogen + - lts/gallium - node From 57378999cb8a20570c0157c9d65b2cb56c7e0e2b Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 13:36:32 +0200 Subject: [PATCH 02/10] Update dev-dependencies --- package.json | 10 +++++----- test/core.js | 11 +++++++++++ test/index.js | 13 +------------ 3 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 test/core.js diff --git a/package.json b/package.json index 9ecb287..7b9d7b4 100644 --- a/package.json +++ b/package.json @@ -41,15 +41,15 @@ "@types/unist": "^2.0.0" }, "devDependencies": { - "@types/node": "^18.0.0", - "c8": "^7.0.0", + "@types/node": "^20.0.0", + "c8": "^8.0.0", "prettier": "^2.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", - "tsd": "^0.25.0", + "tsd": "^0.28.0", "type-coverage": "^2.0.0", - "typescript": "^4.0.0", - "xo": "^0.53.0" + "typescript": "^5.0.0", + "xo": "^0.54.0" }, "scripts": { "prepack": "npm run build && npm run format", diff --git a/test/core.js b/test/core.js new file mode 100644 index 0000000..b7682d5 --- /dev/null +++ b/test/core.js @@ -0,0 +1,11 @@ +import assert from 'node:assert/strict' +import test from 'node:test' +import * as mod from '../index.js' + +test('assert', () => { + assert.deepEqual( + Object.keys(mod).sort(), + ['_void', 'assert', 'literal', 'parent', 'wrap'], + 'should expose the public api' + ) +}) diff --git a/test/index.js b/test/index.js index 4f863a5..d2e8419 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,5 @@ /* eslint-disable import/no-unassigned-import */ +import './core.js' import './node.js' import './type.js' import './value.js' @@ -9,15 +10,3 @@ import './parent.js' import './literal.js' import './void.js' /* eslint-enable import/no-unassigned-import */ - -import assert from 'node:assert/strict' -import test from 'node:test' -import * as mod from '../index.js' - -test('assert', () => { - assert.deepEqual( - Object.keys(mod).sort(), - ['_void', 'assert', 'literal', 'parent', 'wrap'], - 'should expose the public api' - ) -}) From e429ed80c73ccdb1e5261b982fe876995ce99e69 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 13:37:26 +0200 Subject: [PATCH 03/10] Refactor `package.json`, `tsconfig.json` --- package.json | 24 ++++++++++++------------ tsconfig.json | 10 ++++------ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 7b9d7b4..7f6631d 100644 --- a/package.json +++ b/package.json @@ -56,33 +56,33 @@ "build": "tsc --build --clean && tsc --build && tsd && type-coverage", "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix", "test-api": "node --conditions development test/index.js", - "test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api", + "test-coverage": "c8 --100 --reporter lcov npm run test-api", "test": "npm run build && npm run format && npm run test-coverage" }, "prettier": { - "tabWidth": 2, - "useTabs": false, - "singleQuote": true, "bracketSpacing": false, "semi": false, - "trailingComma": "none" - }, - "xo": { - "prettier": true + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false }, "remarkConfig": { "plugins": [ - "preset-wooorm" + "remark-preset-wooorm" ] }, "typeCoverage": { "atLeast": 100, "detail": true, - "strict": true, "ignoreCatch": true, - "#": "Couple of needed any’s", + "#": "Couple of needed any’s", "ignoreFiles": [ "lib/index.d.ts" - ] + ], + "strict": true + }, + "xo": { + "prettier": true } } diff --git a/tsconfig.json b/tsconfig.json index 1bc9e99..870d82c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,15 @@ { - "include": ["**/**.js"], - "exclude": ["coverage/", "node_modules/"], "compilerOptions": { "checkJs": true, + "customConditions": ["development"], "declaration": true, "emitDeclarationOnly": true, "exactOptionalPropertyTypes": true, - "forceConsistentCasingInFileNames": true, "lib": ["es2020"], "module": "node16", - "newLine": "lf", - "skipLibCheck": true, "strict": true, "target": "es2020" - } + }, + "exclude": ["coverage/", "node_modules/"], + "include": ["**/*.js"] } From d9ff3b86e7edc26bce778a4035fa27d1ce605149 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 14:04:11 +0200 Subject: [PATCH 04/10] Refactor code-style --- index.test-d.ts | 2 +- lib/index.js | 55 +++++++--- package.json | 10 ++ readme.md | 2 +- test/children.js | 46 +++++---- test/core.js | 17 +-- test/index.js | 12 +-- test/literal.js | 46 +++++---- test/node.js | 42 +++----- test/non-defined.js | 54 +++++----- test/parent.js | 46 +++++---- test/position.js | 247 +++++++++++++++++++++++++++----------------- test/type.js | 56 +++++----- test/value.js | 53 ++++++---- test/void.js | 46 +++++---- 15 files changed, 422 insertions(+), 312 deletions(-) diff --git a/index.test-d.ts b/index.test-d.ts index e1b4525..4802246 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,4 +1,4 @@ -import {expectType, expectNotType} from 'tsd' +import {expectNotType, expectType} from 'tsd' import type {Node, Parent} from 'unist' import {assert, parent} from './index.js' diff --git a/lib/index.js b/lib/index.js index dbdcd71..ba2ce1a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,12 +1,22 @@ /** - * @typedef {import('assert').AssertionError} AssertionError - * Assertion error from `node:assert`. + * @typedef {import('node:assert').AssertionError} AssertionError * + * @typedef {import('unist').Literal} Literal * @typedef {import('unist').Node} Node * @typedef {import('unist').Parent} Parent - * @typedef {import('unist').Literal} Literal - * @typedef {import('unist').Position} Position * @typedef {import('unist').Point} Point + * @typedef {import('unist').Position} Position + */ + +/** + * @template T + * @callback CustomAssertion + * @param {any} [node] + * @param {Parent | null | undefined} [parent] + * @returns {asserts node is T} + */ + +/** * @typedef {Node & {children: never, value: never}} _Void * * @typedef SeenErrorFields @@ -100,9 +110,9 @@ const defined = new Set(['type', 'value', 'children', 'position']) * * @template {Node} T * Node type. - * @param {(node?: any, parent?: Parent | null | undefined) => asserts node is T} fn + * @param {CustomAssertion} fn * Custom assertion. - * @returns {(node?: any, parent?: Parent | null | undefined) => asserts node is T} + * @returns {CustomAssertion} * Assertion. */ export function wrap(fn) { @@ -115,7 +125,7 @@ export function wrap(fn) { * Optional, valid parent. * @throws {AssertionError} * Whether `node` is a node but neither parent nor literal. - * @returns {void} + * @returns {undefined} * Nothing. */ function wrapped(node, parent) { @@ -153,28 +163,24 @@ function assertNode(node) { node && typeof node === 'object' && !Array.isArray(node), 'node should be an object' ) + indexable(node) nodeAssert.ok(own.call(node, 'type'), 'node should have a type') nodeAssert.strictEqual( - // @ts-expect-error Looks like an indexed object. typeof node.type, 'string', '`type` should be a string' ) - // @ts-expect-error Looks like an indexed object. nodeAssert.notStrictEqual(node.type, '', '`type` should not be empty') - // @ts-expect-error Looks like an indexed object. if (node.value !== null && node.value !== undefined) { nodeAssert.strictEqual( - // @ts-expect-error Looks like an indexed object. typeof node.value, 'string', '`value` should be a string' ) } - // @ts-expect-error Looks like an indexed object. position(node.position) /** @type {string} */ @@ -182,14 +188,11 @@ function assertNode(node) { for (key in node) { if (!defined.has(key)) { - /** @type {unknown} */ - // @ts-expect-error: hush. const value = node[key] vanilla(key, value) } } - // @ts-expect-error Looks like an indexed object. if (node.children !== null && node.children !== undefined) { /** @type {Parent} */ // @ts-expect-error Looks like parent. @@ -324,9 +327,8 @@ function position(position) { '`position` should be an object' ) - // @ts-expect-error: indexable. + indexable(position) point(position.start, 'position.start') - // @ts-expect-error: indexable. point(position.end, 'position.end') } } @@ -374,3 +376,22 @@ function point(point, label) { } } } + +/** + * TypeScript helper to check if something is indexable (any object is + * indexable in JavaScript). + * + * @param {unknown} value + * Thing to check. + * @returns {asserts value is Record} + * Nothing. + * @throws {Error} + * When `value` is not an object. + */ +function indexable(value) { + // Always called when something is an object, this is just for TS. + /* c8 ignore next 3 */ + if (!value || typeof value !== 'object') { + throw new Error('Expected object') + } +} diff --git a/package.json b/package.json index 7f6631d..e269b38 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,16 @@ "strict": true }, "xo": { + "overrides": [ + { + "files": [ + "test/**/*.js" + ], + "rules": { + "import/no-unassigned-import": "off" + } + } + ], "prettier": true } } diff --git a/readme.md b/readme.md index 384f48b..c98754d 100644 --- a/readme.md +++ b/readme.md @@ -69,7 +69,7 @@ In browsers with [`esm.sh`][esmsh]: ## Use ```js -import {assert, parent, _void} from 'unist-util-assert' +import {_void, assert, parent} from 'unist-util-assert' assert({type: 'root', children: []}) assert({type: 'break'}) diff --git a/test/children.js b/test/children.js index 6a8e27c..29ea1ce 100644 --- a/test/children.js +++ b/test/children.js @@ -2,29 +2,33 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('children', () => { - nodeAssert.throws( - () => { - assert({type: 'foo', children: {alpha: 'bravo'}}) - }, - /`children` should be an array: `{ type: 'foo', children: { alpha: 'bravo' } }`$/, - 'should throw if given a non-node child in children' +test('children', async function (t) { + await t.test( + 'should throw if given a non-node child in children', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', children: {alpha: 'bravo'}}) + }, /`children` should be an array: `{ type: 'foo', children: { alpha: 'bravo' } }`$/) + } ) - nodeAssert.throws( - () => { - assert({type: 'foo', children: ['one']}) - }, - /node should be an object: `'one'` in `{ type: 'foo', children: \[ 'one' ] }`$/, - 'should throw if given a non-node child in children' + await t.test( + 'should throw if given a non-node child in children', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', children: ['one']}) + }, /node should be an object: `'one'` in `{ type: 'foo', children: \[ 'one' ] }`$/) + } ) - nodeAssert.doesNotThrow(() => { - assert({type: 'parent', children: [{type: 'text', value: 'alpha'}]}) - }, 'should not throw on vald children') + await t.test('should not throw on vald children', async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'parent', children: [{type: 'text', value: 'alpha'}]}) + }) + }) - nodeAssert.throws( - () => { + await t.test('should throw on invalid descendants', async function () { + nodeAssert.throws(function () { assert({ type: 'foo', children: [ @@ -34,8 +38,6 @@ test('children', () => { } ] }) - }, - /node should be an object: `'one'` in `{ type: 'bar', children: \[ 'one' ] }`$/, - 'should throw on invalid descendants' - ) + }, /node should be an object: `'one'` in `{ type: 'bar', children: \[ 'one' ] }`$/) + }) }) diff --git a/test/core.js b/test/core.js index b7682d5..98d8e3a 100644 --- a/test/core.js +++ b/test/core.js @@ -1,11 +1,14 @@ import assert from 'node:assert/strict' import test from 'node:test' -import * as mod from '../index.js' -test('assert', () => { - assert.deepEqual( - Object.keys(mod).sort(), - ['_void', 'assert', 'literal', 'parent', 'wrap'], - 'should expose the public api' - ) +test('assert', async function (t) { + await t.test('should expose the public api', async function () { + assert.deepEqual(Object.keys(await import('../index.js')).sort(), [ + '_void', + 'assert', + 'literal', + 'parent', + 'wrap' + ]) + }) }) diff --git a/test/index.js b/test/index.js index d2e8419..c9ea1b8 100644 --- a/test/index.js +++ b/test/index.js @@ -1,12 +1,10 @@ -/* eslint-disable import/no-unassigned-import */ +import './children.js' import './core.js' +import './literal.js' import './node.js' -import './type.js' -import './value.js' -import './children.js' -import './position.js' import './non-defined.js' import './parent.js' -import './literal.js' +import './position.js' +import './type.js' +import './value.js' import './void.js' -/* eslint-enable import/no-unassigned-import */ diff --git a/test/literal.js b/test/literal.js index b0c11fd..14f32e4 100644 --- a/test/literal.js +++ b/test/literal.js @@ -2,32 +2,34 @@ import assert from 'node:assert/strict' import test from 'node:test' import {literal} from '../index.js' -test('literal()', () => { - assert.throws( - () => { +test('literal()', async function (t) { + await t.test('should throw the same errors as `assert()`', async function () { + assert.throws(function () { literal({}) - }, - /node should have a type: `{}`$/, - 'should throw the same errors as `assert()`' - ) + }, /node should have a type: `{}`$/) + }) - assert.throws( - () => { - literal({type: 'strong', children: []}) - }, - /literal should not have `children`: `{ type: 'strong', children: \[] }`$/, - 'should throw if the given node has `children`' + await t.test( + 'should throw if the given node has `children`', + async function () { + assert.throws(function () { + literal({type: 'strong', children: []}) + }, /literal should not have `children`: `{ type: 'strong', children: \[] }`$/) + } ) - assert.throws( - () => { - literal({type: 'break'}) - }, - /literal should have `value`: `{ type: 'break' }`$/, - 'should throw if the given node has no `value`' + await t.test( + 'should throw if the given node has no `value`', + async function () { + assert.throws(function () { + literal({type: 'break'}) + }, /literal should have `value`: `{ type: 'break' }`$/) + } ) - assert.doesNotThrow(() => { - literal({type: 'text', value: 'foo'}) - }, 'should not throw on valid text nodes') + await t.test('should not throw on valid text nodes', async function () { + assert.doesNotThrow(function () { + literal({type: 'text', value: 'foo'}) + }) + }) }) diff --git a/test/node.js b/test/node.js index f9da6d6..c1bba41 100644 --- a/test/node.js +++ b/test/node.js @@ -2,36 +2,28 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('node', () => { - nodeAssert.throws( - () => { +test('node', async function (t) { + await t.test('should throw if not given a node (#1)', async function () { + nodeAssert.throws(function () { assert() - }, - /node should be an object: `undefined`$/, - 'should throw if not given a node (#1)' - ) + }, /node should be an object: `undefined`$/) + }) - nodeAssert.throws( - () => { + await t.test('should throw if not given a node (#2)', async function () { + nodeAssert.throws(function () { assert(null) - }, - /node should be an object: `null`$/, - 'should throw if not given a node (#2)' - ) + }, /node should be an object: `null`$/) + }) - nodeAssert.throws( - () => { + await t.test('should throw if given a non-node (#1)', async function () { + nodeAssert.throws(function () { assert('foo') - }, - /node should be an object: `'foo'`$/, - 'should throw if given a non-node (#1)' - ) + }, /node should be an object: `'foo'`$/) + }) - nodeAssert.throws( - () => { + await t.test('should throw if not given a non-node (#2)', async function () { + nodeAssert.throws(function () { assert(6) - }, - /node should be an object: `6`$/, - 'should throw if not given a non-node (#2)' - ) + }, /node should be an object: `6`$/) + }) }) diff --git a/test/non-defined.js b/test/non-defined.js index abe7431..d5c11e3 100644 --- a/test/non-defined.js +++ b/test/non-defined.js @@ -2,30 +2,36 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('non-defined', () => { - nodeAssert.doesNotThrow(() => { - assert({ - type: 'element', - properties: { - className: ['alpha'], - id: 'bravo' - }, - children: [], - position: {}, - data: { - charlie: 'delta' - } - }) - }, 'should not throw if non-defined properties are found') - - nodeAssert.throws( - () => { - assert({ - type: 'break', - data: {foo: Function} +test('non-defined', async function (t) { + await t.test( + 'should not throw if non-defined properties are found', + async function () { + nodeAssert.doesNotThrow(function () { + assert({ + type: 'element', + properties: { + className: ['alpha'], + id: 'bravo' + }, + children: [], + position: {}, + data: { + charlie: 'delta' + } + }) }) - }, - /non-specced property `data` should be JSON: `{ type: 'break', data: { foo: \[Function: Function] } }`$/, - 'should throw if non-defined properties are not serialisable' + } + ) + + await t.test( + 'should throw if non-defined properties are not serialisable', + async function () { + nodeAssert.throws(function () { + assert({ + type: 'break', + data: {foo: Function} + }) + }, /non-specced property `data` should be JSON: `{ type: 'break', data: { foo: \[Function: Function] } }`$/) + } ) }) diff --git a/test/parent.js b/test/parent.js index c247a19..416b0f9 100644 --- a/test/parent.js +++ b/test/parent.js @@ -2,32 +2,34 @@ import assert from 'node:assert/strict' import test from 'node:test' import {parent} from '../index.js' -test('parent()', () => { - assert.throws( - () => { +test('parent()', async function (t) { + await t.test('should throw the same errors as `assert()`', async function () { + assert.throws(function () { parent({}) - }, - /node should have a type: `{}`$/, - 'should throw the same errors as `assert()`' - ) + }, /node should have a type: `{}`$/) + }) - assert.throws( - () => { - parent({type: 'text', value: 'foo'}) - }, - /parent should not have `value`: `{ type: 'text', value: 'foo' }`$/, - 'should throw if the given node has a `value`' + await t.test( + 'should throw if the given node has a `value`', + async function () { + assert.throws(function () { + parent({type: 'text', value: 'foo'}) + }, /parent should not have `value`: `{ type: 'text', value: 'foo' }`$/) + } ) - assert.throws( - () => { - parent({type: 'break'}) - }, - /parent should have `children`: `{ type: 'break' }`$/, - 'should throw if the given node has `children`' + await t.test( + 'should throw if the given node has `children`', + async function () { + assert.throws(function () { + parent({type: 'break'}) + }, /parent should have `children`: `{ type: 'break' }`$/) + } ) - assert.doesNotThrow(() => { - parent({type: 'strong', children: []}) - }, 'should not throw on valid void nodes') + await t.test('should not throw on valid void nodes', async function () { + assert.doesNotThrow(function () { + parent({type: 'strong', children: []}) + }) + }) }) diff --git a/test/position.js b/test/position.js index 7c09655..73945da 100644 --- a/test/position.js +++ b/test/position.js @@ -2,100 +2,157 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('position', () => { - nodeAssert.throws( - () => { - assert({type: 'foo', position: 1}) - }, - /`position` should be an object: `{ type: 'foo', position: 1 }`$/, - 'should throw if given a non-object `position`' - ) - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: null}) - }, 'should not throw if given a null `position`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {}}) - }, 'should not throw if given an empty `position` object') - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {start: 1}}) - }, - /`position.start` should be an object: `{ type: 'foo', position: { start: 1 } }`$/, - 'should throw if given a non-object `position.start`' - ) - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {start: null}}) - }, 'should not throw if given a null `position.start`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {start: {}}}) - }, 'should not throw if given an empty `position.start` object') - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {end: 1}}) - }, - /`position.end` should be an object: `{ type: 'foo', position: { end: 1 } }`$/, - 'should throw if given a non-object `position.end`' - ) - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {end: null}}) - }, 'should not throw if given a null `position.end`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {end: {}}}) - }, 'should not throw if given an empty `position.end` object') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {start: {line: null}}}) - }, 'should not throw if given a `position.start.line` to `null`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {start: {column: null}}}) - }, 'should not throw if given a `position.start.column` to `null`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {end: {line: null}}}) - }, 'should not throw if given a `position.end.line` to `null`') - - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', position: {end: {column: null}}}) - }, 'should not throw if given a `position.end.column` to `null`') - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {start: {line: 0}}}) - }, - /`position.start.line` should be gte `1`: `{ type: 'foo', position: { start: { line: 0 } } }`$/, - 'should throw if `position.start.line` is less than 1' - ) - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {start: {column: 0}}}) - }, - /`position.start.column` should be gte `1`: `{ type: 'foo', position: { start: { column: 0 } } }`$/, - 'should throw if `position.start.column` is less than 1' - ) - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {end: {line: 0}}}) - }, - /`position.end.line` should be gte `1`: `{ type: 'foo', position: { end: { line: 0 } } }`$/, - 'should throw if `position.end.line` is less than 1' - ) - - nodeAssert.throws( - () => { - assert({type: 'foo', position: {end: {column: 0}}}) - }, - /`position.end.column` should be gte `1`: `{ type: 'foo', position: { end: { column: 0 } } }`$/, - 'should throw if `position.end.column` is less than 1' +test('position', async function (t) { + await t.test( + 'should throw if given a non-object `position`', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: 1}) + }, /`position` should be an object: `{ type: 'foo', position: 1 }`$/) + } + ) + + await t.test( + 'should not throw if given a null `position`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: null}) + }) + } + ) + + await t.test( + 'should not throw if given an empty `position` object', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {}}) + }) + } + ) + + await t.test( + 'should throw if given a non-object `position.start`', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {start: 1}}) + }, /`position.start` should be an object: `{ type: 'foo', position: { start: 1 } }`$/) + } + ) + + await t.test( + 'should not throw if given a null `position.start`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {start: null}}) + }) + } + ) + + await t.test( + 'should not throw if given an empty `position.start` object', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {start: {}}}) + }) + } + ) + + await t.test( + 'should throw if given a non-object `position.end`', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {end: 1}}) + }, /`position.end` should be an object: `{ type: 'foo', position: { end: 1 } }`$/) + } + ) + + await t.test( + 'should not throw if given a null `position.end`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {end: null}}) + }) + } + ) + + await t.test( + 'should not throw if given an empty `position.end` object', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {end: {}}}) + }) + } + ) + + await t.test( + 'should not throw if given a `position.start.line` to `null`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {start: {line: null}}}) + }) + } + ) + + await t.test( + 'should not throw if given a `position.start.column` to `null`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {start: {column: null}}}) + }) + } + ) + + await t.test( + 'should not throw if given a `position.end.line` to `null`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {end: {line: null}}}) + }) + } + ) + + await t.test( + 'should not throw if given a `position.end.column` to `null`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', position: {end: {column: null}}}) + }) + } + ) + + await t.test( + 'should throw if `position.start.line` is less than 1', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {start: {line: 0}}}) + }, /`position.start.line` should be gte `1`: `{ type: 'foo', position: { start: { line: 0 } } }`$/) + } + ) + + await t.test( + 'should throw if `position.start.column` is less than 1', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {start: {column: 0}}}) + }, /`position.start.column` should be gte `1`: `{ type: 'foo', position: { start: { column: 0 } } }`$/) + } + ) + + await t.test( + 'should throw if `position.end.line` is less than 1', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {end: {line: 0}}}) + }, /`position.end.line` should be gte `1`: `{ type: 'foo', position: { end: { line: 0 } } }`$/) + } + ) + + await t.test( + 'should throw if `position.end.column` is less than 1', + async function () { + nodeAssert.throws(function () { + assert({type: 'foo', position: {end: {column: 0}}}) + }, /`position.end.column` should be gte `1`: `{ type: 'foo', position: { end: { column: 0 } } }`$/) + } ) }) diff --git a/test/type.js b/test/type.js index 52e2afd..47ae94d 100644 --- a/test/type.js +++ b/test/type.js @@ -2,40 +2,40 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('type', () => { - nodeAssert.throws( - () => { +test('type', async function (t) { + await t.test('should throw if not given a `type` (#1)', async function () { + nodeAssert.throws(function () { assert({}) - }, - /node should have a type: `{}`$/, - 'should throw if not given a `type` (#1)' - ) + }, /node should have a type: `{}`$/) + }) - nodeAssert.throws( - () => { + await t.test('should throw if not given a type (#2)', async function () { + nodeAssert.throws(function () { assert({value: 'foo'}) - }, - /node should have a type: `{ value: 'foo' }`$/, - 'should throw if not given a type (#2)' - ) + }, /node should have a type: `{ value: 'foo' }`$/) + }) - nodeAssert.throws( - () => { - assert({type: 1}) - }, - /`type` should be a string: `{ type: 1 }`$/, - 'should throw if not given a non-string type' + await t.test( + 'should throw if not given a non-string type', + async function () { + nodeAssert.throws(function () { + assert({type: 1}) + }, /`type` should be a string: `{ type: 1 }`$/) + } ) - nodeAssert.throws( - () => { + await t.test('should throw if given an empty string type', async function () { + nodeAssert.throws(function () { assert({type: ''}) - }, - /`type` should not be empty: `{ type: '' }`$/, - 'should throw if given an empty string type' - ) + }, /`type` should not be empty: `{ type: '' }`$/) + }) - nodeAssert.doesNotThrow(() => { - assert({type: 'foo'}) - }, 'should not throw if given a non-empty type string') + await t.test( + 'should not throw if given a non-empty type string', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo'}) + }) + } + ) }) diff --git a/test/value.js b/test/value.js index f2f50e5..4ddfde0 100644 --- a/test/value.js +++ b/test/value.js @@ -2,28 +2,43 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' import {assert} from '../index.js' -test('value', () => { - nodeAssert.throws( - () => { +test('value', async function (t) { + await t.test('should throw if given a non-string `value`', async function () { + nodeAssert.throws(function () { assert({type: 'foo', value: 1}) - }, - /`value` should be a string: `{ type: 'foo', value: 1 }`$/, - 'should throw if given a non-string `value`' - ) + }, /`value` should be a string: `{ type: 'foo', value: 1 }`$/) + }) - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', value: ''}) - }, 'should not throw if given an empty string `value`') + await t.test( + 'should not throw if given an empty string `value`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', value: ''}) + }) + } + ) - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', value: 'foo'}) - }, 'should not throw if given an string `value`') + await t.test( + 'should not throw if given an string `value`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', value: 'foo'}) + }) + } + ) - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', value: undefined}) - }, 'should not throw if given an undefined `value`') + await t.test( + 'should not throw if given an undefined `value`', + async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', value: undefined}) + }) + } + ) - nodeAssert.doesNotThrow(() => { - assert({type: 'foo', value: null}) - }, 'should not throw if given an null `value`') + await t.test('should not throw if given an null `value`', async function () { + nodeAssert.doesNotThrow(function () { + assert({type: 'foo', value: null}) + }) + }) }) diff --git a/test/void.js b/test/void.js index 7384f2c..1354d24 100644 --- a/test/void.js +++ b/test/void.js @@ -2,32 +2,34 @@ import assert from 'node:assert/strict' import test from 'node:test' import {_void} from '../index.js' -test('_void()', () => { - assert.throws( - () => { +test('_void()', async function (t) { + await t.test('should throw the same errors as `assert()`', async function () { + assert.throws(function () { _void({}) - }, - /node should have a type: `{}`$/, - 'should throw the same errors as `assert()`' - ) + }, /node should have a type: `{}`$/) + }) - assert.throws( - () => { - _void({type: 'text', value: 'foo'}) - }, - /void should not have `value`: `{ type: 'text', value: 'foo' }`$/, - 'should throw if the given node has a `value`' + await t.test( + 'should throw if the given node has a `value`', + async function () { + assert.throws(function () { + _void({type: 'text', value: 'foo'}) + }, /void should not have `value`: `{ type: 'text', value: 'foo' }`$/) + } ) - assert.throws( - () => { - _void({type: 'strong', children: []}) - }, - /void should not have `children`: `{ type: 'strong', children: \[] }`$/, - 'should throw if the given node has `children`' + await t.test( + 'should throw if the given node has `children`', + async function () { + assert.throws(function () { + _void({type: 'strong', children: []}) + }, /void should not have `children`: `{ type: 'strong', children: \[] }`$/) + } ) - assert.doesNotThrow(() => { - _void({type: 'break'}) - }, 'should not throw on valid void nodes') + await t.test('should not throw on valid void nodes', async function () { + assert.doesNotThrow(function () { + _void({type: 'break'}) + }) + }) }) From f19e56ac8f62683369b15b80ebefa648fcbe01cc Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 14:04:24 +0200 Subject: [PATCH 05/10] Refactor `.npmrc` --- .npmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.npmrc b/.npmrc index 9951b11..3757b30 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,2 @@ -package-lock=false ignore-scripts=true +package-lock=false From 4e4061b404a7d7ebfbdfa93d2c1651ddf5eae0d7 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 14:05:41 +0200 Subject: [PATCH 06/10] Refactor docs --- readme.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index c98754d..ebc8ca3 100644 --- a/readme.md +++ b/readme.md @@ -46,7 +46,7 @@ do the same but for mdast, hast, and nlcst nodes, respectively. ## Install This package is [ESM only][esm]. -In Node.js (version 14.14+ and 16.0+), install with [npm][]: +In Node.js (version 16+), install with [npm][]: ```sh npm install unist-util-assert @@ -218,10 +218,13 @@ It exports the additional type [`AssertionError`][assertionerror]. ## Compatibility -Projects maintained by the unified collective are compatible with all maintained +Projects maintained by the unified collective are compatible with maintained versions of Node.js. -As of now, that is Node.js 14.14+ and 16.0+. -Our projects sometimes work with older versions, but this is not guaranteed. + +When we cut a new major release, we drop support for unmaintained versions of +Node. +This means we try to keep the current release line, `unist-util-assert@^3`, +compatible with Node.js 12. ## Related @@ -260,9 +263,9 @@ abide by its terms. [downloads]: https://www.npmjs.com/package/unist-util-assert -[size-badge]: https://img.shields.io/bundlephobia/minzip/unist-util-assert.svg +[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=unist-util-assert -[size]: https://bundlephobia.com/result?p=unist-util-assert +[size]: https://bundlejs.com/?q=unist-util-assert [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg From 6dacb525442a9dbf40f5c91983c149f419c7be8a Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 14:10:30 +0200 Subject: [PATCH 07/10] Change to use `export` map --- index.test-d.ts | 2 +- lib/index.js | 2 +- lib/{inspect.browser.js => inspect.default.js} | 0 lib/{inspect.js => inspect.node.js} | 0 package.json | 13 ++++++------- test/children.js | 2 +- test/core.js | 2 +- test/literal.js | 2 +- test/node.js | 2 +- test/non-defined.js | 2 +- test/parent.js | 2 +- test/position.js | 2 +- test/type.js | 2 +- test/value.js | 2 +- test/void.js | 2 +- 15 files changed, 18 insertions(+), 19 deletions(-) rename lib/{inspect.browser.js => inspect.default.js} (100%) rename lib/{inspect.js => inspect.node.js} (100%) diff --git a/index.test-d.ts b/index.test-d.ts index 4802246..6f606cd 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,6 +1,6 @@ import {expectNotType, expectType} from 'tsd' import type {Node, Parent} from 'unist' -import {assert, parent} from './index.js' +import {assert, parent} from 'unist-util-assert' const emptyNode = {type: 'a'} const literalNode = {type: 'b', value: 'c'} diff --git a/lib/index.js b/lib/index.js index ba2ce1a..fcf3cee 100644 --- a/lib/index.js +++ b/lib/index.js @@ -26,7 +26,7 @@ */ import nodeAssert from 'node:assert' -import {inspect} from './inspect.js' +import {inspect} from 'unist-util-assert/do-not-use-conditional-inspect' const own = {}.hasOwnProperty diff --git a/lib/inspect.browser.js b/lib/inspect.default.js similarity index 100% rename from lib/inspect.browser.js rename to lib/inspect.default.js diff --git a/lib/inspect.js b/lib/inspect.node.js similarity index 100% rename from lib/inspect.js rename to lib/inspect.node.js diff --git a/package.json b/package.json index e269b38..4626574 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,13 @@ ], "sideEffects": false, "type": "module", - "main": "index.js", - "browser": { - "./lib/inspect.js": "./lib/inspect.browser.js" + "exports": { + ".": "./index.js", + "./do-not-use-conditional-inspect": { + "node": "./lib/inspect.node.js", + "default": "./lib/inspect.default.js" + } }, - "react-native": { - "./lib/inspect.js": "./lib/inspect.browser.js" - }, - "types": "index.d.ts", "files": [ "lib/", "index.d.ts", diff --git a/test/children.js b/test/children.js index 29ea1ce..6068376 100644 --- a/test/children.js +++ b/test/children.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('children', async function (t) { await t.test( diff --git a/test/core.js b/test/core.js index 98d8e3a..62126ee 100644 --- a/test/core.js +++ b/test/core.js @@ -3,7 +3,7 @@ import test from 'node:test' test('assert', async function (t) { await t.test('should expose the public api', async function () { - assert.deepEqual(Object.keys(await import('../index.js')).sort(), [ + assert.deepEqual(Object.keys(await import('unist-util-assert')).sort(), [ '_void', 'assert', 'literal', diff --git a/test/literal.js b/test/literal.js index 14f32e4..c9d737d 100644 --- a/test/literal.js +++ b/test/literal.js @@ -1,6 +1,6 @@ import assert from 'node:assert/strict' import test from 'node:test' -import {literal} from '../index.js' +import {literal} from 'unist-util-assert' test('literal()', async function (t) { await t.test('should throw the same errors as `assert()`', async function () { diff --git a/test/node.js b/test/node.js index c1bba41..e9d9e84 100644 --- a/test/node.js +++ b/test/node.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('node', async function (t) { await t.test('should throw if not given a node (#1)', async function () { diff --git a/test/non-defined.js b/test/non-defined.js index d5c11e3..95c99fc 100644 --- a/test/non-defined.js +++ b/test/non-defined.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('non-defined', async function (t) { await t.test( diff --git a/test/parent.js b/test/parent.js index 416b0f9..511d7d0 100644 --- a/test/parent.js +++ b/test/parent.js @@ -1,6 +1,6 @@ import assert from 'node:assert/strict' import test from 'node:test' -import {parent} from '../index.js' +import {parent} from 'unist-util-assert' test('parent()', async function (t) { await t.test('should throw the same errors as `assert()`', async function () { diff --git a/test/position.js b/test/position.js index 73945da..c687359 100644 --- a/test/position.js +++ b/test/position.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('position', async function (t) { await t.test( diff --git a/test/type.js b/test/type.js index 47ae94d..d59e7d1 100644 --- a/test/type.js +++ b/test/type.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('type', async function (t) { await t.test('should throw if not given a `type` (#1)', async function () { diff --git a/test/value.js b/test/value.js index 4ddfde0..9afbc9f 100644 --- a/test/value.js +++ b/test/value.js @@ -1,6 +1,6 @@ import nodeAssert from 'node:assert/strict' import test from 'node:test' -import {assert} from '../index.js' +import {assert} from 'unist-util-assert' test('value', async function (t) { await t.test('should throw if given a non-string `value`', async function () { diff --git a/test/void.js b/test/void.js index 1354d24..d358bea 100644 --- a/test/void.js +++ b/test/void.js @@ -1,6 +1,6 @@ import assert from 'node:assert/strict' import test from 'node:test' -import {_void} from '../index.js' +import {_void} from 'unist-util-assert' test('_void()', async function (t) { await t.test('should throw the same errors as `assert()`', async function () { From e2abc8be675cce80b790fc60c2a77ad56a1184ad Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 29 Jun 2023 14:10:52 +0200 Subject: [PATCH 08/10] Change to require Node.js 16 --- readme.md | 4 ++-- tsconfig.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index ebc8ca3..e650bdb 100644 --- a/readme.md +++ b/readme.md @@ -223,8 +223,8 @@ versions of Node.js. When we cut a new major release, we drop support for unmaintained versions of Node. -This means we try to keep the current release line, `unist-util-assert@^3`, -compatible with Node.js 12. +This means we try to keep the current release line, `unist-util-assert@^4`, +compatible with Node.js 16. ## Related diff --git a/tsconfig.json b/tsconfig.json index 870d82c..82cc749 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,10 +5,10 @@ "declaration": true, "emitDeclarationOnly": true, "exactOptionalPropertyTypes": true, - "lib": ["es2020"], + "lib": ["es2022"], "module": "node16", "strict": true, - "target": "es2020" + "target": "es2022" }, "exclude": ["coverage/", "node_modules/"], "include": ["**/*.js"] From 74155db01bdc41511f1ac13b667fe7277f866186 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Fri, 7 Jul 2023 12:03:34 +0200 Subject: [PATCH 09/10] Update `@types/unist` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4626574..b9ea206 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "index.js" ], "dependencies": { - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0" }, "devDependencies": { "@types/node": "^20.0.0", From 963f4c869206ebf1fdea95d120cdcee6b064f0ca Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Fri, 7 Jul 2023 12:04:09 +0200 Subject: [PATCH 10/10] 4.0.0 --- package.json | 2 +- readme.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b9ea206..6e7b325 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unist-util-assert", - "version": "3.0.2", + "version": "4.0.0", "description": "unist utility to assert nodes", "license": "MIT", "keywords": [ diff --git a/readme.md b/readme.md index e650bdb..50c4b55 100644 --- a/readme.md +++ b/readme.md @@ -55,14 +55,14 @@ npm install unist-util-assert In Deno with [`esm.sh`][esmsh]: ```js -import {assert} from 'https://esm.sh/unist-util-assert@3' +import {assert} from 'https://esm.sh/unist-util-assert@4' ``` In browsers with [`esm.sh`][esmsh]: ```html ```