Skip to content

Commit

Permalink
chore: add async plugin example
Browse files Browse the repository at this point in the history
  • Loading branch information
cossssmin committed Mar 21, 2024
1 parent 15a2c7c commit 712d394
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 4 deletions.
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,60 @@ git clone https://github.com/posthtml/posthtml-plugin-starter.git

### Features

- [Async](#async-plugins) and [sync](#sync-plugins) examples
- ESM, Node.js 18+
- Tests with [`vitest`](https://vitest.dev)
- Linting with [`eslint`](https://eslint.org)
- Releases with [`np`](https://github.com/sindresorhus/np)
- ESM, Node.js 18+
- CI with GitHub Actions

#### Async plugins

When writing an async PostHTML plugin, you must return a `Promise` that resolves the current `tree`:

```js
export default (options = {}) => tree => {
// Accept options and set defaults
options.foo = options.foo || {}

return new Promise((resolve, reject) => {
try {
// do something async

// finally, resolve the promise by returning the tree
resolve(tree)
} catch (error) {
reject(error)
}
})
}
```

Note: async plugins can't be used in PostHTML's [`sync` mode](https://posthtml.org/#/core?id=posthtml-options).

#### Sync plugins

Synchronous plugins just need to return the `tree`.

You may use the `tree.walk` method to traverse the `tree` and handle nodes.

The handling of nodes can be a function that is passed to `tree.walk`, and which must return the node:

```js
export default (options = {}) => tree => {
options.foo = options.foo || {}

const handleNodes = node => {
// Write your code...

// Return the node
return node
}

return tree.walk(handleNodes)
}
```

#### Tests

The testing boilerplate includes a `process()` method which accepts 4 parameters:
Expand Down
11 changes: 11 additions & 0 deletions lib/asyncPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default (options = {}) => tree => {
// Accept options and set defaults
options.foo = options.foo || {}

return new Promise((resolve) => {
// do something async

// finally, resolve the promise by returning the tree
resolve(tree)
})
}
5 changes: 2 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const plugin = (options = {}) => tree => {
export default (options = {}) => tree => {
// Accept options and set defaults
options.foo = options.foo || {}

const process = node => {
Expand All @@ -10,5 +11,3 @@ const plugin = (options = {}) => tree => {

return tree.walk(process)
}

export default plugin
7 changes: 7 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {fileURLToPath} from 'node:url'
import {test, expect} from 'vitest'
import posthtml from 'posthtml'
import plugin from '../lib/index.js'
import asyncPlugin from '../lib/asyncPlugin.js'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

Expand All @@ -24,3 +25,9 @@ const process = (name, options, log = false) => {
test('Basic', () => {
return process('basic')
})

test('Async plugin', () => {
return posthtml([asyncPlugin()])
.process(fixture('basic'))
.then(result => expect(clean(result.html)).toEqual(expected('basic')))
})

0 comments on commit 712d394

Please sign in to comment.