Skip to content

Commit

Permalink
Add improved types
Browse files Browse the repository at this point in the history
*   Add better support for different compile results, if you have custom
    results, add them to `CompileResultMap`
*   Better input/output of functions
*   Infer plugins better
*   Redo all docs
  • Loading branch information
wooorm committed Aug 12, 2023
1 parent 1aa3494 commit 807ffb9
Show file tree
Hide file tree
Showing 14 changed files with 1,016 additions and 737 deletions.
1,162 changes: 738 additions & 424 deletions index.d.ts

Large diffs are not rendered by default.

262 changes: 101 additions & 161 deletions index.test-d.ts

Large diffs are not rendered by default.

48 changes: 25 additions & 23 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
* @typedef {import('../index.js').Parser} Parser
* @typedef {import('../index.js').Pluggable} Pluggable
* @typedef {import('../index.js').PluggableList} PluggableList
* @typedef {import('../index.js').PluginTuple} PluginTuple
* @typedef {import('../index.js').Plugin} Plugin
* @typedef {import('../index.js').Preset} Preset
* @typedef {import('../index.js').ProcessCallback} ProcessCallback
* @typedef {import('../index.js').Processor} Processor
* @typedef {import('../index.js').RunCallback} RunCallback
* @typedef {import('../index.js').Transformer} Transformer
*/

