Skip to content

Commit

Permalink
feat: 🎸 add ctx options for remark plugins (#1085)
Browse files Browse the repository at this point in the history
Closes: #1064
  • Loading branch information
Saul-Mirone authored Aug 12, 2023
1 parent d42040f commit 24ad8f8
Show file tree
Hide file tree
Showing 20 changed files with 156 additions and 128 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/internal-plugin/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const schema: MilkdownPlugin = (ctx) => {
const remark = ctx.get(remarkCtx)
const remarkPlugins = ctx.get(remarkPluginsCtx)

const processor = remarkPlugins.reduce((acc: RemarkParser, plug) => acc.use(plug), remark)
const processor = remarkPlugins.reduce((acc: RemarkParser, plug) => acc.use(plug.plugin, plug.options), remark)
ctx.set(remarkCtx, processor)

const nodes = Object.fromEntries(ctx.get(nodesCtx).map(([key, x]) => [key, extendPriority(x)]))
Expand Down
8 changes: 6 additions & 2 deletions packages/plugin-diagram/src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,16 @@ withMeta(insertDiagramInputRules, {
})

/// A remark plugin that will parse mermaid code block.
export const remarkDiagramPlugin = $remark(() => remarkMermaid)
export const remarkDiagramPlugin = $remark('remarkMermaid', () => remarkMermaid)

withMeta(remarkDiagramPlugin, {
withMeta(remarkDiagramPlugin.plugin, {
displayName: 'Remark<diagram>',
})

withMeta(remarkDiagramPlugin.options, {
displayName: 'RemarkConfig<diagram>',
})

/// A command that will insert a diagram node.
export const insertDiagramCommand = $command('InsertDiagramCommand', ctx => () => setBlockType(diagramSchema.type(ctx), { identity: getId() }))

Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-emoji/src/__internal__/remark-twemoji.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright 2021, Milkdown by Mirone. */
import type { Node, RemarkPlugin } from '@milkdown/transformer'
import type { Node, RemarkPluginRaw } from '@milkdown/transformer'
import emojiRegex from 'emoji-regex'

import { parse } from './parse'
Expand Down Expand Up @@ -35,7 +35,7 @@ function flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null)
}
}

export const twemojiPlugin: (twemojiOptions?: TwemojiOptions) => RemarkPlugin = twemojiOptions => () => {
export const twemojiPlugin: RemarkPluginRaw<TwemojiOptions> = (twemojiOptions) => {
function transformer(tree: Node) {
flatMap(tree, (node) => {
if (!isLiteral(node))
Expand Down
59 changes: 26 additions & 33 deletions packages/plugin-emoji/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
/* Copyright 2021, Milkdown by Mirone. */
import type { MilkdownPlugin } from '@milkdown/ctx'
import type { RemarkPlugin } from '@milkdown/transformer'
import type { RemarkPluginRaw } from '@milkdown/transformer'
import { expectDomTypeError } from '@milkdown/exception'
import { InputRule } from '@milkdown/prose/inputrules'
import { $ctx, $inputRule, $nodeAttr, $nodeSchema, $remark } from '@milkdown/utils'
import { $inputRule, $nodeAttr, $nodeSchema, $remark } from '@milkdown/utils'
import { get } from 'node-emoji'
import type { RemarkEmojiOptions } from 'remark-emoji'
import remarkEmoji from 'remark-emoji'
import type Twemoji from 'twemoji'

import { parse } from './__internal__/parse'
import { twemojiPlugin } from './__internal__/remark-twemoji'
import { withMeta } from './__internal__/with-meta'

// eslint-disable-next-line @typescript-eslint/ban-types
type TwemojiOptions = Exclude<Parameters<typeof Twemoji.parse>[1], Function | undefined>

/// @internal
export interface EmojiConfig {
twemojiOptions?: TwemojiOptions
}

/// A slice that contains [options for twemoji](https://github.com/twitter/twemoji#object-as-parameter).
export const emojiConfig = $ctx<EmojiConfig, 'emojiConfig'>({}, 'emojiConfig')
withMeta(emojiConfig, {
displayName: 'Ctx<emojiConfig>',
})

/// HTML attributes for emoji node.
export const emojiAttr = $nodeAttr('emoji', () => ({
span: {},
Expand Down Expand Up @@ -92,6 +78,28 @@ withMeta(emojiSchema.ctx, {
displayName: 'NodeSchemaCtx<emoji>',
})

/// This plugin wraps [remark-emoji](https://github.com/rhysd/remark-emoji).
export const remarkEmojiPlugin = $remark('remarkEmoji', () => remarkEmoji as RemarkPluginRaw<RemarkEmojiOptions>)

withMeta(remarkEmojiPlugin.plugin, {
displayName: 'Remark<remarkEmojiPlugin>',
})

withMeta(remarkEmojiPlugin.options, {
displayName: 'RemarkConfig<remarkEmojiPlugin>',
})

/// This plugin is used for transforming emoji to twemoji.
export const remarkTwemojiPlugin = $remark('remarkTwemoji', () => twemojiPlugin)

withMeta(remarkTwemojiPlugin.plugin, {
displayName: 'Remark<remarkTwemojiPlugin>',
})

withMeta(remarkTwemojiPlugin.options, {
displayName: 'RemarkConfig<remarkTwemojiPlugin>',
})

/// Input rule for inserting emoji.
/// For example, `:smile:` will be replaced with `😄`.
export const insertEmojiInputRule = $inputRule(ctx => new InputRule(/(:([^:\s]+):)$/, (state, match, start, end) => {
Expand All @@ -102,7 +110,7 @@ export const insertEmojiInputRule = $inputRule(ctx => new InputRule(/(:([^:\s]+)
if (!got || content.includes(got))
return null

const html = parse(got, ctx.get(emojiConfig.key).twemojiOptions)
const html = parse(got, ctx.get(remarkTwemojiPlugin.options.key))

return state.tr
.setMeta('emoji', true)
Expand All @@ -114,24 +122,9 @@ withMeta(insertEmojiInputRule, {
displayName: 'InputRule<insertEmojiInputRule>',
})

/// This plugin wraps [remark-emoji](https://github.com/rhysd/remark-emoji).
export const remarkEmojiPlugin = $remark(() => remarkEmoji as RemarkPlugin)

withMeta(remarkEmojiPlugin, {
displayName: 'Remark<remarkEmojiPlugin>',
})

/// This plugin is used for transforming emoji to twemoji.
export const remarkTwemojiPlugin = $remark(ctx => twemojiPlugin(ctx.get(emojiConfig.key).twemojiOptions))

withMeta(remarkTwemojiPlugin, {
displayName: 'Remark<remarkTwemojiPlugin>',
})

/// All plugins exported by this package.
export const emoji: MilkdownPlugin[] = [
emojiAttr,
emojiConfig,
remarkEmojiPlugin,
remarkTwemojiPlugin,
emojiSchema,
Expand Down
8 changes: 6 additions & 2 deletions packages/plugin-math/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ const withMeta = <T extends MilkdownPlugin>(
}

/// This plugin wraps [remark-math](https://www.npmjs.com/package/remark-math).
export const remarkMathPlugin = $remark(() => remarkMath)
export const remarkMathPlugin = $remark<'remarkMath', undefined>('remarkMath', () => remarkMath)

withMeta(remarkMathPlugin, {
withMeta(remarkMathPlugin.plugin, {
displayName: 'Remark<remarkMath>',
})

withMeta(remarkMathPlugin.options, {
displayName: 'RemarkConfig<remarkMath>',
})

const mathInlineId = 'math_inline'

/// A slice that contains [options for katex](https://katex.org/docs/options.html).
Expand Down
2 changes: 1 addition & 1 deletion packages/preset-commonmark/src/composed/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ export const plugins: MilkdownPlugin[] = [

syncHeadingIdPlugin,
syncListOrderPlugin,
]
].flat()
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { visit } from 'unist-util-visit'
import { withMeta } from '../__internal__'

/// This plugin is used to add order in list for remark AST.
export const remarkAddOrderInListPlugin = $remark(() => () => (tree) => {
export const remarkAddOrderInListPlugin = $remark('remarkAddOrderInList', () => () => (tree) => {
visit(tree, 'list', (node) => {
if (node.ordered) {
const start = node.start ?? 1
Expand All @@ -15,7 +15,12 @@ export const remarkAddOrderInListPlugin = $remark(() => () => (tree) => {
})
})

withMeta(remarkAddOrderInListPlugin, {
withMeta(remarkAddOrderInListPlugin.plugin, {
displayName: 'Remark<remarkAddOrderInListPlugin>',
group: 'Remark',
})

withMeta(remarkAddOrderInListPlugin.options, {
displayName: 'RemarkConfig<remarkAddOrderInListPlugin>',
group: 'Remark',
})
13 changes: 9 additions & 4 deletions packages/preset-commonmark/src/plugin/remark-html-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,27 @@ function flatMapWithDepth(ast: Node, fn: (node: Node, index: number, parent: Nod

/// @internal
/// This plugin should be deprecated after we support HTML.
export const remarkHtmlTransformer = $remark(() => () => (tree: Node) => {
export const remarkHtmlTransformer = $remark('remarkHTMLTransformer', () => () => (tree: Node) => {
flatMapWithDepth(tree, (node, _index, parent) => {
if (!isHTML(node))
return [node]

if (parent?.type === 'root') {
node.children = [{ ...node }]
delete node.value
node.type = 'paragraph'
delete node.value;
(node as { type: string }).type = 'paragraph'
}

return [node]
})
})

withMeta(remarkHtmlTransformer, {
withMeta(remarkHtmlTransformer.plugin, {
displayName: 'Remark<remarkHtmlTransformer>',
group: 'Remark',
})

withMeta(remarkHtmlTransformer.options, {
displayName: 'RemarkConfig<remarkHtmlTransformer>',
group: 'Remark',
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import remarkInlineLinks from 'remark-inline-links'
import { withMeta } from '../__internal__'

/// This plugin wraps [remark-inline-links](https://github.com/remarkjs/remark-inline-links).
export const remarkInlineLinkPlugin = $remark(() => remarkInlineLinks)
export const remarkInlineLinkPlugin = $remark('remarkInlineLink', () => remarkInlineLinks)

withMeta(remarkInlineLinkPlugin, {
withMeta(remarkInlineLinkPlugin.plugin, {
displayName: 'Remark<remarkInlineLinkPlugin>',
group: 'Remark',
})

withMeta(remarkInlineLinkPlugin.options, {
displayName: 'RemarkConfig<remarkInlineLinkPlugin>',
group: 'Remark',
})
9 changes: 7 additions & 2 deletions packages/preset-commonmark/src/plugin/remark-line-break.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { withMeta } from '../__internal__'
/// This plugin is used to add inline line break for remark AST.
/// The inline line break should be treated as a `space`.
/// And the normal line break should be treated as a `LF`.
export const remarkLineBreak = $remark(() => () => (tree: Node) => {
export const remarkLineBreak = $remark('remarkLineBreak', () => () => (tree: Node) => {
const find = /[\t ]*(?:\r?\n|\r)/g
visit(tree, 'text', (node: Node & { value: string }, index: number, parent: Node & { children: Node[] }) => {
if (!node.value || typeof node.value !== 'string')
Expand Down Expand Up @@ -44,7 +44,12 @@ export const remarkLineBreak = $remark(() => () => (tree: Node) => {
})
})

withMeta(remarkLineBreak, {
withMeta(remarkLineBreak.plugin, {
displayName: 'Remark<remarkLineBreak>',
group: 'Remark',
})

withMeta(remarkLineBreak.options, {
displayName: 'RemarkConfig<remarkLineBreak>',
group: 'Remark',
})
9 changes: 7 additions & 2 deletions packages/preset-commonmark/src/plugin/remark-marker-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { visit } from 'unist-util-visit'
import { withMeta } from '../__internal__'

/// This plugin is used to keep the marker (`_` and `*`) of emphasis and strong nodes.
export const remarkMarker = $remark(() => () => (tree, file) => {
export const remarkMarker = $remark('remarkMarker', () => () => (tree, file) => {
const getMarker = (node: Node) => {
return (file.value as string).charAt(node.position!.start.offset!)
}
Expand All @@ -14,7 +14,12 @@ export const remarkMarker = $remark(() => () => (tree, file) => {
})
})

withMeta(remarkMarker, {
withMeta(remarkMarker.plugin, {
displayName: 'Remark<remarkMarker>',
group: 'Remark',
})

withMeta(remarkMarker.options, {
displayName: 'RemarkConfig<remarkMarker>',
group: 'Remark',
})
9 changes: 7 additions & 2 deletions packages/preset-gfm/src/composed/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
/* Copyright 2021, Milkdown by Mirone. */
import type { MilkdownPlugin } from '@milkdown/ctx'
import { autoInsertZeroSpaceInTablePlugin, columnResizingPlugin, remarkGFMPlugin, tableEditingPlugin } from '../plugin'
import {
autoInsertZeroSpaceInTablePlugin,
columnResizingPlugin,
remarkGFMPlugin,
tableEditingPlugin,
} from '../plugin'

/// @internal
export const plugins: MilkdownPlugin[] = [
autoInsertZeroSpaceInTablePlugin,
columnResizingPlugin,
tableEditingPlugin,
remarkGFMPlugin,
]
].flat()
1 change: 1 addition & 0 deletions packages/preset-gfm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { commands, inputrules, keymap, plugins, schema } from './composed'

export * from './node'
export * from './mark'
export * from './plugin'
export * from './composed'

/// The GFM preset, includes all the plugins.
Expand Down
9 changes: 7 additions & 2 deletions packages/preset-gfm/src/plugin/remark-gfm-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import remarkGFM from 'remark-gfm'
import { withMeta } from '../__internal__'

/// This plugin is wrapping the [remark-gfm](https://github.com/remarkjs/remark-gfm).
export const remarkGFMPlugin = $remark(() => remarkGFM)
export const remarkGFMPlugin = $remark('remarkGFM', () => remarkGFM)

withMeta(remarkGFMPlugin, {
withMeta(remarkGFMPlugin.plugin, {
displayName: 'Remark<remarkGFMPlugin>',
group: 'Remark',
})

withMeta(remarkGFMPlugin.options, {
displayName: 'RemarkConfig<remarkGFMPlugin>',
group: 'Remark',
})
8 changes: 7 additions & 1 deletion packages/transformer/src/utility/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ export type JSONValue = string | number | boolean | null | JSONValue[] | { [key:
/// @internal
export type JSONRecord = Record<string, JSONValue>

/// @internal
export type RemarkPluginRaw<T> = Plugin<[T], Root>

/// The universal type of a [remark plugin](https://github.com/remarkjs/remark/blob/main/doc/plugins.md).
export type RemarkPlugin = Plugin<never[], Root>
export type RemarkPlugin<T = Record<string, unknown>> = {
plugin: Plugin<[T], Root>
options: T
}

/// The type of [remark instance](https://github.com/remarkjs/remark/tree/main/packages/remark#remark-1).
export type RemarkParser = ReturnType<typeof remark>
Expand Down
53 changes: 0 additions & 53 deletions packages/utils/src/composable/$remark.ts

This file was deleted.

Loading

0 comments on commit 24ad8f8

Please sign in to comment.