@portabletext/plugin-markdown-shortcuts 1.1.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/behavior.markdown-shortcuts.ts","../src/plugin.markdown-shortcuts.tsx"],"sourcesContent":["import type {EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\n\nexport type MarkdownBehaviorsConfig = {\n horizontalRuleObject?: (context: {\n schema: EditorSchema\n }) => {name: string; value?: {[prop: string]: unknown}} | undefined\n defaultStyle?: (context: {schema: EditorSchema}) => string | undefined\n headingStyle?: (context: {\n schema: EditorSchema\n level: number\n }) => string | undefined\n blockquoteStyle?: (context: {schema: EditorSchema}) => string | undefined\n unorderedList?: (context: {schema: EditorSchema}) => string | undefined\n orderedList?: (context: {schema: EditorSchema}) => string | undefined\n}\n\nexport function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {\n const automaticBlockquoteOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const focusSpan = selectors.getFocusSpan(snapshot)\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const blockOffset = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: snapshot.context.selection?.focus.offset ?? 0,\n },\n })\n\n if (previousInlineObject || !blockOffset) {\n return false\n }\n\n const blockText = utils.getTextBlockText(focusTextBlock.node)\n const caretAtTheEndOfQuote = blockOffset.offset === 1\n const looksLikeMarkdownQuote = /^>/.test(blockText)\n const blockquoteStyle = config.blockquoteStyle?.({\n schema: snapshot.context.schema,\n })\n\n if (\n caretAtTheEndOfQuote &&\n looksLikeMarkdownQuote &&\n blockquoteStyle !== undefined\n ) {\n return {focusTextBlock, style: blockquoteStyle}\n }\n\n return false\n },\n actions: [\n () => [\n execute({\n type: 'insert.text',\n text: ' ',\n }),\n ],\n (_, {focusTextBlock, style}) => [\n execute({\n type: 'block.unset',\n props: ['listItem', 'level'],\n at: focusTextBlock.path,\n }),\n execute({\n type: 'block.set',\n props: {style},\n at: focusTextBlock.path,\n }),\n execute({\n type: 'delete.text',\n at: {\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: 2,\n },\n },\n }),\n ],\n ],\n })\n const automaticHr = defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n const hrCharacter =\n event.text === '-'\n ? '-'\n : event.text === '*'\n ? '*'\n : event.text === '_'\n ? '_'\n : undefined\n\n if (hrCharacter === undefined) {\n return false\n }\n\n const hrObject = config.horizontalRuleObject?.({\n schema: snapshot.context.schema,\n })\n const focusBlock = selectors.getFocusTextBlock(snapshot)\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n\n if (!hrObject || !focusBlock || !selectionCollapsed) {\n return false\n }\n\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const textBefore = selectors.getBlockTextBefore(snapshot)\n const hrBlockOffsets = {\n anchor: {\n path: focusBlock.path,\n offset: 0,\n },\n focus: {\n path: focusBlock.path,\n offset: 3,\n },\n }\n\n if (\n !previousInlineObject &&\n textBefore === `${hrCharacter}${hrCharacter}`\n ) {\n return {hrObject, focusBlock, hrCharacter, hrBlockOffsets}\n }\n\n return false\n },\n actions: [\n (_, {hrCharacter}) => [\n execute({\n type: 'insert.text',\n text: hrCharacter,\n }),\n ],\n (_, {hrObject, hrBlockOffsets}) => [\n execute({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'before',\n select: 'none',\n }),\n execute({\n type: 'delete.text',\n at: hrBlockOffsets,\n }),\n ],\n ],\n })\n const automaticHrOnPaste = defineBehavior({\n on: 'clipboard.paste',\n guard: ({snapshot, event}) => {\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const hrRegExp = /^(---)$|(___)$|(\\*\\*\\*)$/\n const hrCharacters = text.match(hrRegExp)?.[0]\n const hrObject = config.horizontalRuleObject?.({\n schema: snapshot.context.schema,\n })\n const focusBlock = selectors.getFocusBlock(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n\n if (!hrCharacters || !hrObject || !focusBlock) {\n return false\n }\n\n return {hrCharacters, hrObject, focusBlock, focusTextBlock}\n },\n actions: [\n (_, {hrCharacters}) => [\n execute({\n type: 'insert.text',\n text: hrCharacters,\n }),\n ],\n ({snapshot}, {hrObject, focusBlock, focusTextBlock}) =>\n focusTextBlock\n ? [\n execute({\n type: 'insert.block',\n block: {\n _type: snapshot.context.schema.block.name,\n children: focusTextBlock.node.children,\n },\n placement: 'after',\n }),\n execute({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'after',\n }),\n execute({\n type: 'delete.block',\n at: focusBlock.path,\n }),\n ]\n : [\n execute({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'after',\n }),\n ],\n ],\n })\n const automaticHeadingOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const focusSpan = selectors.getFocusSpan(snapshot)\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const blockOffset = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: snapshot.context.selection?.focus.offset ?? 0,\n },\n })\n\n if (!blockOffset) {\n return false\n }\n\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const blockText = utils.getTextBlockText(focusTextBlock.node)\n const markdownHeadingSearch = /^#+/.exec(blockText)\n const level = markdownHeadingSearch\n ? markdownHeadingSearch[0].length\n : undefined\n const caretAtTheEndOfHeading = blockOffset.offset === level\n\n if (previousInlineObject || !caretAtTheEndOfHeading) {\n return false\n }\n\n const style =\n level !== undefined\n ? config.headingStyle?.({schema: snapshot.context.schema, level})\n : undefined\n\n if (level !== undefined && style !== undefined) {\n return {\n focusTextBlock,\n style: style,\n level,\n }\n }\n\n return false\n },\n actions: [\n ({event}) => [execute(event)],\n (_, {focusTextBlock, style, level}) => [\n execute({\n type: 'block.unset',\n props: ['listItem', 'level'],\n at: focusTextBlock.path,\n }),\n execute({\n type: 'block.set',\n props: {style},\n at: focusTextBlock.path,\n }),\n execute({\n type: 'delete.text',\n at: {\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: level + 1,\n },\n },\n }),\n ],\n ],\n })\n const clearStyleOnBackspace = defineBehavior({\n on: 'delete.backward',\n guard: ({snapshot}) => {\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const focusSpan = selectors.getFocusSpan(snapshot)\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const atTheBeginningOfBLock =\n focusTextBlock.node.children[0]._key === focusSpan.node._key &&\n snapshot.context.selection?.focus.offset === 0\n\n const defaultStyle = config.defaultStyle?.({\n schema: snapshot.context.schema,\n })\n\n if (\n atTheBeginningOfBLock &&\n defaultStyle &&\n focusTextBlock.node.style !== defaultStyle\n ) {\n return {defaultStyle, focusTextBlock}\n }\n\n return false\n },\n actions: [\n (_, {defaultStyle, focusTextBlock}) => [\n execute({\n type: 'block.set',\n props: {style: defaultStyle},\n at: focusTextBlock.path,\n }),\n ],\n ],\n })\n const automaticListOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const focusSpan = selectors.getFocusSpan(snapshot)\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const blockOffset = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: snapshot.context.selection?.focus.offset ?? 0,\n },\n })\n\n if (previousInlineObject || !blockOffset) {\n return false\n }\n\n const blockText = utils.getTextBlockText(focusTextBlock.node)\n const defaultStyle = config.defaultStyle?.({\n schema: snapshot.context.schema,\n })\n const looksLikeUnorderedList = /^(-|\\*)/.test(blockText)\n const unorderedList = config.unorderedList?.({\n schema: snapshot.context.schema,\n })\n const caretAtTheEndOfUnorderedList = blockOffset.offset === 1\n\n if (\n defaultStyle &&\n caretAtTheEndOfUnorderedList &&\n looksLikeUnorderedList &&\n unorderedList !== undefined\n ) {\n return {\n focusTextBlock,\n listItem: unorderedList,\n listItemLength: 1,\n style: defaultStyle,\n }\n }\n\n const looksLikeOrderedList = /^1\\./.test(blockText)\n const orderedList = config.orderedList?.({\n schema: snapshot.context.schema,\n })\n const caretAtTheEndOfOrderedList = blockOffset.offset === 2\n\n if (\n defaultStyle &&\n caretAtTheEndOfOrderedList &&\n looksLikeOrderedList &&\n orderedList !== undefined\n ) {\n return {\n focusTextBlock,\n listItem: orderedList,\n listItemLength: 2,\n style: defaultStyle,\n }\n }\n\n return false\n },\n actions: [\n ({event}) => [execute(event)],\n (_, {focusTextBlock, style, listItem, listItemLength}) => [\n execute({\n type: 'block.set',\n props: {\n listItem,\n level: 1,\n style,\n },\n at: focusTextBlock.path,\n }),\n execute({\n type: 'delete.text',\n at: {\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: listItemLength + 1,\n },\n },\n }),\n ],\n ],\n })\n\n const markdownBehaviors = [\n automaticBlockquoteOnSpace,\n automaticHeadingOnSpace,\n automaticHr,\n automaticHrOnPaste,\n clearStyleOnBackspace,\n automaticListOnSpace,\n ]\n\n return markdownBehaviors\n}\n","import {useEditor} from '@portabletext/editor'\nimport type {EditorSchema} from '@portabletext/editor'\nimport {CharacterPairDecoratorPlugin} from '@portabletext/plugin-character-pair-decorator'\nimport {useEffect} from 'react'\nimport {\n createMarkdownBehaviors,\n type MarkdownBehaviorsConfig,\n} from './behavior.markdown-shortcuts'\n\n/**\n * @beta\n */\nexport type MarkdownShortcutsPluginProps = MarkdownBehaviorsConfig & {\n boldDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n codeDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n italicDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n strikeThroughDecorator?: ({\n schema,\n }: {\n schema: EditorSchema\n }) => string | undefined\n}\n\n/**\n * @beta\n */\nexport function MarkdownShortcutsPlugin({\n blockquoteStyle,\n boldDecorator,\n codeDecorator,\n defaultStyle,\n headingStyle,\n horizontalRuleObject,\n italicDecorator,\n orderedList,\n strikeThroughDecorator,\n unorderedList,\n}: MarkdownShortcutsPluginProps) {\n const editor = useEditor()\n\n useEffect(() => {\n const behaviors = createMarkdownBehaviors({\n blockquoteStyle,\n defaultStyle,\n headingStyle,\n horizontalRuleObject,\n orderedList,\n unorderedList,\n })\n\n const unregisterBehaviors = behaviors.map((behavior) =>\n editor.registerBehavior({behavior}),\n )\n\n return () => {\n for (const unregisterBehavior of unregisterBehaviors) {\n unregisterBehavior()\n }\n }\n }, [\n blockquoteStyle,\n defaultStyle,\n editor,\n headingStyle,\n horizontalRuleObject,\n orderedList,\n unorderedList,\n ])\n\n return (\n <>\n {boldDecorator ? (\n <>\n <CharacterPairDecoratorPlugin\n decorator={boldDecorator}\n pair={{char: '*', amount: 2}}\n />\n <CharacterPairDecoratorPlugin\n decorator={boldDecorator}\n pair={{char: '_', amount: 2}}\n />\n </>\n ) : null}\n {codeDecorator ? (\n <CharacterPairDecoratorPlugin\n decorator={codeDecorator}\n pair={{char: '`', amount: 1}}\n />\n ) : null}\n {italicDecorator ? (\n <>\n <CharacterPairDecoratorPlugin\n decorator={italicDecorator}\n pair={{char: '*', amount: 1}}\n />\n <CharacterPairDecoratorPlugin\n decorator={italicDecorator}\n pair={{char: '_', amount: 1}}\n />\n </>\n ) : null}\n {strikeThroughDecorator ? (\n <CharacterPairDecoratorPlugin\n decorator={strikeThroughDecorator}\n pair={{char: '~', amount: 2}}\n />\n ) : null}\n </>\n )\n}\n"],"names":["createMarkdownBehaviors","config","automaticBlockquoteOnSpace","defineBehavior","on","guard","snapshot","event","text","selectionCollapsed","selectors","isSelectionCollapsed","focusTextBlock","getFocusTextBlock","focusSpan","getFocusSpan","previousInlineObject","getPreviousInlineObject","blockOffset","utils","spanSelectionPointToBlockOffset","context","selectionPoint","path","_key","node","offset","selection","focus","blockText","getTextBlockText","caretAtTheEndOfQuote","looksLikeMarkdownQuote","test","blockquoteStyle","schema","undefined","style","actions","execute","type","_","props","at","anchor","automaticHr","hrCharacter","hrObject","horizontalRuleObject","focusBlock","textBefore","getBlockTextBefore","hrBlockOffsets","block","_type","name","value","placement","select","automaticHrOnPaste","originEvent","dataTransfer","getData","hrRegExp","hrCharacters","match","getFocusBlock","children","automaticHeadingOnSpace","markdownHeadingSearch","exec","level","length","caretAtTheEndOfHeading","headingStyle","clearStyleOnBackspace","atTheBeginningOfBLock","defaultStyle","automaticListOnSpace","looksLikeUnorderedList","unorderedList","caretAtTheEndOfUnorderedList","listItem","listItemLength","looksLikeOrderedList","orderedList","caretAtTheEndOfOrderedList","MarkdownShortcutsPlugin","t0","$","_c","boldDecorator","codeDecorator","italicDecorator","strikeThroughDecorator","editor","useEditor","t1","t2","unregisterBehaviors","map","behavior","registerBehavior","unregisterBehavior","useEffect","t3","char","amount","t4","t5","t6","t7"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/behavior.markdown-shortcuts.ts","../src/rule.blockquote.ts","../src/rule.heading.ts","../src/rule.horizontal-rule.ts","../src/rule.ordered-list.ts","../src/rule.unordered-list.ts","../src/plugin.markdown-shortcuts.tsx"],"sourcesContent":["import type {EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\n\nexport type MarkdownBehaviorsConfig = {\n horizontalRuleObject?: (context: {\n schema: EditorSchema\n }) => {name: string; value?: {[prop: string]: unknown}} | undefined\n defaultStyle?: (context: {schema: EditorSchema}) => string | undefined\n}\n\nexport function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {\n const automaticHrOnPaste = defineBehavior({\n on: 'clipboard.paste',\n guard: ({snapshot, event}) => {\n const text = event.originEvent.dataTransfer.getData('text/plain')\n const hrRegExp = /^(---)$|^(—-)$|^(___)$|^(\\*\\*\\*)$/\n const hrCharacters = text.match(hrRegExp)?.[0]\n const hrObject = config.horizontalRuleObject?.({\n schema: snapshot.context.schema,\n })\n const focusBlock = selectors.getFocusBlock(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n\n if (!hrCharacters || !hrObject || !focusBlock) {\n return false\n }\n\n return {hrCharacters, hrObject, focusBlock, focusTextBlock}\n },\n actions: [\n (_, {hrCharacters}) => [\n execute({\n type: 'insert.text',\n text: hrCharacters,\n }),\n ],\n ({snapshot}, {hrObject, focusBlock, focusTextBlock}) =>\n focusTextBlock\n ? [\n execute({\n type: 'insert.block',\n block: {\n _type: snapshot.context.schema.block.name,\n children: focusTextBlock.node.children,\n },\n placement: 'after',\n }),\n execute({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'after',\n }),\n execute({\n type: 'delete.block',\n at: focusBlock.path,\n }),\n ]\n : [\n execute({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'after',\n }),\n ],\n ],\n })\n\n const clearStyleOnBackspace = defineBehavior({\n on: 'delete.backward',\n guard: ({snapshot}) => {\n const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const focusSpan = selectors.getFocusSpan(snapshot)\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const atTheBeginningOfBLock =\n focusTextBlock.node.children[0]._key === focusSpan.node._key &&\n snapshot.context.selection?.focus.offset === 0\n\n const defaultStyle = config.defaultStyle?.({\n schema: snapshot.context.schema,\n })\n\n if (\n atTheBeginningOfBLock &&\n defaultStyle &&\n focusTextBlock.node.style !== defaultStyle\n ) {\n return {defaultStyle, focusTextBlock}\n }\n\n return false\n },\n actions: [\n (_, {defaultStyle, focusTextBlock}) => [\n execute({\n type: 'block.set',\n props: {style: defaultStyle},\n at: focusTextBlock.path,\n }),\n ],\n ],\n })\n\n const markdownBehaviors = [automaticHrOnPaste, clearStyleOnBackspace]\n\n return markdownBehaviors\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {raise} from '@portabletext/editor/behaviors'\nimport {getPreviousInlineObject} from '@portabletext/editor/selectors'\nimport {defineInputRule} from '@portabletext/plugin-input-rule'\n\nexport function createBlockquoteRule(config: {\n blockquoteStyle: (context: {schema: EditorSchema}) => string | undefined\n}) {\n return defineInputRule({\n on: /^> /,\n guard: ({snapshot, event}) => {\n const style = config.blockquoteStyle({\n schema: snapshot.context.schema,\n })\n\n if (!style) {\n return false\n }\n\n const previousInlineObject = getPreviousInlineObject(snapshot)\n\n if (previousInlineObject) {\n return false\n }\n\n const match = event.matches.at(0)\n\n if (!match) {\n return false\n }\n\n return {style, match}\n },\n actions: [\n ({event}, {style, match}) => [\n raise({\n type: 'block.unset',\n props: ['listItem', 'level'],\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'block.set',\n props: {style},\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'delete',\n at: match.targetOffsets,\n }),\n ],\n ],\n })\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {raise} from '@portabletext/editor/behaviors'\nimport {getPreviousInlineObject} from '@portabletext/editor/selectors'\nimport {defineInputRule} from '@portabletext/plugin-input-rule'\n\nexport function createHeadingRule(config: {\n headingStyle: (context: {\n schema: EditorSchema\n level: number\n }) => string | undefined\n}) {\n return defineInputRule({\n on: /^#+ /,\n guard: ({snapshot, event}) => {\n const previousInlineObject = getPreviousInlineObject(snapshot)\n\n if (previousInlineObject) {\n return false\n }\n\n const match = event.matches.at(0)\n\n if (!match) {\n return false\n }\n\n const level = match.text.length - 1\n\n const style = config.headingStyle({\n schema: snapshot.context.schema,\n level,\n })\n\n if (!style) {\n return false\n }\n\n return {match, style}\n },\n actions: [\n ({event}, {match, style}) => [\n raise({\n type: 'block.unset',\n props: ['listItem', 'level'],\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'block.set',\n props: {style},\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'delete',\n at: match.targetOffsets,\n }),\n ],\n ],\n })\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {raise} from '@portabletext/editor/behaviors'\nimport {getPreviousInlineObject} from '@portabletext/editor/selectors'\nimport {defineInputRule} from '@portabletext/plugin-input-rule'\n\nexport function createHorizontalRuleRule(config: {\n horizontalRuleObject: (context: {\n schema: EditorSchema\n }) => {name: string; value?: {[prop: string]: unknown}} | undefined\n}) {\n return defineInputRule({\n on: /^(---)|^(—-)|^(___)|^(\\*\\*\\*)/,\n guard: ({snapshot, event}) => {\n const hrObject = config.horizontalRuleObject({\n schema: snapshot.context.schema,\n })\n\n if (!hrObject) {\n // If no horizontal rule object is provided, then we can safely skip\n // this rule.\n return false\n }\n\n const previousInlineObject = getPreviousInlineObject(snapshot)\n\n if (previousInlineObject) {\n // Input Rules only look at the plain text of the text block. This\n // means that the RegExp is matched even if there is a leading inline\n // object.\n return false\n }\n\n // In theory, an Input Rule could return multiple matches. But in this\n // case we only expect one match.\n const match = event.matches.at(0)\n\n if (!match) {\n return false\n }\n\n return {hrObject, match}\n },\n actions: [\n (_, {hrObject, match}) => [\n raise({\n type: 'insert.block',\n block: {\n _type: hrObject.name,\n ...(hrObject.value ?? {}),\n },\n placement: 'before',\n select: 'none',\n }),\n raise({\n type: 'delete',\n at: match.targetOffsets,\n }),\n ],\n ],\n })\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {raise} from '@portabletext/editor/behaviors'\nimport {getPreviousInlineObject} from '@portabletext/editor/selectors'\nimport {defineInputRule} from '@portabletext/plugin-input-rule'\n\nexport function createOrderedListRule(config: {\n orderedList: (context: {schema: EditorSchema}) => string | undefined\n}) {\n return defineInputRule({\n on: /^1\\. /,\n guard: ({snapshot, event}) => {\n const orderedList = config.orderedList({\n schema: snapshot.context.schema,\n })\n\n if (!orderedList) {\n return false\n }\n\n const previousInlineObject = getPreviousInlineObject(snapshot)\n\n if (previousInlineObject) {\n return false\n }\n\n const match = event.matches.at(0)\n\n if (!match) {\n return false\n }\n\n return {match, orderedList}\n },\n actions: [\n ({event}, {match, orderedList}) => [\n raise({\n type: 'block.unset',\n props: ['style'],\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'block.set',\n props: {\n listItem: orderedList,\n level: event.focusTextBlock.node.level ?? 1,\n },\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'delete',\n at: match.targetOffsets,\n }),\n ],\n ],\n })\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {raise} from '@portabletext/editor/behaviors'\nimport {getPreviousInlineObject} from '@portabletext/editor/selectors'\nimport {defineInputRule} from '@portabletext/plugin-input-rule'\n\nexport function createUnorderedListRule(config: {\n unorderedList: (context: {schema: EditorSchema}) => string | undefined\n}) {\n return defineInputRule({\n on: /^(-|\\*) /,\n guard: ({snapshot, event}) => {\n const unorderedList = config.unorderedList({\n schema: snapshot.context.schema,\n })\n\n if (!unorderedList) {\n return false\n }\n\n const previousInlineObject = getPreviousInlineObject(snapshot)\n\n if (previousInlineObject) {\n return false\n }\n\n const match = event.matches.at(0)\n\n if (!match) {\n return false\n }\n\n return {match, unorderedList}\n },\n actions: [\n ({event}, {match, unorderedList}) => [\n raise({\n type: 'block.unset',\n props: ['style'],\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'block.set',\n props: {\n listItem: unorderedList,\n level: event.focusTextBlock.node.level ?? 1,\n },\n at: event.focusTextBlock.path,\n }),\n raise({\n type: 'delete',\n at: match.targetOffsets,\n }),\n ],\n ],\n })\n}\n","import type {EditorSchema} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {CharacterPairDecoratorPlugin} from '@portabletext/plugin-character-pair-decorator'\nimport {InputRulePlugin} from '@portabletext/plugin-input-rule'\nimport {useEffect} from 'react'\nimport {\n createMarkdownBehaviors,\n type MarkdownBehaviorsConfig,\n} from './behavior.markdown-shortcuts'\nimport {createBlockquoteRule} from './rule.blockquote'\nimport {createHeadingRule} from './rule.heading'\nimport {createHorizontalRuleRule} from './rule.horizontal-rule'\nimport {createOrderedListRule} from './rule.ordered-list'\nimport {createUnorderedListRule} from './rule.unordered-list'\n\n/**\n * @beta\n */\nexport type MarkdownShortcutsPluginProps = MarkdownBehaviorsConfig & {\n blockquoteStyle?: (context: {schema: EditorSchema}) => string | undefined\n defaultStyle?: (context: {schema: EditorSchema}) => string | undefined\n headingStyle?: (context: {\n schema: EditorSchema\n level: number\n }) => string | undefined\n unorderedList?: (context: {schema: EditorSchema}) => string | undefined\n orderedList?: (context: {schema: EditorSchema}) => string | undefined\n boldDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n codeDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n italicDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined\n strikeThroughDecorator?: ({\n schema,\n }: {\n schema: EditorSchema\n }) => string | undefined\n}\n\n/**\n * @beta\n */\nexport function MarkdownShortcutsPlugin({\n blockquoteStyle,\n boldDecorator,\n codeDecorator,\n defaultStyle,\n headingStyle,\n horizontalRuleObject,\n italicDecorator,\n orderedList,\n strikeThroughDecorator,\n unorderedList,\n}: MarkdownShortcutsPluginProps) {\n const editor = useEditor()\n\n useEffect(() => {\n const behaviors = createMarkdownBehaviors({\n defaultStyle,\n })\n\n const unregisterBehaviors = behaviors.map((behavior) =>\n editor.registerBehavior({behavior}),\n )\n\n return () => {\n for (const unregisterBehavior of unregisterBehaviors) {\n unregisterBehavior()\n }\n }\n }, [defaultStyle, editor, horizontalRuleObject])\n\n return (\n <>\n {boldDecorator ? (\n <>\n <CharacterPairDecoratorPlugin\n decorator={boldDecorator}\n pair={{char: '*', amount: 2}}\n />\n <CharacterPairDecoratorPlugin\n decorator={boldDecorator}\n pair={{char: '_', amount: 2}}\n />\n </>\n ) : null}\n {codeDecorator ? (\n <CharacterPairDecoratorPlugin\n decorator={codeDecorator}\n pair={{char: '`', amount: 1}}\n />\n ) : null}\n {italicDecorator ? (\n <>\n <CharacterPairDecoratorPlugin\n decorator={italicDecorator}\n pair={{char: '*', amount: 1}}\n />\n <CharacterPairDecoratorPlugin\n decorator={italicDecorator}\n pair={{char: '_', amount: 1}}\n />\n </>\n ) : null}\n {strikeThroughDecorator ? (\n <CharacterPairDecoratorPlugin\n decorator={strikeThroughDecorator}\n pair={{char: '~', amount: 2}}\n />\n ) : null}\n {blockquoteStyle ? (\n <InputRulePlugin rules={[createBlockquoteRule({blockquoteStyle})]} />\n ) : null}\n {headingStyle ? (\n <InputRulePlugin rules={[createHeadingRule({headingStyle})]} />\n ) : null}\n {horizontalRuleObject ? (\n <InputRulePlugin\n rules={[createHorizontalRuleRule({horizontalRuleObject})]}\n />\n ) : null}\n {orderedList ? (\n <InputRulePlugin rules={[createOrderedListRule({orderedList})]} />\n ) : null}\n {unorderedList ? (\n <InputRulePlugin rules={[createUnorderedListRule({unorderedList})]} />\n ) : null}\n </>\n )\n}\n"],"names":["createMarkdownBehaviors","config","automaticHrOnPaste","defineBehavior","on","guard","snapshot","event","text","originEvent","dataTransfer","getData","hrRegExp","hrCharacters","match","hrObject","horizontalRuleObject","schema","context","focusBlock","selectors","getFocusBlock","focusTextBlock","getFocusTextBlock","actions","_","execute","type","block","_type","name","children","node","placement","value","at","path","clearStyleOnBackspace","selectionCollapsed","isSelectionCollapsed","focusSpan","getFocusSpan","atTheBeginningOfBLock","_key","selection","focus","offset","defaultStyle","style","props","createBlockquoteRule","defineInputRule","blockquoteStyle","getPreviousInlineObject","matches","raise","targetOffsets","createHeadingRule","level","length","headingStyle","createHorizontalRuleRule","select","createOrderedListRule","orderedList","listItem","createUnorderedListRule","unorderedList","MarkdownShortcutsPlugin","t0","$","_c","boldDecorator","codeDecorator","italicDecorator","strikeThroughDecorator","editor","useEditor","t1","unregisterBehaviors","map","behavior","registerBehavior","unregisterBehavior","t2","useEffect","t3","char","amount","t4","t5","t6","t7","t8","t9","t10","t11","t12"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/plugin-markdown-shortcuts",
3
- "version": "1.1.4",
3
+ "version": "1.3.0",
4
4
  "description": "Adds helpful Markdown shortcuts to the editor",
