import type { Ctx, MilkdownPlugin } from '@milkdown/ctx' import type { RemarkPlugin, RemarkPluginRaw } from '@milkdown/transformer' import { InitReady, remarkPluginsCtx } from '@milkdown/core' import type { $Ctx } from '../$ctx' import { $ctx } from '../$ctx' /// @internal export type $Remark = [ optionsCtx: $Ctx, plugin: MilkdownPlugin, ] & { id: Id plugin: MilkdownPlugin options: $Ctx } /// Create a milkdown wrapper for [remark plugin](https://github.com/remarkjs/remark/blob/main/doc/plugins.md). /// It takes a factory function which returns a [remark plugin](https://github.com/remarkjs/remark/blob/main/doc/plugins.md). /// /// Additional property: /// - `id`: The id of the remark plugin. /// - `plugin`: The remark plugin created. /// - `options`: The ctx contains the options of the remark plugin. export function $remark( id: Id, remark: (ctx: Ctx) => RemarkPluginRaw, initialOptions?: Options ): $Remark { const options = $ctx(initialOptions ?? ({} as Options), id) const plugin: MilkdownPlugin = (ctx) => async () => { await ctx.wait(InitReady) const re = remark(ctx) const remarkPlugin: RemarkPlugin = { plugin: re, options: ctx.get(options.key), } ctx.update(remarkPluginsCtx, (rp) => [...rp, remarkPlugin as RemarkPlugin]) return () => { ctx.update(remarkPluginsCtx, (rp) => rp.filter((x) => x !== remarkPlugin)) } } const result = [options, plugin] as $Remark result.id = id result.plugin = plugin result.options = options return result }