diff --git a/lib/configuration.js b/lib/configuration.js index 77f3969..8540ba5 100644 --- a/lib/configuration.js +++ b/lib/configuration.js @@ -99,6 +99,9 @@ const loaders = { '.cjs': loadScriptOrModule, '.mjs': loadScriptOrModule, '.js': loadScriptOrModule, + '.cts': loadScriptOrModule, + '.mts': loadScriptOrModule, + '.ts': loadScriptOrModule, '.yaml': loadYaml, '.yml': loadYaml } diff --git a/readme.md b/readme.md index e86a92f..ca01754 100644 --- a/readme.md +++ b/readme.md @@ -1223,7 +1223,11 @@ engine( This example processes `readme.md` and allows configuration from `.remarkrc`, `.remarkrc.json`, `.remarkrc.yml`, `.remarkrc.yaml`, `.remarkrc.js`, -`.remarkrc.cjs`, and `.remarkrc.mjs` files. +`.remarkrc.cjs`, `.remarkrc.mjs`, `.remarkrc.ts`, `.remarkrc.cts`, and +`.remarkrc.mts` files. + +Note: TypeScript support relies on Node.js itself, so it requires Node.js 22.7+ +with `--experimental-transform-types` flag enabled or 23.6+ by default. ```js import {remark} from 'remark' diff --git a/test/configuration-plugins.js b/test/configuration-plugins.js index 41ef27b..13e7a85 100644 --- a/test/configuration-plugins.js +++ b/test/configuration-plugins.js @@ -1,5 +1,6 @@ import assert from 'node:assert/strict' import path from 'node:path' +import process from 'node:process' import test from 'node:test' import {engine} from 'unified-engine' import {cleanError} from './util/clean-error.js' @@ -71,6 +72,50 @@ test('configuration (plugins)', async function (t) { } ) + if (process.features.typescript) { + await t.test( + 'should support an ESM plugin w/ an `.mts` extname', + async function () { + const stderr = spy() + + globalThis.unifiedEngineTestCalls = 0 + + const result = await engine({ + cwd: new URL('config-plugins-esm-mts/', fixtures), + files: ['one.txt'], + processor: noop(), + rcName: '.foorc', + streamError: stderr.stream + }) + + assert.equal(result.code, 0) + assert.equal(stderr(), 'one.txt: no issues found\n') + assert.equal(globalThis.unifiedEngineTestCalls, 1) + } + ) + + await t.test( + 'should support an ESM plugin w/ a `.ts` extname', + async function () { + const stderr = spy() + + globalThis.unifiedEngineTestCalls = 0 + + const result = await engine({ + cwd: new URL('config-plugins-esm-ts/', fixtures), + files: ['one.txt'], + processor: noop(), + rcName: '.foorc', + streamError: stderr.stream + }) + + assert.equal(result.code, 0) + assert.equal(stderr(), 'one.txt: no issues found\n') + assert.equal(globalThis.unifiedEngineTestCalls, 1) + } + ) + } + await t.test('should handle failing plugins', async function () { const stderr = spy() diff --git a/test/configuration.js b/test/configuration.js index a1157e7..cb815ac 100644 --- a/test/configuration.js +++ b/test/configuration.js @@ -1,5 +1,6 @@ import assert from 'node:assert/strict' import path from 'node:path' +import process from 'node:process' import test from 'node:test' import {engine} from 'unified-engine' import {cleanError} from './util/clean-error.js' @@ -202,6 +203,86 @@ test('configuration', async function (t) { ) }) + if (process.features.typescript) { + await t.test( + 'should prefer `.rc.js` scripts over `.rc.ts`', + async function () { + const stderr = spy() + let calls = 0 + + const result = await engine({ + cwd: new URL('mixed-rc-script/', fixtures), + extensions: ['txt'], + files: ['.'], + plugins: [ + function () { + assert.deepEqual(this.data('settings'), {}) + calls++ + } + ], + processor: noop, + rcName: '.foorc', + streamError: stderr.stream + }) + + assert.deepEqual( + [result.code, calls, stderr()], + [0, 1, 'one.txt: no issues found\n'] + ) + } + ) + + await t.test('should support `.rc.mts` module', async function () { + const stderr = spy() + let calls = 0 + + const result = await engine({ + cwd: new URL('rc-module-mts/', fixtures), + extensions: ['txt'], + files: ['.'], + plugins: [ + function () { + assert.deepEqual(this.data('settings'), {foo: 'bar'}) + calls++ + } + ], + processor: noop, + rcName: '.foorc', + streamError: stderr.stream + }) + + assert.deepEqual( + [result.code, calls, stderr()], + [0, 1, 'one.txt: no issues found\n'] + ) + }) + + await t.test('should support `.rc.cts` module', async function () { + const stderr = spy() + let calls = 0 + + const result = await engine({ + cwd: new URL('rc-module-cts/', fixtures), + extensions: ['txt'], + files: ['.'], + plugins: [ + function () { + assert.deepEqual(this.data('settings'), {foo: 'bar'}) + calls++ + } + ], + processor: noop, + rcName: '.foorc', + streamError: stderr.stream + }) + + assert.deepEqual( + [result.code, calls, stderr()], + [0, 1, 'one.txt: no issues found\n'] + ) + }) + } + await t.test('should support `.rc.yaml` config files', async function () { const stderr = spy() diff --git a/test/fixtures/config-plugins-esm-mts/.foorc b/test/fixtures/config-plugins-esm-mts/.foorc new file mode 100644 index 0000000..4f69d3d --- /dev/null +++ b/test/fixtures/config-plugins-esm-mts/.foorc @@ -0,0 +1,3 @@ +{ + "plugins": ["./test.mts"] +} diff --git a/test/fixtures/config-plugins-esm-mts/one.txt b/test/fixtures/config-plugins-esm-mts/one.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/config-plugins-esm-mts/test.mts b/test/fixtures/config-plugins-esm-mts/test.mts new file mode 100644 index 0000000..2df4845 --- /dev/null +++ b/test/fixtures/config-plugins-esm-mts/test.mts @@ -0,0 +1,6 @@ +import assert from 'node:assert/strict' + +export default function test() { + assert(typeof globalThis.unifiedEngineTestCalls === 'number') + globalThis.unifiedEngineTestCalls++ +} diff --git a/test/fixtures/config-plugins-esm-ts/.foorc b/test/fixtures/config-plugins-esm-ts/.foorc new file mode 100644 index 0000000..304ab64 --- /dev/null +++ b/test/fixtures/config-plugins-esm-ts/.foorc @@ -0,0 +1,3 @@ +{ + "plugins": ["./test.ts"] +} diff --git a/test/fixtures/config-plugins-esm-ts/one.txt b/test/fixtures/config-plugins-esm-ts/one.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/config-plugins-esm-ts/package.json b/test/fixtures/config-plugins-esm-ts/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/test/fixtures/config-plugins-esm-ts/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/fixtures/config-plugins-esm-ts/test.ts b/test/fixtures/config-plugins-esm-ts/test.ts new file mode 100644 index 0000000..2df4845 --- /dev/null +++ b/test/fixtures/config-plugins-esm-ts/test.ts @@ -0,0 +1,6 @@ +import assert from 'node:assert/strict' + +export default function test() { + assert(typeof globalThis.unifiedEngineTestCalls === 'number') + globalThis.unifiedEngineTestCalls++ +} diff --git a/test/fixtures/mixed-rc-script/.foorc.js b/test/fixtures/mixed-rc-script/.foorc.js new file mode 100644 index 0000000..212bb12 --- /dev/null +++ b/test/fixtures/mixed-rc-script/.foorc.js @@ -0,0 +1,8 @@ +/** + * @import {Preset} from 'unified-engine' + */ + +/** @type {Preset} */ +const config = {settings: {}} + +export default config diff --git a/test/fixtures/mixed-rc-script/.foorc.ts b/test/fixtures/mixed-rc-script/.foorc.ts new file mode 100644 index 0000000..83f83fb --- /dev/null +++ b/test/fixtures/mixed-rc-script/.foorc.ts @@ -0,0 +1,9 @@ +import type {Preset} from 'unified-engine' + +const config: Preset = { + settings: { + foo: 'bar' + } +} + +export default config diff --git a/test/fixtures/mixed-rc-script/one.txt b/test/fixtures/mixed-rc-script/one.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/rc-module-cts/.foorc.cts b/test/fixtures/rc-module-cts/.foorc.cts new file mode 100644 index 0000000..960a6b9 --- /dev/null +++ b/test/fixtures/rc-module-cts/.foorc.cts @@ -0,0 +1,5 @@ +import type {Settings} from 'unified' + +exports.settings = { + foo: 'bar' +} satisfies Settings diff --git a/test/fixtures/rc-module-cts/one.txt b/test/fixtures/rc-module-cts/one.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/rc-module-mts/.foorc.mts b/test/fixtures/rc-module-mts/.foorc.mts new file mode 100644 index 0000000..8d9019a --- /dev/null +++ b/test/fixtures/rc-module-mts/.foorc.mts @@ -0,0 +1,15 @@ +import type {Preset} from 'unified-engine' + +declare module 'unified' { + interface Settings { + foo: string + } +} + +const config: Preset = { + settings: { + foo: 'bar' + } +} + +export default config diff --git a/test/fixtures/rc-module-mts/one.txt b/test/fixtures/rc-module-mts/one.txt new file mode 100644 index 0000000..e69de29