5
5
  "keywords": [
6
6
  "portabletext",
@@ -39,7 +39,8 @@
39
39
  "dist"
40
40
  ],
41
41
  "dependencies": {
42
- "@portabletext/plugin-character-pair-decorator": "^1.1.3"
42
+ "@portabletext/plugin-character-pair-decorator": "^1.1.4",
43
+ "@portabletext/plugin-input-rule": "0.3.1"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/react": "^19.1.12",
@@ -49,11 +50,11 @@
49
50
  "react": "^19.1.1",
50
51
  "typescript": "5.9.3",
51
52
  "typescript-eslint": "^8.46.1",
52
- "@portabletext/editor": "^2.14.0"
53
+ "@portabletext/editor": "^2.14.1"
53
54
  },
54
55
  "peerDependencies": {
55
56
  "react": "^19",
56
- "@portabletext/editor": "^2.14.0"
57
+ "@portabletext/editor": "^2.14.1"
57
58
  },
58
59
  "scripts": {
59
60
  "build": "pkg-utils build --strict --check --clean",
@@ -1,185 +1,20 @@
1
1
  import type {EditorSchema} from '@portabletext/editor'
2
2
  import {defineBehavior, execute} from '@portabletext/editor/behaviors'
3
3
  import * as selectors from '@portabletext/editor/selectors'
4
- import * as utils from '@portabletext/editor/utils'
5
4
 
6
5
  export type MarkdownBehaviorsConfig = {
7
6
  horizontalRuleObject?: (context: {
8
7
  schema: EditorSchema
9
8
  }) => {name: string; value?: {[prop: string]: unknown}} | undefined
10
9
  defaultStyle?: (context: {schema: EditorSchema}) => string | undefined
11
- headingStyle?: (context: {
12
- schema: EditorSchema
13
- level: number
14
- }) => string | undefined
15
- blockquoteStyle?: (context: {schema: EditorSchema}) => string | undefined
16
- unorderedList?: (context: {schema: EditorSchema}) => string | undefined
17
- orderedList?: (context: {schema: EditorSchema}) => string | undefined
18
10
  }
19
11
 
20
12
  export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
21
- const automaticBlockquoteOnSpace = defineBehavior({
22
- on: 'insert.text',
23
- guard: ({snapshot, event}) => {
24
- const isSpace = event.text === ' '
25
-
26
- if (!isSpace) {
27
- return false
28
- }
29
-
30
- const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
31
- const focusTextBlock = selectors.getFocusTextBlock(snapshot)
32
- const focusSpan = selectors.getFocusSpan(snapshot)
33
-
34
- if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
35
- return false
36
- }
37
-
38
- const previousInlineObject = selectors.getPreviousInlineObject(snapshot)
39
- const blockOffset = utils.spanSelectionPointToBlockOffset({
40
- context: snapshot.context,
41
- selectionPoint: {
42
- path: [
43
- {_key: focusTextBlock.node._key},
44
- 'children',
45
- {_key: focusSpan.node._key},
46
- ],
47
- offset: snapshot.context.selection?.focus.offset ?? 0,
48
- },
49
- })
50
-
51
- if (previousInlineObject || !blockOffset) {
52
- return false
53
- }
54
-
55
- const blockText = utils.getTextBlockText(focusTextBlock.node)
56
- const caretAtTheEndOfQuote = blockOffset.offset === 1
57
- const looksLikeMarkdownQuote = /^>/.test(blockText)
58
- const blockquoteStyle = config.blockquoteStyle?.({
59
- schema: snapshot.context.schema,
60
- })
61
-
62
- if (
63
- caretAtTheEndOfQuote &&
64
- looksLikeMarkdownQuote &&
65
- blockquoteStyle !== undefined
66
- ) {
67
- return {focusTextBlock, style: blockquoteStyle}
68
- }
69
-
70
- return false
71
- },
72
- actions: [
73
- () => [
74
- execute({
75
- type: 'insert.text',
76
- text: ' ',
77
- }),
78
- ],
79
- (_, {focusTextBlock, style}) => [
80
- execute({
81
- type: 'block.unset',
82
- props: ['listItem', 'level'],
83
- at: focusTextBlock.path,
84
- }),
85
- execute({
86
- type: 'block.set',
87
- props: {style},
88
- at: focusTextBlock.path,
89
- }),
90
- execute({
91
- type: 'delete.text',
92
- at: {
93
- anchor: {
94
- path: focusTextBlock.path,
95
- offset: 0,
96
- },
97
- focus: {
98
- path: focusTextBlock.path,
99
- offset: 2,
100
- },
101
- },
102
- }),
103
- ],
104
- ],
105
- })
106
- const automaticHr = defineBehavior({
107
- on: 'insert.text',
108
- guard: ({snapshot, event}) => {
109
- const hrCharacter =
110
- event.text === '-'
111
- ? '-'
112
- : event.text === '*'
113
- ? '*'
114
- : event.text === '_'
115
- ? '_'
116
- : undefined
117
-
118
- if (hrCharacter === undefined) {
119
- return false
120
- }
121
-
122
- const hrObject = config.horizontalRuleObject?.({
123
- schema: snapshot.context.schema,
124
- })
125
- const focusBlock = selectors.getFocusTextBlock(snapshot)
126
- const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
127
-
128
- if (!hrObject || !focusBlock || !selectionCollapsed) {
129
- return false
130
- }
131
-
132
- const previousInlineObject = selectors.getPreviousInlineObject(snapshot)
133
- const textBefore = selectors.getBlockTextBefore(snapshot)
134
- const hrBlockOffsets = {
135
- anchor: {
136
- path: focusBlock.path,
137
- offset: 0,
138
- },
139
- focus: {
140
- path: focusBlock.path,
141
- offset: 3,
142
- },
143
- }
144
-
145
- if (
146
- !previousInlineObject &&
147
- textBefore === `${hrCharacter}${hrCharacter}`
148
- ) {
149
- return {hrObject, focusBlock, hrCharacter, hrBlockOffsets}
150
- }
151
-
152
- return false
153
- },
154
- actions: [
155
- (_, {hrCharacter}) => [
156
- execute({
157
- type: 'insert.text',
158
- text: hrCharacter,
159
- }),
160
- ],
161
- (_, {hrObject, hrBlockOffsets}) => [
162
- execute({
163
- type: 'insert.block',
164
- block: {
165
- _type: hrObject.name,
166
- ...(hrObject.value ?? {}),
167
- },
168
- placement: 'before',
169
- select: 'none',
170
- }),
171
- execute({
172
- type: 'delete.text',
173
- at: hrBlockOffsets,
174
- }),
175
- ],
176
- ],
177
- })
178
13
  const automaticHrOnPaste = defineBehavior({
179
14
  on: 'clipboard.paste',
180
15
  guard: ({snapshot, event}) => {
181
16
  const text = event.originEvent.dataTransfer.getData('text/plain')
182
- const hrRegExp = /^(---)$|(___)$|(\*\*\*)$/
17
+ const hrRegExp = /^(---)$|^(—-)$|^(___)$|^(\*\*\*)$/
183
18
  const hrCharacters = text.match(hrRegExp)?.[0]
184
19
  const hrObject = config.horizontalRuleObject?.({
185
20
  schema: snapshot.context.schema,
@@ -236,95 +71,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
236
71
  ],
237
72
  ],
238
73
  })
239
- const automaticHeadingOnSpace = defineBehavior({
240
- on: 'insert.text',
241
- guard: ({snapshot, event}) => {
242
- const isSpace = event.text === ' '
243
-
244
- if (!isSpace) {
245
- return false
246
- }
247
-
248
- const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
249
- const focusTextBlock = selectors.getFocusTextBlock(snapshot)
250
- const focusSpan = selectors.getFocusSpan(snapshot)
251
74
 
252
- if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
253
- return false
254
- }
255
-
256
- const blockOffset = utils.spanSelectionPointToBlockOffset({
257
- context: snapshot.context,
258
- selectionPoint: {
259
- path: [
260
- {_key: focusTextBlock.node._key},
261
- 'children',
262
- {_key: focusSpan.node._key},
263
- ],
264
- offset: snapshot.context.selection?.focus.offset ?? 0,
265
- },
266
- })
267
-
268
- if (!blockOffset) {
269
- return false
270
- }
271
-
272
- const previousInlineObject = selectors.getPreviousInlineObject(snapshot)
273
- const blockText = utils.getTextBlockText(focusTextBlock.node)
274
- const markdownHeadingSearch = /^#+/.exec(blockText)
275
- const level = markdownHeadingSearch
276
- ? markdownHeadingSearch[0].length
277
- : undefined
278
- const caretAtTheEndOfHeading = blockOffset.offset === level
279
-
280
- if (previousInlineObject || !caretAtTheEndOfHeading) {
281
- return false
282
- }
283
-
284
- const style =
285
- level !== undefined
286
- ? config.headingStyle?.({schema: snapshot.context.schema, level})
287
- : undefined
288
-
289
- if (level !== undefined && style !== undefined) {
290
- return {
291
- focusTextBlock,
292
- style: style,
293
- level,
294
- }
295
- }
296
-
297
- return false
298
- },
299
- actions: [
300
- ({event}) => [execute(event)],
301
- (_, {focusTextBlock, style, level}) => [
302
- execute({
303
- type: 'block.unset',
304
- props: ['listItem', 'level'],
305
- at: focusTextBlock.path,
306
- }),
307
- execute({
308
- type: 'block.set',
309
- props: {style},
310
- at: focusTextBlock.path,
311
- }),
312
- execute({
313
- type: 'delete.text',
314
- at: {
315
- anchor: {
316
- path: focusTextBlock.path,
317
- offset: 0,
318
- },
319
- focus: {
320
- path: focusTextBlock.path,
321
- offset: level + 1,
322
- },
323
- },
324
- }),
325
- ],
326
- ],
327
- })
328
75
  const clearStyleOnBackspace = defineBehavior({
329
76
  on: 'delete.backward',
330
77
  guard: ({snapshot}) => {
@@ -364,123 +111,8 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
364
111
  ],
365
112
  ],
366
113
  })
