unifiedパーザープラグインの事例

ドライバー内蔵ではないプラグインパーザーの例: https://github.com/retextjs/retext/blob/main/packages/retext-english/lib/index.js

まず、使っているパッケージは https://www.npmjs.com/package/unherithttps://www.npmjs.com/package/parse-english の2つ。

import {unherit} from 'unherit'
// @ts-expect-error: untyped.
import {ParseEnglish} from 'parse-english'

unheritの使い方:

// unherit create a custom constructor 
// which can be modified without affecting the original class.

import {EventEmitter} from 'events'
import {unherit} from 'unherit'

// Create a private class which acts just like `EventEmitter`.
var Emitter = unherit(EventEmitter)

Emitter.prototype.defaultMaxListeners = 0
// Now, all instances of `Emitter` have no maximum listeners, without affecting
// other `EventEmitter`s.

parse-englishの使い方:

import {ParseEnglish} from 'parse-english'

var tree = new ParseEnglish().parse(
  'Mr. Henry Brown: A hapless but friendly City of London worker.'
)

パーザープラグインの本体:

/** @type {import('unified').ParserClass<Root>} */

/** @type {import('unified').Plugin<void[], string, Root>} */
export default function retextEnglish() {
  Object.assign(this, {Parser: unherit(ParseEnglish)})
}

// @ts-expect-error: untyped.
export {ParseEnglish as Parser} from 'parse-english'

型定義は unified.d.ts https://github.com/unifiedjs/unified/blob/main/index.d.ts にある。型 Root は、nlcst で定義されたRootノード。

export class ParserClass<Tree extends Node = Node> {
  prototype: {
    /**
     * Parse a file.
     *
     * @returns
     *   Parsed tree.
     */
    parse(): Tree
  }
export type Plugin<
  PluginParameters extends any[] = any[],
  Input = Node,
  Output = Input
> = (
  this: Input extends Node
    ? Output extends Node
      ? // This is a transform, so define `Input` as the current tree.
        Processor<void, Input>
      : // Compiler.
        Processor<void, Input, Input, Output>
    : Output extends Node
    ? // Parser.
      Processor<Output, Output>
    : // No clue.
      Processor,
  ...settings: PluginParameters
) => // If both `Input` and `Output` are `Node`, expect an optional `Transformer`.
Input extends Node
  ? Output extends Node
    ? Transformer<Input, Output> | void
    : void
  : void

Object.assign は、

Object.assign(target, ...sources)
  • target コピー先オブジェクト — コピー元のプロパティを適用するもので、変更後に返されます。
  • sources コピー元オブジェクト (単数または複数) — 適用したいプロパティを含むオブジェクトです。

コピーはシャローコピー。