import structuredClone from '@ungap/structured-clone'
Expand Down Expand Up @@ -52,7 +52,6 @@ function base() {

// Plugins.
processor.attachers = attachers
// @ts-expect-error: overloads are handled.
processor.use = use

// API.
Expand All @@ -75,7 +74,8 @@ function base() {
let index = -1

while (++index < attachers.length) {
destination.use(...attachers[index])
const attacher = attachers[index]
destination.use(...attacher)
}

destination.data(structuredClone(namespace))
Expand Down Expand Up @@ -129,7 +129,6 @@ function base() {
options[0] = undefined
}

/** @type {Transformer | void} */
const transformer = attacher.call(processor, ...options)

if (typeof transformer === 'function') {
Expand All @@ -144,7 +143,7 @@ function base() {
}

/**
* @param {Pluggable | null | undefined} [value]
* @param {Exclude<Pluggable, PluginTuple> | PluggableList | null | undefined} [value]
* @param {...unknown} options
* @returns {Processor}
*/
Expand Down Expand Up @@ -176,15 +175,16 @@ function base() {
return processor

/**
* @param {import('../index.js').Pluggable<Array<unknown>>} value
* @returns {void}
* @param {import('../index.js').Pluggable} value
* @returns {undefined}
*/
function add(value) {
if (typeof value === 'function') {
addPlugin(value)
} else if (typeof value === 'object') {
if (Array.isArray(value)) {
const [plugin, ...options] = value
const [plugin, ...options] =
/** @type {[Plugin, ...Array<unknown>]} */ (value)
addPlugin(plugin, ...options)
} else {
addPreset(value)
Expand All @@ -196,7 +196,7 @@ function base() {

/**
* @param {Preset} result
* @returns {void}
* @returns {undefined}
*/
function addPreset(result) {
if (!('plugins' in result) && !('settings' in result)) {
Expand All @@ -215,7 +215,7 @@ function base() {

/**
* @param {PluggableList | null | undefined} [plugins]
* @returns {void}
* @returns {undefined}
*/
function addList(plugins) {
let index = -1
Expand All @@ -235,7 +235,7 @@ function base() {
/**
* @param {Plugin} plugin
* @param {...unknown} [value]
* @returns {void}
* @returns {undefined}
*/
function addPlugin(plugin, value) {
let index = -1
Expand Down Expand Up @@ -299,7 +299,7 @@ function base() {
* @param {Node} node
* @param {RunCallback | VFileCompatible} [doc]
* @param {RunCallback} [callback]
* @returns {Promise<Node> | void}
* @returns {Promise<Node> | undefined}
*/
function run(node, doc, callback) {
assertNode(node)
Expand All @@ -316,10 +316,11 @@ function base() {

executor(undefined, callback)

// Note: `void`s needed for TS.
/**
* @param {((node: Node) => void) | undefined} resolve
* @param {(error: Error) => void} reject
* @returns {void}
* @param {((node: Node) => undefined | void) | undefined} resolve
* @param {(error: Error) => undefined | void} reject
* @returns {undefined}
*/
function executor(resolve, reject) {
// @ts-expect-error: `doc` can’t be a callback anymore, we checked.
Expand All @@ -329,7 +330,7 @@ function base() {
* @param {Error | undefined} error
* @param {Node} tree
* @param {VFile} file
* @returns {void}
* @returns {undefined}
*/
function done(error, tree, file) {
tree = tree || node
Expand Down Expand Up @@ -362,7 +363,7 @@ function base() {
/**
* @param {Error | undefined} [error]
* @param {Node} [tree]
* @returns {void}
* @returns {undefined}
*/
function done(error, tree) {
bail(error)
Expand All @@ -387,10 +388,11 @@ function base() {

executor(undefined, callback)

// Note: `void`s needed for TS.
/**
* @param {((file: VFile) => void) | undefined} resolve
* @param {(error?: Error | undefined) => void} reject
* @returns {void}
* @param {((file: VFile) => undefined | void) | undefined} resolve
* @param {(error?: Error | undefined) => undefined | void} reject
* @returns {undefined}
*/
function executor(resolve, reject) {
const file = vfile(doc)
Expand All @@ -417,7 +419,7 @@ function base() {
/**
* @param {Error | undefined} [error]
* @param {VFile | undefined} [file]
* @returns {void}
* @returns {undefined}
*/
function done(error, file) {
if (error || !file) {
Expand All @@ -432,7 +434,7 @@ function base() {
}
}

/** @type {Processor['processSync']} */
/** @type {import('../index.js').Processor['processSync']} */
function processSync(doc) {
/** @type {boolean | undefined} */
let complete
Expand All @@ -451,7 +453,7 @@ function base() {

/**
* @param {Error | undefined} [error]
* @returns {void}
* @returns {undefined}
*/
function done(error) {
complete = true
Expand Down
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"xo": "^0.55.0"
},
"scripts": {
"build": "tsc --build --clean && tsc --build && type-coverage",
"build": "tsc --build --clean && tsc --build && type-coverage && tsd",
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
"prepack": "npm run build && npm run format",
"test": "npm run build && npm run format && npm run test-coverage",
Expand Down Expand Up @@ -95,10 +95,6 @@
"atLeast": 100,
"detail": true,
"ignoreCatch": true,
"#": "`type-coverage` currently barfs on inferring nodes in plugins, while TS gets it",
"ignoreFiles": [
"test/**/*.js"
],
"strict": true
},
"xo": {
Expand All @@ -109,6 +105,7 @@
],
"rules": {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/naming-convention": "off"
}
}
Expand Down
41 changes: 26 additions & 15 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ Parse text to a syntax tree.
###### Parameters

* `file` ([`VFile`][vfile]) — any value accepted as `x` in `new VFile(x)`
* `file` ([`VFile`][vfile]) — file to parse; typically `string`; any value
accepted as `x` in `new VFile(x)`

###### Returns

Expand Down Expand Up @@ -497,14 +498,15 @@ Yields:
#### `processor.Parser`

A **parser** handles the parsing of text to a syntax tree.

It is used in the [parse phase][overview] and is called with a `string` and
[`VFile`][vfile] of the document to parse.

`Parser` can be a normal function, in which case it must return the syntax
tree representation of the given file ([`Node`][node]).

`Parser` can also be a constructor function (a function with a `parse` field, or
other fields, in its `prototype`), in which case it is constructed with `new`.
`Parser` can also be a constructor function (a function with a `parse` field in
its `prototype`), in which case it is constructed with `new`.
Instances must have a `parse` method that is called without arguments and must
return a [`Node`][node].

Expand All @@ -521,8 +523,8 @@ Compile a syntax tree.
###### Parameters

* `tree` ([`Node`][node]) — tree to compile
* `file` ([`VFile`][vfile], optional) — any value accepted as `x` in
`new VFile(x)`
* `file` ([`VFile`][vfile], optional) — file associated with `node`; any
value accepted as `x` in `new VFile(x)`

###### Returns

Expand Down Expand Up @@ -562,14 +564,15 @@ Yields:

A **compiler** handles the compiling of a syntax tree to something else (in
most cases, text).

It is used in the [stringify phase][overview] and called with a [`Node`][node]
and [`VFile`][file] representation of the document to compile.

`Compiler` can be a normal function, in which case it should return the textual
representation of the given tree (`string`).

`Compiler` can also be a constructor function (a function with a `compile`
field, or other fields, in its `prototype`), in which case it is constructed
field in its `prototype`), in which case it is constructed
with `new`.
Instances must have a `compile` method that is called without arguments and
should return a `string`.
Expand Down Expand Up @@ -599,7 +602,7 @@ Run *[transformers][transformer]* on a syntax tree.

###### Returns

Nothing if `done` is given (`void`).
Nothing if `done` is given (`undefined`).
A [`Promise`][promise] otherwise.
The promise is rejected with a fatal error or resolved with the transformed
tree ([`Node`][node]).
Expand Down Expand Up @@ -639,6 +642,7 @@ Yields:
#### `function done(err[, tree, file])`

Callback called when transformers are done.

Called with either an error or results.

###### Parameters
Expand Down Expand Up @@ -679,12 +683,13 @@ Process the given file as configured on the processor.
###### Parameters

* `file` ([`VFile`][vfile]) — any value accepted as `x` in `new VFile(x)`
* `file` ([`VFile`][vfile]) — file; any value accepted as `x` in
`new VFile(x)`
* `done` ([`Function`][process-done], optional) — callback

###### Returns

Nothing if `done` is given (`void`).
Nothing if `done` is given (`undefined`).
A [`Promise`][promise] otherwise.
The promise is rejected with a fatal error or resolved with the processed
file ([`VFile`][vfile]).
Expand Down Expand Up @@ -742,6 +747,7 @@ Yields:
#### `function done(err, file)`

Callback called when the process is done.

Called with either an error or a result.

###### Parameters
Expand Down Expand Up @@ -905,6 +911,7 @@ processor.data() // => {charlie: 'delta'}
### `processor.freeze()`

Freeze a processor.

Frozen processors are meant to be extended and not to be configured directly.

When a processor is frozen it cannot be unfrozen.
Expand Down Expand Up @@ -1073,6 +1080,7 @@ Optional transform ([`Transformer`][transformer]).
### `function transformer(tree, file[, next])`

Transformers handle syntax trees and files.

They are functions that are called each time a syntax tree and file are passed
through the [run phase][overview].
When an error occurs in them (either because it’s thrown, returned, rejected,
Expand All @@ -1084,16 +1092,18 @@ exact semantics of these functions.
###### Parameters

* `tree` ([`Node`][node]) — tree to handle
* `file` ([`VFile`][vfile]) —file to handle
* `next` ([`Function`][next], optional)
* `file` ([`VFile`][vfile]) — file to handle
* `next` ([`Function`][next], optional) — callback

###### Returns

* `void` — the next transformer keeps using same tree
If you accept `next`, nothing.
Otherwise:

* `Error` — fatal error to stop the process
* [`Node`][node] — new, changed, tree
* `Promise<Node>` — resolved with a new, changed, tree or rejected with an
`Error`
* `Promise<undefined>` or `undefined` — the next transformer keeps using same
tree
* `Promise<Node>` or [`Node`][node] — new, changed, tree

#### `function next(err[, tree[, file]])`

Expand All @@ -1109,6 +1119,7 @@ may perform asynchronous operations, and must call `next()`.
## `Preset`

Presets are sharable configuration.

They can contain plugins and settings.

###### Example
Expand Down
Loading

0 comments on commit 807ffb9

Please sign in to comment.