367
- const automaticListOnSpace = defineBehavior({
368
- on: 'insert.text',
369
- guard: ({snapshot, event}) => {
370
- const isSpace = event.text === ' '
371
-
372
- if (!isSpace) {
373
- return false
374
- }
375
-
376
- const selectionCollapsed = selectors.isSelectionCollapsed(snapshot)
377
- const focusTextBlock = selectors.getFocusTextBlock(snapshot)
378
- const focusSpan = selectors.getFocusSpan(snapshot)
379
-
380
- if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
381
- return false
382
- }
383
-
384
- const previousInlineObject = selectors.getPreviousInlineObject(snapshot)
385
- const blockOffset = utils.spanSelectionPointToBlockOffset({
386
- context: snapshot.context,
387
- selectionPoint: {
388
- path: [
389
- {_key: focusTextBlock.node._key},
390
- 'children',
391
- {_key: focusSpan.node._key},
392
- ],
393
- offset: snapshot.context.selection?.focus.offset ?? 0,
394
- },
395
- })
396
-
397
- if (previousInlineObject || !blockOffset) {
398
- return false
399
- }
400
-
401
- const blockText = utils.getTextBlockText(focusTextBlock.node)
402
- const defaultStyle = config.defaultStyle?.({
403
- schema: snapshot.context.schema,
404
- })
405
- const looksLikeUnorderedList = /^(-|\*)/.test(blockText)
406
- const unorderedList = config.unorderedList?.({
407
- schema: snapshot.context.schema,
408
- })
409
- const caretAtTheEndOfUnorderedList = blockOffset.offset === 1
410
-
411
- if (
412
- defaultStyle &&
413
- caretAtTheEndOfUnorderedList &&
414
- looksLikeUnorderedList &&
415
- unorderedList !== undefined
416
- ) {
417
- return {
418
- focusTextBlock,
419
- listItem: unorderedList,
420
- listItemLength: 1,
421
- style: defaultStyle,
422
- }
423
- }
424
-
425
- const looksLikeOrderedList = /^1\./.test(blockText)
426
- const orderedList = config.orderedList?.({
427
- schema: snapshot.context.schema,
428
- })
429
- const caretAtTheEndOfOrderedList = blockOffset.offset === 2
430
-
431
- if (
432
- defaultStyle &&
433
- caretAtTheEndOfOrderedList &&
434
- looksLikeOrderedList &&
435
- orderedList !== undefined
436
- ) {
437
- return {
438
- focusTextBlock,
439
- listItem: orderedList,
440
- listItemLength: 2,
441
- style: defaultStyle,
442
- }
443
- }
444
-
445
- return false
446
- },
447
- actions: [
448
- ({event}) => [execute(event)],
449
- (_, {focusTextBlock, style, listItem, listItemLength}) => [
450
- execute({
451
- type: 'block.set',
452
- props: {
453
- listItem,
454
- level: 1,
455
- style,
456
- },
457
- at: focusTextBlock.path,
458
- }),
459
- execute({
460
- type: 'delete.text',
461
- at: {
462
- anchor: {
463
- path: focusTextBlock.path,
464
- offset: 0,
465
- },
466
- focus: {
467
- path: focusTextBlock.path,
468
- offset: listItemLength + 1,
469
- },
470
- },
471
- }),
472
- ],
473
- ],
474
- })
475
114
 
