@llui/markdown-editor 0.2.2 → 0.2.3
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/__llui_deps.json +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/core.d.ts.map +1 -1
- package/dist/plugins/core.js +3 -40
- package/dist/plugins/core.js.map +1 -1
- package/dist/plugins/inline.d.ts +12 -0
- package/dist/plugins/inline.d.ts.map +1 -0
- package/dist/plugins/inline.js +59 -0
- package/dist/plugins/inline.js.map +1 -0
- package/dist/plugins/single-block.d.ts +29 -0
- package/dist/plugins/single-block.d.ts.map +1 -0
- package/dist/plugins/single-block.js +145 -0
- package/dist/plugins/single-block.js.map +1 -0
- package/dist/transformers/gfm.d.ts +4 -0
- package/dist/transformers/gfm.d.ts.map +1 -1
- package/dist/transformers/gfm.js +15 -9
- package/dist/transformers/gfm.js.map +1 -1
- package/package.json +1 -1
package/dist/__llui_deps.json
CHANGED
|
@@ -155,6 +155,21 @@
|
|
|
155
155
|
}
|
|
156
156
|
]
|
|
157
157
|
},
|
|
158
|
+
"plugins/single-block#singleBlockPlugin": {
|
|
159
|
+
"helperLocalPaths": [],
|
|
160
|
+
"kind": "view-helper",
|
|
161
|
+
"viaParams": [
|
|
162
|
+
{
|
|
163
|
+
"index": 0,
|
|
164
|
+
"reads": [
|
|
165
|
+
"allowLineBreaks",
|
|
166
|
+
"formats",
|
|
167
|
+
"link"
|
|
168
|
+
],
|
|
169
|
+
"shape": "state-value"
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
},
|
|
158
173
|
"plugins/ui#definePluginUI": {
|
|
159
174
|
"helperLocalPaths": [],
|
|
160
175
|
"kind": "view-helper",
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { type BlockType, type FormatState, type OverlayKind, type CollabStatus,
|
|
|
3
3
|
export { type ItemSurface, type CommandItem, type CommandContext, type MarkdownPlugin, } from './plugins/types.js';
|
|
4
4
|
export { type PluginUI, type PluginUISpec, type PluginViewArgs, type PluginEffectContext, definePluginUI, } from './plugins/ui.js';
|
|
5
5
|
export { type CorePluginOptions, corePlugin } from './plugins/core.js';
|
|
6
|
+
export { type InlineFormat, type SingleBlockPluginOptions, singleBlockPlugin, } from './plugins/single-block.js';
|
|
6
7
|
export { type LinkPluginOptions, linkPlugin } from './plugins/link.js';
|
|
7
8
|
export { type CalloutKind, type CalloutData, type CalloutPluginOptions, calloutPlugin, $insertCallout, } from './plugins/callout.js';
|
|
8
9
|
export { hrPlugin, $insertHorizontalRule } from './plugins/hr.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { EMPTY_FORMAT, COLLAB_OFF, init, update, countWords, } from './state.js'
|
|
|
4
4
|
export {} from './plugins/types.js';
|
|
5
5
|
export { definePluginUI, } from './plugins/ui.js';
|
|
6
6
|
export { corePlugin } from './plugins/core.js';
|
|
7
|
+
export { singleBlockPlugin, } from './plugins/single-block.js';
|
|
7
8
|
export { linkPlugin } from './plugins/link.js';
|
|
8
9
|
export { calloutPlugin, $insertCallout, } from './plugins/callout.js';
|
|
9
10
|
export { hrPlugin, $insertHorizontalRule } from './plugins/hr.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,EAML,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAUL,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EAKN,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAKL,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAIL,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAA6B,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAA2C,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAA2B,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAIL,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAA0B,UAAU,EAAE,MAAM,2BAA2B,CAAA","sourcesContent":["// `@llui/markdown-editor` — WYSIWYG Markdown editor for LLui, built on Lexical.\n\nexport {\n type EditorConfig,\n type EditorParts,\n type CollabBinding,\n type CollabHooks,\n type CollabFactory,\n markdownEditor,\n} from './editor.js'\n\nexport {\n type BlockType,\n type FormatState,\n type OverlayKind,\n type CollabStatus,\n type EditorState,\n type EditorMsg,\n type EditorOutMsg,\n type EditorEffect,\n type InitOptions,\n EMPTY_FORMAT,\n COLLAB_OFF,\n init,\n update,\n countWords,\n} from './state.js'\n\nexport {\n type ItemSurface,\n type CommandItem,\n type CommandContext,\n type MarkdownPlugin,\n} from './plugins/types.js'\n\nexport {\n type PluginUI,\n type PluginUISpec,\n type PluginViewArgs,\n type PluginEffectContext,\n definePluginUI,\n} from './plugins/ui.js'\n\nexport { type CorePluginOptions, corePlugin } from './plugins/core.js'\nexport { type LinkPluginOptions, linkPlugin } from './plugins/link.js'\nexport {\n type CalloutKind,\n type CalloutData,\n type CalloutPluginOptions,\n calloutPlugin,\n $insertCallout,\n} from './plugins/callout.js'\nexport { hrPlugin, $insertHorizontalRule } from './plugins/hr.js'\nexport { slashPlugin } from './plugins/slash.js'\nexport { contextMenuPlugin } from './plugins/context-menu.js'\nexport { floatingToolbarPlugin } from './plugins/floating-toolbar.js'\nexport { type MathPluginOptions, mathPlugin } from './plugins/math.js'\nexport { type MermaidPluginOptions, mermaidPlugin } from './plugins/mermaid.js'\nexport { type Mention, type MentionPluginOptions, mentionPlugin } from './plugins/mention.js'\nexport { type EmojiPluginOptions, DEFAULT_EMOJI, emojiPlugin } from './plugins/emoji.js'\nexport { type ImagePluginOptions, imagePlugin } from './plugins/image.js'\nexport { tablePlugin } from './plugins/table.js'\n\nexport { GFM_NODES, GFM_TRANSFORMERS } from './transformers/gfm.js'\nexport { buildTransformers, orderTransformers } from './transformers/registry.js'\n\nexport { computeFormatState } from './format.js'\n\nexport {\n type ToolbarItemParts,\n type ToolbarParts,\n type ToolbarOptions,\n DEFAULT_GLYPHS,\n connectToolbar,\n toolbar,\n} from './surfaces/toolbar.js'\n\nexport { type LinkDialogOptions, linkDialog } from './surfaces/link-dialog.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,EAML,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAUL,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EAKN,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAKL,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAGL,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAIL,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAA6B,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAA2C,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAA2B,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAIL,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAA0B,UAAU,EAAE,MAAM,2BAA2B,CAAA","sourcesContent":["// `@llui/markdown-editor` — WYSIWYG Markdown editor for LLui, built on Lexical.\n\nexport {\n type EditorConfig,\n type EditorParts,\n type CollabBinding,\n type CollabHooks,\n type CollabFactory,\n markdownEditor,\n} from './editor.js'\n\nexport {\n type BlockType,\n type FormatState,\n type OverlayKind,\n type CollabStatus,\n type EditorState,\n type EditorMsg,\n type EditorOutMsg,\n type EditorEffect,\n type InitOptions,\n EMPTY_FORMAT,\n COLLAB_OFF,\n init,\n update,\n countWords,\n} from './state.js'\n\nexport {\n type ItemSurface,\n type CommandItem,\n type CommandContext,\n type MarkdownPlugin,\n} from './plugins/types.js'\n\nexport {\n type PluginUI,\n type PluginUISpec,\n type PluginViewArgs,\n type PluginEffectContext,\n definePluginUI,\n} from './plugins/ui.js'\n\nexport { type CorePluginOptions, corePlugin } from './plugins/core.js'\nexport {\n type InlineFormat,\n type SingleBlockPluginOptions,\n singleBlockPlugin,\n} from './plugins/single-block.js'\nexport { type LinkPluginOptions, linkPlugin } from './plugins/link.js'\nexport {\n type CalloutKind,\n type CalloutData,\n type CalloutPluginOptions,\n calloutPlugin,\n $insertCallout,\n} from './plugins/callout.js'\nexport { hrPlugin, $insertHorizontalRule } from './plugins/hr.js'\nexport { slashPlugin } from './plugins/slash.js'\nexport { contextMenuPlugin } from './plugins/context-menu.js'\nexport { floatingToolbarPlugin } from './plugins/floating-toolbar.js'\nexport { type MathPluginOptions, mathPlugin } from './plugins/math.js'\nexport { type MermaidPluginOptions, mermaidPlugin } from './plugins/mermaid.js'\nexport { type Mention, type MentionPluginOptions, mentionPlugin } from './plugins/mention.js'\nexport { type EmojiPluginOptions, DEFAULT_EMOJI, emojiPlugin } from './plugins/emoji.js'\nexport { type ImagePluginOptions, imagePlugin } from './plugins/image.js'\nexport { tablePlugin } from './plugins/table.js'\n\nexport { GFM_NODES, GFM_TRANSFORMERS } from './transformers/gfm.js'\nexport { buildTransformers, orderTransformers } from './transformers/registry.js'\n\nexport { computeFormatState } from './format.js'\n\nexport {\n type ToolbarItemParts,\n type ToolbarParts,\n type ToolbarOptions,\n DEFAULT_GLYPHS,\n connectToolbar,\n toolbar,\n} from './surfaces/toolbar.js'\n\nexport { type LinkDialogOptions, linkDialog } from './surfaces/link-dialog.js'\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAA+B,cAAc,EAAE,MAAM,YAAY,CAAA;AAmB7E,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAA;CACnB;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,iBAAsB,GAAG,cAAc,CAkIxE"}
|
package/dist/plugins/core.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
// The core plugin: the GFM superset of nodes, transformers, command items, and
|
|
2
2
|
// shortcuts. This is the default plugin when none are supplied, so the minimal
|
|
3
3
|
// `markdownEditor()` one-liner still has full keyboard formatting.
|
|
4
|
-
import { $createParagraphNode, $getSelection, $isRangeSelection,
|
|
4
|
+
import { $createParagraphNode, $getSelection, $isRangeSelection, REDO_COMMAND, UNDO_COMMAND, } from 'lexical';
|
|
5
5
|
import { mergeRegister } from '@lexical/utils';
|
|
6
6
|
import { $setBlocksType } from '@lexical/selection';
|
|
7
7
|
import { $createHeadingNode, $createQuoteNode } from '@lexical/rich-text';
|
|
8
8
|
import { $createCodeNode } from '@lexical/code-core';
|
|
9
9
|
import { INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, registerCheckList, registerList, } from '@lexical/list';
|
|
10
|
+
import { inlineItems } from './inline.js';
|
|
10
11
|
import { GFM_NODES, GFM_TRANSFORMERS } from '../transformers/gfm.js';
|
|
11
12
|
const NOOP_CTX = { send: () => { } };
|
|
12
|
-
function inline(format) {
|
|
13
|
-
return (editor) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
|
|
14
|
-
}
|
|
15
13
|
/** Wrap a node-factory into an editor action that converts the selected blocks. */
|
|
16
14
|
function block(create) {
|
|
17
15
|
return (editor) => editor.update(() => {
|
|
@@ -25,42 +23,7 @@ function heading(tag) {
|
|
|
25
23
|
}
|
|
26
24
|
export function corePlugin(_opts = {}) {
|
|
27
25
|
const items = [
|
|
28
|
-
|
|
29
|
-
id: 'bold',
|
|
30
|
-
label: 'Bold',
|
|
31
|
-
icon: 'bold',
|
|
32
|
-
group: 'inline',
|
|
33
|
-
keywords: ['strong'],
|
|
34
|
-
run: inline('bold'),
|
|
35
|
-
isActive: (f) => f.bold,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: 'italic',
|
|
39
|
-
label: 'Italic',
|
|
40
|
-
icon: 'italic',
|
|
41
|
-
group: 'inline',
|
|
42
|
-
keywords: ['emphasis'],
|
|
43
|
-
run: inline('italic'),
|
|
44
|
-
isActive: (f) => f.italic,
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: 'strikethrough',
|
|
48
|
-
label: 'Strikethrough',
|
|
49
|
-
icon: 'strikethrough',
|
|
50
|
-
group: 'inline',
|
|
51
|
-
keywords: ['strike', 'del'],
|
|
52
|
-
run: inline('strikethrough'),
|
|
53
|
-
isActive: (f) => f.strikethrough,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
id: 'code',
|
|
57
|
-
label: 'Inline code',
|
|
58
|
-
icon: 'code',
|
|
59
|
-
group: 'inline',
|
|
60
|
-
keywords: ['mono'],
|
|
61
|
-
run: inline('code'),
|
|
62
|
-
isActive: (f) => f.code,
|
|
63
|
-
},
|
|
26
|
+
...inlineItems(),
|
|
64
27
|
{
|
|
65
28
|
id: 'paragraph',
|
|
66
29
|
label: 'Text',
|
package/dist/plugins/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"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","sourcesContent":["// The core plugin: the GFM superset of nodes, transformers, command items, and\n// shortcuts. This is the default plugin when none are supplied, so the minimal\n// `markdownEditor()` one-liner still has full keyboard formatting.\n\nimport {\n $createParagraphNode,\n $getSelection,\n $isRangeSelection,\n FORMAT_TEXT_COMMAND,\n REDO_COMMAND,\n UNDO_COMMAND,\n type ElementNode,\n type LexicalEditor,\n type TextFormatType,\n} from 'lexical'\nimport { mergeRegister } from '@lexical/utils'\nimport { $setBlocksType } from '@lexical/selection'\nimport { $createHeadingNode, $createQuoteNode, type HeadingTagType } from '@lexical/rich-text'\nimport { $createCodeNode } from '@lexical/code-core'\nimport {\n INSERT_CHECK_LIST_COMMAND,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n registerCheckList,\n registerList,\n} from '@lexical/list'\nimport type { CommandContext, CommandItem, MarkdownPlugin } from './types.js'\nimport { GFM_NODES, GFM_TRANSFORMERS } from '../transformers/gfm.js'\n\nconst NOOP_CTX: CommandContext = { send: () => {} }\n\nfunction inline(format: TextFormatType): (editor: LexicalEditor) => void {\n return (editor) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format)\n}\n\n/** Wrap a node-factory into an editor action that converts the selected blocks. */\nfunction block(create: () => ElementNode): (editor: LexicalEditor) => void {\n return (editor) =>\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $setBlocksType(selection, create)\n })\n}\n\nfunction heading(tag: HeadingTagType): (editor: LexicalEditor) => void {\n return block(() => $createHeadingNode(tag))\n}\n\nexport interface CorePluginOptions {\n /** Reserved for future core options. */\n readonly _?: never\n}\n\nexport function corePlugin(_opts: CorePluginOptions = {}): MarkdownPlugin {\n const items: CommandItem[] = [\n {\n id: 'bold',\n label: 'Bold',\n icon: 'bold',\n group: 'inline',\n keywords: ['strong'],\n run: inline('bold'),\n isActive: (f) => f.bold,\n },\n {\n id: 'italic',\n label: 'Italic',\n icon: 'italic',\n group: 'inline',\n keywords: ['emphasis'],\n run: inline('italic'),\n isActive: (f) => f.italic,\n },\n {\n id: 'strikethrough',\n label: 'Strikethrough',\n icon: 'strikethrough',\n group: 'inline',\n keywords: ['strike', 'del'],\n run: inline('strikethrough'),\n isActive: (f) => f.strikethrough,\n },\n {\n id: 'code',\n label: 'Inline code',\n icon: 'code',\n group: 'inline',\n keywords: ['mono'],\n run: inline('code'),\n isActive: (f) => f.code,\n },\n {\n id: 'paragraph',\n label: 'Text',\n icon: 'paragraph',\n group: 'block',\n keywords: ['body', 'normal'],\n run: block(() => $createParagraphNode()),\n isActive: (f) => f.blockType === 'paragraph',\n },\n {\n id: 'h1',\n label: 'Heading 1',\n icon: 'h1',\n group: 'block',\n keywords: ['title'],\n run: heading('h1'),\n isActive: (f) => f.blockType === 'h1',\n },\n {\n id: 'h2',\n label: 'Heading 2',\n icon: 'h2',\n group: 'block',\n run: heading('h2'),\n isActive: (f) => f.blockType === 'h2',\n },\n {\n id: 'h3',\n label: 'Heading 3',\n icon: 'h3',\n group: 'block',\n run: heading('h3'),\n isActive: (f) => f.blockType === 'h3',\n },\n {\n id: 'quote',\n label: 'Quote',\n icon: 'quote',\n group: 'block',\n keywords: ['blockquote'],\n run: block(() => $createQuoteNode()),\n isActive: (f) => f.blockType === 'quote',\n },\n {\n id: 'codeBlock',\n label: 'Code block',\n icon: 'code-block',\n group: 'block',\n keywords: ['fence', 'pre'],\n run: block(() => $createCodeNode()),\n isActive: (f) => f.blockType === 'code',\n },\n {\n id: 'bulletList',\n label: 'Bulleted list',\n icon: 'list-bullet',\n group: 'list',\n keywords: ['unordered', 'ul'],\n run: (e) => e.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'bullet',\n },\n {\n id: 'numberList',\n label: 'Numbered list',\n icon: 'list-number',\n group: 'list',\n keywords: ['ordered', 'ol'],\n run: (e) => e.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'number',\n },\n {\n id: 'checkList',\n label: 'Task list',\n icon: 'list-check',\n group: 'list',\n keywords: ['todo', 'checkbox'],\n run: (e) => e.dispatchCommand(INSERT_CHECK_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'check',\n },\n {\n id: 'undo',\n label: 'Undo',\n icon: 'undo',\n group: 'history',\n run: (e) => e.dispatchCommand(UNDO_COMMAND, undefined),\n isDisabled: (f) => !f.canUndo,\n surfaces: ['toolbar', 'context'],\n },\n {\n id: 'redo',\n label: 'Redo',\n icon: 'redo',\n group: 'history',\n run: (e) => e.dispatchCommand(REDO_COMMAND, undefined),\n isDisabled: (f) => !f.canRedo,\n surfaces: ['toolbar', 'context'],\n },\n ]\n\n const byId = new Map(items.map((i) => [i.id, i]))\n const shortcut =\n (id: string) =>\n (editor: LexicalEditor): boolean => {\n const item = byId.get(id)\n if (!item) return false\n item.run(editor, NOOP_CTX)\n return true\n }\n\n return {\n name: 'core',\n nodes: GFM_NODES,\n transformers: GFM_TRANSFORMERS,\n items,\n // registerList wires list commands/indentation; registerCheckList adds the\n // click-to-toggle on task items. (Linking is handled by the editor's link\n // dialog via $toggleLink — see commitLink in editor.ts.)\n register: (editor) => mergeRegister(registerList(editor), registerCheckList(editor)),\n shortcuts: [\n { combo: 'Mod-Alt-1', run: shortcut('h1') },\n { combo: 'Mod-Alt-2', run: shortcut('h2') },\n { combo: 'Mod-Alt-3', run: shortcut('h3') },\n { combo: 'Mod-Shift-7', run: shortcut('numberList') },\n { combo: 'Mod-Shift-8', run: shortcut('bulletList') },\n { combo: 'Mod-Shift-9', run: shortcut('quote') },\n ],\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"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","sourcesContent":["// The core plugin: the GFM superset of nodes, transformers, command items, and\n// shortcuts. This is the default plugin when none are supplied, so the minimal\n// `markdownEditor()` one-liner still has full keyboard formatting.\n\nimport {\n $createParagraphNode,\n $getSelection,\n $isRangeSelection,\n REDO_COMMAND,\n UNDO_COMMAND,\n type ElementNode,\n type LexicalEditor,\n} from 'lexical'\nimport { mergeRegister } from '@lexical/utils'\nimport { $setBlocksType } from '@lexical/selection'\nimport { $createHeadingNode, $createQuoteNode, type HeadingTagType } from '@lexical/rich-text'\nimport { $createCodeNode } from '@lexical/code-core'\nimport {\n INSERT_CHECK_LIST_COMMAND,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n registerCheckList,\n registerList,\n} from '@lexical/list'\nimport type { CommandContext, CommandItem, MarkdownPlugin } from './types.js'\nimport { inlineItems } from './inline.js'\nimport { GFM_NODES, GFM_TRANSFORMERS } from '../transformers/gfm.js'\n\nconst NOOP_CTX: CommandContext = { send: () => {} }\n\n/** Wrap a node-factory into an editor action that converts the selected blocks. */\nfunction block(create: () => ElementNode): (editor: LexicalEditor) => void {\n return (editor) =>\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $setBlocksType(selection, create)\n })\n}\n\nfunction heading(tag: HeadingTagType): (editor: LexicalEditor) => void {\n return block(() => $createHeadingNode(tag))\n}\n\nexport interface CorePluginOptions {\n /** Reserved for future core options. */\n readonly _?: never\n}\n\nexport function corePlugin(_opts: CorePluginOptions = {}): MarkdownPlugin {\n const items: CommandItem[] = [\n ...inlineItems(),\n {\n id: 'paragraph',\n label: 'Text',\n icon: 'paragraph',\n group: 'block',\n keywords: ['body', 'normal'],\n run: block(() => $createParagraphNode()),\n isActive: (f) => f.blockType === 'paragraph',\n },\n {\n id: 'h1',\n label: 'Heading 1',\n icon: 'h1',\n group: 'block',\n keywords: ['title'],\n run: heading('h1'),\n isActive: (f) => f.blockType === 'h1',\n },\n {\n id: 'h2',\n label: 'Heading 2',\n icon: 'h2',\n group: 'block',\n run: heading('h2'),\n isActive: (f) => f.blockType === 'h2',\n },\n {\n id: 'h3',\n label: 'Heading 3',\n icon: 'h3',\n group: 'block',\n run: heading('h3'),\n isActive: (f) => f.blockType === 'h3',\n },\n {\n id: 'quote',\n label: 'Quote',\n icon: 'quote',\n group: 'block',\n keywords: ['blockquote'],\n run: block(() => $createQuoteNode()),\n isActive: (f) => f.blockType === 'quote',\n },\n {\n id: 'codeBlock',\n label: 'Code block',\n icon: 'code-block',\n group: 'block',\n keywords: ['fence', 'pre'],\n run: block(() => $createCodeNode()),\n isActive: (f) => f.blockType === 'code',\n },\n {\n id: 'bulletList',\n label: 'Bulleted list',\n icon: 'list-bullet',\n group: 'list',\n keywords: ['unordered', 'ul'],\n run: (e) => e.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'bullet',\n },\n {\n id: 'numberList',\n label: 'Numbered list',\n icon: 'list-number',\n group: 'list',\n keywords: ['ordered', 'ol'],\n run: (e) => e.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'number',\n },\n {\n id: 'checkList',\n label: 'Task list',\n icon: 'list-check',\n group: 'list',\n keywords: ['todo', 'checkbox'],\n run: (e) => e.dispatchCommand(INSERT_CHECK_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'check',\n },\n {\n id: 'undo',\n label: 'Undo',\n icon: 'undo',\n group: 'history',\n run: (e) => e.dispatchCommand(UNDO_COMMAND, undefined),\n isDisabled: (f) => !f.canUndo,\n surfaces: ['toolbar', 'context'],\n },\n {\n id: 'redo',\n label: 'Redo',\n icon: 'redo',\n group: 'history',\n run: (e) => e.dispatchCommand(REDO_COMMAND, undefined),\n isDisabled: (f) => !f.canRedo,\n surfaces: ['toolbar', 'context'],\n },\n ]\n\n const byId = new Map(items.map((i) => [i.id, i]))\n const shortcut =\n (id: string) =>\n (editor: LexicalEditor): boolean => {\n const item = byId.get(id)\n if (!item) return false\n item.run(editor, NOOP_CTX)\n return true\n }\n\n return {\n name: 'core',\n nodes: GFM_NODES,\n transformers: GFM_TRANSFORMERS,\n items,\n // registerList wires list commands/indentation; registerCheckList adds the\n // click-to-toggle on task items. (Linking is handled by the editor's link\n // dialog via $toggleLink — see commitLink in editor.ts.)\n register: (editor) => mergeRegister(registerList(editor), registerCheckList(editor)),\n shortcuts: [\n { combo: 'Mod-Alt-1', run: shortcut('h1') },\n { combo: 'Mod-Alt-2', run: shortcut('h2') },\n { combo: 'Mod-Alt-3', run: shortcut('h3') },\n { combo: 'Mod-Shift-7', run: shortcut('numberList') },\n { combo: 'Mod-Shift-8', run: shortcut('bulletList') },\n { combo: 'Mod-Shift-9', run: shortcut('quote') },\n ],\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type LexicalEditor, type TextFormatType } from 'lexical';
|
|
2
|
+
import type { CommandItem } from './types.js';
|
|
3
|
+
/** An inline text-format surfaced as a toolbar command item. */
|
|
4
|
+
export type InlineFormat = 'bold' | 'italic' | 'strikethrough' | 'code';
|
|
5
|
+
/** The full inline-format set, in toolbar order. */
|
|
6
|
+
export declare const INLINE_FORMATS: readonly InlineFormat[];
|
|
7
|
+
/** Dispatch a text-format toggle on the live editor. */
|
|
8
|
+
export declare function inlineFormatCommand(format: TextFormatType): (editor: LexicalEditor) => void;
|
|
9
|
+
/** Build the inline `CommandItem`s for `formats` (default: all four), grouped
|
|
10
|
+
* under `'inline'`. Surfaces are left unset (item appears in every surface). */
|
|
11
|
+
export declare function inlineItems(formats?: readonly InlineFormat[]): CommandItem[];
|
|
12
|
+
//# sourceMappingURL=inline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../../src/plugins/inline.ts"],"names":[],"mappings":"AAMA,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAEtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,CAAA;AAEvE,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAAgD,CAAA;AAyClG,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAE3F;AAED;gFACgF;AAChF,wBAAgB,WAAW,CAAC,OAAO,GAAE,SAAS,YAAY,EAAmB,GAAG,WAAW,EAAE,CAa5F"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Shared inline text-formatting building blocks: the bold / italic /
|
|
2
|
+
// strikethrough / code command items and the `FORMAT_TEXT_COMMAND` dispatcher.
|
|
3
|
+
// Both `corePlugin` (the full GFM superset) and `singleBlockPlugin` (inline-only)
|
|
4
|
+
// derive their inline surface from here, so the canonical inline-format set and
|
|
5
|
+
// its labels/icons/keywords live in exactly one place.
|
|
6
|
+
import { FORMAT_TEXT_COMMAND } from 'lexical';
|
|
7
|
+
/** The full inline-format set, in toolbar order. */
|
|
8
|
+
export const INLINE_FORMATS = ['bold', 'italic', 'strikethrough', 'code'];
|
|
9
|
+
const DEFS = {
|
|
10
|
+
bold: {
|
|
11
|
+
label: 'Bold',
|
|
12
|
+
icon: 'bold',
|
|
13
|
+
keywords: ['strong'],
|
|
14
|
+
format: 'bold',
|
|
15
|
+
isActive: (f) => f.bold,
|
|
16
|
+
},
|
|
17
|
+
italic: {
|
|
18
|
+
label: 'Italic',
|
|
19
|
+
icon: 'italic',
|
|
20
|
+
keywords: ['emphasis'],
|
|
21
|
+
format: 'italic',
|
|
22
|
+
isActive: (f) => f.italic,
|
|
23
|
+
},
|
|
24
|
+
strikethrough: {
|
|
25
|
+
label: 'Strikethrough',
|
|
26
|
+
icon: 'strikethrough',
|
|
27
|
+
keywords: ['strike', 'del'],
|
|
28
|
+
format: 'strikethrough',
|
|
29
|
+
isActive: (f) => f.strikethrough,
|
|
30
|
+
},
|
|
31
|
+
code: {
|
|
32
|
+
label: 'Inline code',
|
|
33
|
+
icon: 'code',
|
|
34
|
+
keywords: ['mono'],
|
|
35
|
+
format: 'code',
|
|
36
|
+
isActive: (f) => f.code,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
/** Dispatch a text-format toggle on the live editor. */
|
|
40
|
+
export function inlineFormatCommand(format) {
|
|
41
|
+
return (editor) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
|
|
42
|
+
}
|
|
43
|
+
/** Build the inline `CommandItem`s for `formats` (default: all four), grouped
|
|
44
|
+
* under `'inline'`. Surfaces are left unset (item appears in every surface). */
|
|
45
|
+
export function inlineItems(formats = INLINE_FORMATS) {
|
|
46
|
+
return formats.map((id) => {
|
|
47
|
+
const def = DEFS[id];
|
|
48
|
+
return {
|
|
49
|
+
id,
|
|
50
|
+
label: def.label,
|
|
51
|
+
icon: def.icon,
|
|
52
|
+
group: 'inline',
|
|
53
|
+
keywords: def.keywords,
|
|
54
|
+
run: inlineFormatCommand(def.format),
|
|
55
|
+
isActive: def.isActive,
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=inline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/plugins/inline.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,+EAA+E;AAC/E,kFAAkF;AAClF,gFAAgF;AAChF,uDAAuD;AAEvD,OAAO,EAAE,mBAAmB,EAA2C,MAAM,SAAS,CAAA;AAOtF,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,CAAA;AAUlG,MAAM,IAAI,GAA0C;IAClD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,UAAU,CAAC;QACtB,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM;KAC1B;IACD,aAAa,EAAE;QACb,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC3B,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;KACjC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;CACF,CAAA;AAED,wDAAwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA;AACxE,CAAC;AAED;gFACgF;AAChF,MAAM,UAAU,WAAW,CAAC,UAAmC,cAAc;IAC3E,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;QACpB,OAAO;YACL,EAAE;YACF,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["// Shared inline text-formatting building blocks: the bold / italic /\n// strikethrough / code command items and the `FORMAT_TEXT_COMMAND` dispatcher.\n// Both `corePlugin` (the full GFM superset) and `singleBlockPlugin` (inline-only)\n// derive their inline surface from here, so the canonical inline-format set and\n// its labels/icons/keywords live in exactly one place.\n\nimport { FORMAT_TEXT_COMMAND, type LexicalEditor, type TextFormatType } from 'lexical'\nimport type { FormatState } from '../state.js'\nimport type { CommandItem } from './types.js'\n\n/** An inline text-format surfaced as a toolbar command item. */\nexport type InlineFormat = 'bold' | 'italic' | 'strikethrough' | 'code'\n\n/** The full inline-format set, in toolbar order. */\nexport const INLINE_FORMATS: readonly InlineFormat[] = ['bold', 'italic', 'strikethrough', 'code']\n\ninterface InlineFormatDef {\n label: string\n icon: string\n keywords: readonly string[]\n format: TextFormatType\n isActive: (f: FormatState) => boolean\n}\n\nconst DEFS: Record<InlineFormat, InlineFormatDef> = {\n bold: {\n label: 'Bold',\n icon: 'bold',\n keywords: ['strong'],\n format: 'bold',\n isActive: (f) => f.bold,\n },\n italic: {\n label: 'Italic',\n icon: 'italic',\n keywords: ['emphasis'],\n format: 'italic',\n isActive: (f) => f.italic,\n },\n strikethrough: {\n label: 'Strikethrough',\n icon: 'strikethrough',\n keywords: ['strike', 'del'],\n format: 'strikethrough',\n isActive: (f) => f.strikethrough,\n },\n code: {\n label: 'Inline code',\n icon: 'code',\n keywords: ['mono'],\n format: 'code',\n isActive: (f) => f.code,\n },\n}\n\n/** Dispatch a text-format toggle on the live editor. */\nexport function inlineFormatCommand(format: TextFormatType): (editor: LexicalEditor) => void {\n return (editor) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format)\n}\n\n/** Build the inline `CommandItem`s for `formats` (default: all four), grouped\n * under `'inline'`. Surfaces are left unset (item appears in every surface). */\nexport function inlineItems(formats: readonly InlineFormat[] = INLINE_FORMATS): CommandItem[] {\n return formats.map((id) => {\n const def = DEFS[id]\n return {\n id,\n label: def.label,\n icon: def.icon,\n group: 'inline',\n keywords: def.keywords,\n run: inlineFormatCommand(def.format),\n isActive: def.isActive,\n }\n })\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { MarkdownPlugin } from './types.js';
|
|
2
|
+
import { type InlineFormat } from './inline.js';
|
|
3
|
+
export type { InlineFormat };
|
|
4
|
+
declare global {
|
|
5
|
+
interface ImportMeta {
|
|
6
|
+
env?: {
|
|
7
|
+
DEV?: boolean;
|
|
8
|
+
MODE?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export interface SingleBlockPluginOptions {
|
|
13
|
+
/** Inline formats surfaced as toolbar items.
|
|
14
|
+
* Default `['bold', 'italic', 'strikethrough', 'code']`. NOTE: this limits the
|
|
15
|
+
* toolbar buttons only — markdown syntax (`*x*`) and Ctrl/⌘ shortcuts still
|
|
16
|
+
* apply every inline format, and all inline markdown round-trips regardless. */
|
|
17
|
+
formats?: readonly InlineFormat[];
|
|
18
|
+
/** Allow soft line breaks within the single paragraph. When `false` (default)
|
|
19
|
+
* Enter is inert and pasted/seeded line breaks collapse to spaces — a strict
|
|
20
|
+
* single-line field. When `true`, Enter inserts a `\n` and merged lines are
|
|
21
|
+
* joined with a line break instead of a space. A new paragraph is never made. */
|
|
22
|
+
allowLineBreaks?: boolean;
|
|
23
|
+
/** Register `LinkNode` + the markdown link transformer so inline links
|
|
24
|
+
* round-trip. Default `false`. Compose with `linkPlugin()` for the toolbar
|
|
25
|
+
* button + insert dialog. */
|
|
26
|
+
link?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function singleBlockPlugin(opts?: SingleBlockPluginOptions): MarkdownPlugin;
|
|
29
|
+
//# sourceMappingURL=single-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-block.d.ts","sourceRoot":"","sources":["../../src/plugins/single-block.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAG5D,YAAY,EAAE,YAAY,EAAE,CAAA;AAK5B,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KACvC;CACF;AAED,MAAM,WAAW,wBAAwB;IACvC;;;oFAGgF;IAChF,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACjC;;;qFAGiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;iCAE6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAuED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,wBAA6B,GAAG,cAAc,CAqDrF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// The single-block plugin: constrains the editor to exactly ONE paragraph that
|
|
2
|
+
// holds only inline content (bold / italic / strikethrough / code, optionally
|
|
3
|
+
// links). No headings, lists, quotes, code blocks, or multiple paragraphs.
|
|
4
|
+
//
|
|
5
|
+
// It enforces the invariant two ways, so it holds no matter how content arrives
|
|
6
|
+
// (typing, the markdown seed, or a paste):
|
|
7
|
+
// 1. The transformer set contributes ONLY inline text-format transformers, so
|
|
8
|
+
// block markdown (`# `, `- `, `> `, fenced code) is never parsed into block
|
|
9
|
+
// nodes — `registerMarkdownShortcuts` and `$convertFromMarkdownString` both
|
|
10
|
+
// read from this set.
|
|
11
|
+
// 2. A RootNode transform coalesces the document back to a single paragraph of
|
|
12
|
+
// inline leaves whenever anything slips through (a multi-paragraph paste, a
|
|
13
|
+
// multi-line seed). Enter is intercepted so it never splits the paragraph.
|
|
14
|
+
//
|
|
15
|
+
// `singleBlockPlugin()` REPLACES the default plugin set — pass it instead of
|
|
16
|
+
// `corePlugin()`. A dev-only guard warns when block-contributing plugins are
|
|
17
|
+
// composed alongside it (since a plugin is additive and can't un-register them).
|
|
18
|
+
import { $createLineBreakNode, $createParagraphNode, $createTextNode, $getSelection, $isElementNode, $isLineBreakNode, $isParagraphNode, $isRangeSelection, $isTextNode, COMMAND_PRIORITY_HIGH, KEY_ENTER_COMMAND, RootNode, } from 'lexical';
|
|
19
|
+
import { mergeRegister } from '@lexical/utils';
|
|
20
|
+
import { LinkNode } from '@lexical/link';
|
|
21
|
+
import { LINK } from '@lexical/markdown';
|
|
22
|
+
import { inlineItems } from './inline.js';
|
|
23
|
+
import { INLINE_TEXT_TRANSFORMERS } from '../transformers/gfm.js';
|
|
24
|
+
/** Is this node an inline leaf that belongs directly inside a paragraph? */
|
|
25
|
+
function isInlineLeaf(node) {
|
|
26
|
+
return $isTextNode(node) || $isLineBreakNode(node) || ($isElementNode(node) && node.isInline());
|
|
27
|
+
}
|
|
28
|
+
/** Decompose a block element into "lines" — each line is the inline content of
|
|
29
|
+
* one leaf block (paragraph, heading, list item, …). Recurses through nested
|
|
30
|
+
* block containers (a list → its items) so every leaf block becomes its own
|
|
31
|
+
* line; this is what lets adjacent list items be separator-joined rather than
|
|
32
|
+
* mashed together. */
|
|
33
|
+
function blockLines(node) {
|
|
34
|
+
const children = node.getChildren();
|
|
35
|
+
const hasBlockChildren = children.some((c) => $isElementNode(c) && !c.isInline());
|
|
36
|
+
if (!hasBlockChildren) {
|
|
37
|
+
return [children.filter(isInlineLeaf)];
|
|
38
|
+
}
|
|
39
|
+
const lines = [];
|
|
40
|
+
for (const child of children) {
|
|
41
|
+
if ($isElementNode(child) && !child.isInline())
|
|
42
|
+
lines.push(...blockLines(child));
|
|
43
|
+
else if (isInlineLeaf(child))
|
|
44
|
+
lines.push([child]);
|
|
45
|
+
}
|
|
46
|
+
return lines;
|
|
47
|
+
}
|
|
48
|
+
/** Collapse every line break in a paragraph to a single space (single-line
|
|
49
|
+
* mode) so adjacent lines don't mash into one word. */
|
|
50
|
+
function collapseLineBreaks(para) {
|
|
51
|
+
for (const child of para.getChildren()) {
|
|
52
|
+
if ($isLineBreakNode(child))
|
|
53
|
+
child.replace($createTextNode(' '));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Coalesce the document to exactly one paragraph of inline content. Returns the
|
|
57
|
+
* `RootNode` transform the plugin registers. */
|
|
58
|
+
function makeEnforce(allowLineBreaks) {
|
|
59
|
+
return (root) => {
|
|
60
|
+
const children = root.getChildren();
|
|
61
|
+
// Fast path: already a single paragraph — only fix stray line breaks.
|
|
62
|
+
if (children.length === 1 && $isParagraphNode(children[0])) {
|
|
63
|
+
if (!allowLineBreaks)
|
|
64
|
+
collapseLineBreaks(children[0]);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Gather the inline content of every leaf block as a separate line.
|
|
68
|
+
const lines = [];
|
|
69
|
+
for (const child of children) {
|
|
70
|
+
if ($isElementNode(child)) {
|
|
71
|
+
if (child.isInline())
|
|
72
|
+
lines.push([child]);
|
|
73
|
+
else
|
|
74
|
+
lines.push(...blockLines(child));
|
|
75
|
+
}
|
|
76
|
+
else if (isInlineLeaf(child)) {
|
|
77
|
+
lines.push([child]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const para = $createParagraphNode();
|
|
81
|
+
let first = true;
|
|
82
|
+
for (const line of lines) {
|
|
83
|
+
if (line.length === 0)
|
|
84
|
+
continue;
|
|
85
|
+
if (!first)
|
|
86
|
+
para.append(allowLineBreaks ? $createLineBreakNode() : $createTextNode(' '));
|
|
87
|
+
for (const node of line)
|
|
88
|
+
para.append(node);
|
|
89
|
+
first = false;
|
|
90
|
+
}
|
|
91
|
+
if (!allowLineBreaks)
|
|
92
|
+
collapseLineBreaks(para);
|
|
93
|
+
root.clear();
|
|
94
|
+
root.append(para);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export function singleBlockPlugin(opts = {}) {
|
|
98
|
+
const allowLineBreaks = opts.allowLineBreaks ?? false;
|
|
99
|
+
const linkEnabled = opts.link ?? false;
|
|
100
|
+
const items = inlineItems(opts.formats);
|
|
101
|
+
const transformers = [...INLINE_TEXT_TRANSFORMERS];
|
|
102
|
+
if (linkEnabled)
|
|
103
|
+
transformers.push(LINK);
|
|
104
|
+
const enforce = makeEnforce(allowLineBreaks);
|
|
105
|
+
const onEnter = (event) => {
|
|
106
|
+
if (!allowLineBreaks) {
|
|
107
|
+
// Inert: never split the paragraph, never insert a break.
|
|
108
|
+
event?.preventDefault();
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// Convert a plain Enter (which would split the paragraph) into a soft line
|
|
112
|
+
// break; let Shift+Enter fall through to the default soft-break handler.
|
|
113
|
+
if (event && event.shiftKey)
|
|
114
|
+
return false;
|
|
115
|
+
event?.preventDefault();
|
|
116
|
+
const selection = $getSelection();
|
|
117
|
+
if ($isRangeSelection(selection))
|
|
118
|
+
selection.insertLineBreak();
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
name: 'single-block',
|
|
123
|
+
...(linkEnabled ? { nodes: [LinkNode] } : {}),
|
|
124
|
+
transformers,
|
|
125
|
+
items,
|
|
126
|
+
// Dev guard: single-block REPLACES the default plugin set, but a plugin is
|
|
127
|
+
// additive and can't un-register a sibling's block contributions. If another
|
|
128
|
+
// plugin's command items introduce block/structural content, warn loudly so
|
|
129
|
+
// the silently-broken `[corePlugin(), singleBlockPlugin()]` combo is caught.
|
|
130
|
+
onItems: (all) => {
|
|
131
|
+
if (import.meta.env?.DEV !== true)
|
|
132
|
+
return;
|
|
133
|
+
const structural = all.filter((i) => i.group && i.group !== 'inline' && i.group !== 'history');
|
|
134
|
+
if (structural.length === 0)
|
|
135
|
+
return;
|
|
136
|
+
const ids = structural.map((i) => i.id).join(', ');
|
|
137
|
+
console.warn(`[llui] singleBlockPlugin: other plugins contribute block/structural commands (${ids}). ` +
|
|
138
|
+
`single-block REPLACES the default plugin set — pass it INSTEAD OF corePlugin (and any ` +
|
|
139
|
+
`block/insert plugins). Block content may otherwise reappear and the single-paragraph ` +
|
|
140
|
+
`constraint won't hold.`);
|
|
141
|
+
},
|
|
142
|
+
register: (editor) => mergeRegister(editor.registerNodeTransform(RootNode, enforce), editor.registerCommand(KEY_ENTER_COMMAND, onEnter, COMMAND_PRIORITY_HIGH)),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=single-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-block.js","sourceRoot":"","sources":["../../src/plugins/single-block.ts"],"names":[],"mappings":"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","sourcesContent":["// The single-block plugin: constrains the editor to exactly ONE paragraph that\n// holds only inline content (bold / italic / strikethrough / code, optionally\n// links). No headings, lists, quotes, code blocks, or multiple paragraphs.\n//\n// It enforces the invariant two ways, so it holds no matter how content arrives\n// (typing, the markdown seed, or a paste):\n// 1. The transformer set contributes ONLY inline text-format transformers, so\n// block markdown (`# `, `- `, `> `, fenced code) is never parsed into block\n// nodes — `registerMarkdownShortcuts` and `$convertFromMarkdownString` both\n// read from this set.\n// 2. A RootNode transform coalesces the document back to a single paragraph of\n// inline leaves whenever anything slips through (a multi-paragraph paste, a\n// multi-line seed). Enter is intercepted so it never splits the paragraph.\n//\n// `singleBlockPlugin()` REPLACES the default plugin set — pass it instead of\n// `corePlugin()`. A dev-only guard warns when block-contributing plugins are\n// composed alongside it (since a plugin is additive and can't un-register them).\n\nimport {\n $createLineBreakNode,\n $createParagraphNode,\n $createTextNode,\n $getSelection,\n $isElementNode,\n $isLineBreakNode,\n $isParagraphNode,\n $isRangeSelection,\n $isTextNode,\n COMMAND_PRIORITY_HIGH,\n KEY_ENTER_COMMAND,\n RootNode,\n type ElementNode,\n type LexicalNode,\n type ParagraphNode,\n} from 'lexical'\nimport { mergeRegister } from '@lexical/utils'\nimport { LinkNode } from '@lexical/link'\nimport { LINK, type Transformer } from '@lexical/markdown'\nimport type { CommandItem, MarkdownPlugin } from './types.js'\nimport { inlineItems, type InlineFormat } from './inline.js'\nimport { INLINE_TEXT_TRANSFORMERS } from '../transformers/gfm.js'\n\nexport type { InlineFormat }\n\n// `import.meta.env.DEV` is substituted by Vite/Rollup at build time; raw tsc /\n// vitest see it as undefined, so the dev guard stays off there unless the\n// bundler sets it. (Augmented locally so the package carries no build-tool dep.)\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean; MODE?: string }\n }\n}\n\nexport interface SingleBlockPluginOptions {\n /** Inline formats surfaced as toolbar items.\n * Default `['bold', 'italic', 'strikethrough', 'code']`. NOTE: this limits the\n * toolbar buttons only — markdown syntax (`*x*`) and Ctrl/⌘ shortcuts still\n * apply every inline format, and all inline markdown round-trips regardless. */\n formats?: readonly InlineFormat[]\n /** Allow soft line breaks within the single paragraph. When `false` (default)\n * Enter is inert and pasted/seeded line breaks collapse to spaces — a strict\n * single-line field. When `true`, Enter inserts a `\\n` and merged lines are\n * joined with a line break instead of a space. A new paragraph is never made. */\n allowLineBreaks?: boolean\n /** Register `LinkNode` + the markdown link transformer so inline links\n * round-trip. Default `false`. Compose with `linkPlugin()` for the toolbar\n * button + insert dialog. */\n link?: boolean\n}\n\n/** Is this node an inline leaf that belongs directly inside a paragraph? */\nfunction isInlineLeaf(node: LexicalNode): boolean {\n return $isTextNode(node) || $isLineBreakNode(node) || ($isElementNode(node) && node.isInline())\n}\n\n/** Decompose a block element into \"lines\" — each line is the inline content of\n * one leaf block (paragraph, heading, list item, …). Recurses through nested\n * block containers (a list → its items) so every leaf block becomes its own\n * line; this is what lets adjacent list items be separator-joined rather than\n * mashed together. */\nfunction blockLines(node: ElementNode): LexicalNode[][] {\n const children = node.getChildren()\n const hasBlockChildren = children.some((c) => $isElementNode(c) && !c.isInline())\n if (!hasBlockChildren) {\n return [children.filter(isInlineLeaf)]\n }\n const lines: LexicalNode[][] = []\n for (const child of children) {\n if ($isElementNode(child) && !child.isInline()) lines.push(...blockLines(child))\n else if (isInlineLeaf(child)) lines.push([child])\n }\n return lines\n}\n\n/** Collapse every line break in a paragraph to a single space (single-line\n * mode) so adjacent lines don't mash into one word. */\nfunction collapseLineBreaks(para: ParagraphNode): void {\n for (const child of para.getChildren()) {\n if ($isLineBreakNode(child)) child.replace($createTextNode(' '))\n }\n}\n\n/** Coalesce the document to exactly one paragraph of inline content. Returns the\n * `RootNode` transform the plugin registers. */\nfunction makeEnforce(allowLineBreaks: boolean): (root: RootNode) => void {\n return (root) => {\n const children = root.getChildren()\n\n // Fast path: already a single paragraph — only fix stray line breaks.\n if (children.length === 1 && $isParagraphNode(children[0])) {\n if (!allowLineBreaks) collapseLineBreaks(children[0])\n return\n }\n\n // Gather the inline content of every leaf block as a separate line.\n const lines: LexicalNode[][] = []\n for (const child of children) {\n if ($isElementNode(child)) {\n if (child.isInline()) lines.push([child])\n else lines.push(...blockLines(child))\n } else if (isInlineLeaf(child)) {\n lines.push([child])\n }\n }\n\n const para = $createParagraphNode()\n let first = true\n for (const line of lines) {\n if (line.length === 0) continue\n if (!first) para.append(allowLineBreaks ? $createLineBreakNode() : $createTextNode(' '))\n for (const node of line) para.append(node)\n first = false\n }\n if (!allowLineBreaks) collapseLineBreaks(para)\n root.clear()\n root.append(para)\n }\n}\n\nexport function singleBlockPlugin(opts: SingleBlockPluginOptions = {}): MarkdownPlugin {\n const allowLineBreaks = opts.allowLineBreaks ?? false\n const linkEnabled = opts.link ?? false\n\n const items: CommandItem[] = inlineItems(opts.formats)\n\n const transformers: Transformer[] = [...INLINE_TEXT_TRANSFORMERS]\n if (linkEnabled) transformers.push(LINK)\n\n const enforce = makeEnforce(allowLineBreaks)\n\n const onEnter = (event: KeyboardEvent | null): boolean => {\n if (!allowLineBreaks) {\n // Inert: never split the paragraph, never insert a break.\n event?.preventDefault()\n return true\n }\n // Convert a plain Enter (which would split the paragraph) into a soft line\n // break; let Shift+Enter fall through to the default soft-break handler.\n if (event && event.shiftKey) return false\n event?.preventDefault()\n const selection = $getSelection()\n if ($isRangeSelection(selection)) selection.insertLineBreak()\n return true\n }\n\n return {\n name: 'single-block',\n ...(linkEnabled ? { nodes: [LinkNode] } : {}),\n transformers,\n items,\n // Dev guard: single-block REPLACES the default plugin set, but a plugin is\n // additive and can't un-register a sibling's block contributions. If another\n // plugin's command items introduce block/structural content, warn loudly so\n // the silently-broken `[corePlugin(), singleBlockPlugin()]` combo is caught.\n onItems: (all) => {\n if (import.meta.env?.DEV !== true) return\n const structural = all.filter((i) => i.group && i.group !== 'inline' && i.group !== 'history')\n if (structural.length === 0) return\n const ids = structural.map((i) => i.id).join(', ')\n console.warn(\n `[llui] singleBlockPlugin: other plugins contribute block/structural commands (${ids}). ` +\n `single-block REPLACES the default plugin set — pass it INSTEAD OF corePlugin (and any ` +\n `block/insert plugins). Block content may otherwise reappear and the single-paragraph ` +\n `constraint won't hold.`,\n )\n },\n register: (editor) =>\n mergeRegister(\n editor.registerNodeTransform(RootNode, enforce),\n editor.registerCommand(KEY_ENTER_COMMAND, onEnter, COMMAND_PRIORITY_HIGH),\n ),\n }\n}\n"]}
|
|
@@ -2,6 +2,10 @@ import type { Klass, LexicalNode } from 'lexical';
|
|
|
2
2
|
import { type Transformer } from '@lexical/markdown';
|
|
3
3
|
/** Node classes required to render the GFM superset. */
|
|
4
4
|
export declare const GFM_NODES: ReadonlyArray<Klass<LexicalNode>>;
|
|
5
|
+
/** Inline text-format transformers (no block nodes, no node registration). These
|
|
6
|
+
* are the only transformers a single-block / inline-only editor needs; `LINK` is
|
|
7
|
+
* kept separate since it requires `LinkNode` to be registered. */
|
|
8
|
+
export declare const INLINE_TEXT_TRANSFORMERS: readonly Transformer[];
|
|
5
9
|
/** Markdown ↔ node transformers for the GFM superset. */
|
|
6
10
|
export declare const GFM_TRANSFORMERS: readonly Transformer[];
|
|
7
11
|
//# sourceMappingURL=gfm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gfm.d.ts","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOjD,OAAO,EACL,KAAK,WAAW,EAiBjB,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAQvD,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,
|
|
1
|
+
{"version":3,"file":"gfm.d.ts","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOjD,OAAO,EACL,KAAK,WAAW,EAiBjB,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAQvD,CAAA;AAED;;kEAEkE;AAClE,eAAO,MAAM,wBAAwB,EAAE,SAAS,WAAW,EAU1D,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAWlD,CAAA"}
|
package/dist/transformers/gfm.js
CHANGED
|
@@ -17,6 +17,20 @@ export const GFM_NODES = [
|
|
|
17
17
|
CodeHighlightNode,
|
|
18
18
|
LinkNode,
|
|
19
19
|
];
|
|
20
|
+
/** Inline text-format transformers (no block nodes, no node registration). These
|
|
21
|
+
* are the only transformers a single-block / inline-only editor needs; `LINK` is
|
|
22
|
+
* kept separate since it requires `LinkNode` to be registered. */
|
|
23
|
+
export const INLINE_TEXT_TRANSFORMERS = [
|
|
24
|
+
BOLD_ITALIC_STAR,
|
|
25
|
+
BOLD_ITALIC_UNDERSCORE,
|
|
26
|
+
BOLD_STAR,
|
|
27
|
+
BOLD_UNDERSCORE,
|
|
28
|
+
ITALIC_STAR,
|
|
29
|
+
ITALIC_UNDERSCORE,
|
|
30
|
+
STRIKETHROUGH,
|
|
31
|
+
INLINE_CODE,
|
|
32
|
+
HIGHLIGHT,
|
|
33
|
+
];
|
|
20
34
|
/** Markdown ↔ node transformers for the GFM superset. */
|
|
21
35
|
export const GFM_TRANSFORMERS = [
|
|
22
36
|
HEADING,
|
|
@@ -27,15 +41,7 @@ export const GFM_TRANSFORMERS = [
|
|
|
27
41
|
UNORDERED_LIST,
|
|
28
42
|
ORDERED_LIST,
|
|
29
43
|
CODE,
|
|
30
|
-
|
|
31
|
-
BOLD_ITALIC_UNDERSCORE,
|
|
32
|
-
BOLD_STAR,
|
|
33
|
-
BOLD_UNDERSCORE,
|
|
34
|
-
ITALIC_STAR,
|
|
35
|
-
ITALIC_UNDERSCORE,
|
|
36
|
-
STRIKETHROUGH,
|
|
37
|
-
INLINE_CODE,
|
|
38
|
-
HIGHLIGHT,
|
|
44
|
+
...INLINE_TEXT_TRANSFORMERS,
|
|
39
45
|
LINK,
|
|
40
46
|
];
|
|
41
47
|
//# sourceMappingURL=gfm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gfm.js","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAGlF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,gFAAgF;AAChF,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAEL,OAAO,EACP,KAAK,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,SAAS,EACT,IAAI,GACL,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAsC;IAC1D,WAAW;IACX,SAAS;IACT,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,iBAAiB;IACjB,QAAQ;CACT,CAAA;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,OAAO;IACP,KAAK;IACL,4EAA4E;IAC5E,2EAA2E;IAC3E,UAAU;IACV,cAAc;IACd,YAAY;IACZ,IAAI;IACJ,
|
|
1
|
+
{"version":3,"file":"gfm.js","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAGlF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,gFAAgF;AAChF,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAEL,OAAO,EACP,KAAK,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,SAAS,EACT,IAAI,GACL,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAsC;IAC1D,WAAW;IACX,SAAS;IACT,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,iBAAiB;IACjB,QAAQ;CACT,CAAA;AAED;;kEAEkE;AAClE,MAAM,CAAC,MAAM,wBAAwB,GAA2B;IAC9D,gBAAgB;IAChB,sBAAsB;IACtB,SAAS;IACT,eAAe;IACf,WAAW;IACX,iBAAiB;IACjB,aAAa;IACb,WAAW;IACX,SAAS;CACV,CAAA;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,OAAO;IACP,KAAK;IACL,4EAA4E;IAC5E,2EAA2E;IAC3E,UAAU;IACV,cAAc;IACd,YAAY;IACZ,IAAI;IACJ,GAAG,wBAAwB;IAC3B,IAAI;CACL,CAAA","sourcesContent":["// The built-in GFM superset: node classes + the explicit transformer set that\n// maps exactly to those nodes (no surprise nodes — HR/tables are opt-in plugins).\n\nimport type { Klass, LexicalNode } from 'lexical'\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text'\nimport { ListNode, ListItemNode } from '@lexical/list'\nimport { LinkNode } from '@lexical/link'\n// `@lexical/code-core` (not `@lexical/code`) keeps Prism out of the bundle — we\n// never register syntax highlighting, so plain CodeNode is all we need.\nimport { CodeNode, CodeHighlightNode } from '@lexical/code-core'\nimport {\n type Transformer,\n HEADING,\n QUOTE,\n UNORDERED_LIST,\n ORDERED_LIST,\n CHECK_LIST,\n CODE,\n BOLD_ITALIC_STAR,\n BOLD_ITALIC_UNDERSCORE,\n BOLD_STAR,\n BOLD_UNDERSCORE,\n ITALIC_STAR,\n ITALIC_UNDERSCORE,\n STRIKETHROUGH,\n INLINE_CODE,\n HIGHLIGHT,\n LINK,\n} from '@lexical/markdown'\n\n/** Node classes required to render the GFM superset. */\nexport const GFM_NODES: ReadonlyArray<Klass<LexicalNode>> = [\n HeadingNode,\n QuoteNode,\n ListNode,\n ListItemNode,\n CodeNode,\n CodeHighlightNode,\n LinkNode,\n]\n\n/** Inline text-format transformers (no block nodes, no node registration). These\n * are the only transformers a single-block / inline-only editor needs; `LINK` is\n * kept separate since it requires `LinkNode` to be registered. */\nexport const INLINE_TEXT_TRANSFORMERS: readonly Transformer[] = [\n BOLD_ITALIC_STAR,\n BOLD_ITALIC_UNDERSCORE,\n BOLD_STAR,\n BOLD_UNDERSCORE,\n ITALIC_STAR,\n ITALIC_UNDERSCORE,\n STRIKETHROUGH,\n INLINE_CODE,\n HIGHLIGHT,\n]\n\n/** Markdown ↔ node transformers for the GFM superset. */\nexport const GFM_TRANSFORMERS: readonly Transformer[] = [\n HEADING,\n QUOTE,\n // CHECK_LIST must precede the plain list transformers: `- [ ]`/`- [x]` also\n // match `- `, so UNORDERED_LIST would otherwise swallow it as bullet text.\n CHECK_LIST,\n UNORDERED_LIST,\n ORDERED_LIST,\n CODE,\n ...INLINE_TEXT_TRANSFORMERS,\n LINK,\n]\n"]}
|