476
- const markdownBehaviors = [
477
- automaticBlockquoteOnSpace,
478
- automaticHeadingOnSpace,
479
- automaticHr,
480
- automaticHrOnPaste,
481
- clearStyleOnBackspace,
482
- automaticListOnSpace,
483
- ]
115
+ const markdownBehaviors = [automaticHrOnPaste, clearStyleOnBackspace]
484
116
 
485
117
  return markdownBehaviors
486
118
  }
@@ -1,16 +1,30 @@
1
- import {useEditor} from '@portabletext/editor'
2
1
  import type {EditorSchema} from '@portabletext/editor'
2
+ import {useEditor} from '@portabletext/editor'
3
3
  import {CharacterPairDecoratorPlugin} from '@portabletext/plugin-character-pair-decorator'
4
+ import {InputRulePlugin} from '@portabletext/plugin-input-rule'
4
5
  import {useEffect} from 'react'
5
6
  import {
6
7
  createMarkdownBehaviors,
7
8
  type MarkdownBehaviorsConfig,
8
9
  } from './behavior.markdown-shortcuts'
10
+ import {createBlockquoteRule} from './rule.blockquote'
11
+ import {createHeadingRule} from './rule.heading'
12
+ import {createHorizontalRuleRule} from './rule.horizontal-rule'
13
+ import {createOrderedListRule} from './rule.ordered-list'
14
+ import {createUnorderedListRule} from './rule.unordered-list'
9
15
 
10
16
  /**
11
17
  * @beta
12
18
  */
13
19
  export type MarkdownShortcutsPluginProps = MarkdownBehaviorsConfig & {
20
+ blockquoteStyle?: (context: {schema: EditorSchema}) => string | undefined
21
+ defaultStyle?: (context: {schema: EditorSchema}) => string | undefined
22
+ headingStyle?: (context: {
23
+ schema: EditorSchema
24
+ level: number
25
+ }) => string | undefined
26
+ unorderedList?: (context: {schema: EditorSchema}) => string | undefined
27
+ orderedList?: (context: {schema: EditorSchema}) => string | undefined
14
28
  boldDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
15
29
  codeDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
16
30
  italicDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
@@ -40,12 +54,7 @@ export function MarkdownShortcutsPlugin({
40
54
 
41
55
  useEffect(() => {
42
56
  const behaviors = createMarkdownBehaviors({
43
- blockquoteStyle,
44
57
  defaultStyle,
45
- headingStyle,
46
- horizontalRuleObject,
47
- orderedList,
48
- unorderedList,
49
58
  })
50
59
 
51
60
  const unregisterBehaviors = behaviors.map((behavior) =>
@@ -57,15 +66,7 @@ export function MarkdownShortcutsPlugin({
57
66
  unregisterBehavior()
58
67
  }
59
68
  }
60
- }, [
61
- blockquoteStyle,
62
- defaultStyle,
63
- editor,
64
- headingStyle,
65
- horizontalRuleObject,
66
- orderedList,
67
- unorderedList,
68
- ])
69
+ }, [defaultStyle, editor, horizontalRuleObject])
69
70
 
70
71
  return (
71
72
  <>
@@ -105,6 +106,23 @@ export function MarkdownShortcutsPlugin({
105
106
  pair={{char: '~', amount: 2}}
106
107
  />
107
108
  ) : null}
109
+ {blockquoteStyle ? (
110
+ <InputRulePlugin rules={[createBlockquoteRule({blockquoteStyle})]} />
111
+ ) : null}
112
+ {headingStyle ? (
113
+ <InputRulePlugin rules={[createHeadingRule({headingStyle})]} />
114
+ ) : null}
115
+ {horizontalRuleObject ? (
116
+ <InputRulePlugin
117
+ rules={[createHorizontalRuleRule({horizontalRuleObject})]}
118
+ />
119
+ ) : null}
120
+ {orderedList ? (
121
+ <InputRulePlugin rules={[createOrderedListRule({orderedList})]} />
122
+ ) : null}
123
+ {unorderedList ? (
124
+ <InputRulePlugin rules={[createUnorderedListRule({unorderedList})]} />
125
+ ) : null}
108
126
  </>
109
127
  )
110
128
  }