@mdfn/components 0.1.0 → 0.1.1
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.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +43 -10
package/dist/index.cjs
CHANGED
|
@@ -168,7 +168,7 @@ function runToolbarAction(controller, action, commandTarget) {
|
|
|
168
168
|
if (action.id === "redo") return controller.redo();
|
|
169
169
|
return action.command ? controller.run(action.command) : false;
|
|
170
170
|
}
|
|
171
|
-
var MDFN_COMPONENTS_VERSION = "0.1.
|
|
171
|
+
var MDFN_COMPONENTS_VERSION = "0.1.1";
|
|
172
172
|
// Annotate the CommonJS export names for ESM import in node:
|
|
173
173
|
0 && (module.exports = {
|
|
174
174
|
MDFN_COMPONENTS_VERSION,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Transaction, mapSelection, type EditorController, type MdfnDiagnostic, type MdfnNode, type ReviewState, type TextSelection } from \"@mdfn/core\";\n\nexport type EditorMode = \"visual\" | \"source\" | \"split\" | \"preview\" | \"read-only\";\n\nexport interface ToolbarAction {\n readonly id: string;\n readonly label: string;\n readonly command?: string;\n readonly shortcut?: string;\n readonly pressed?: boolean;\n readonly disabled?: boolean;\n}\n\nexport interface ToolbarGroup {\n readonly id: string;\n readonly label: string;\n readonly actions: readonly ToolbarAction[];\n}\n\nexport interface ToolbarModel {\n readonly ariaLabel: string;\n readonly groups: readonly ToolbarGroup[];\n}\n\nexport interface ToolbarCommandTarget {\n can?(command: string): boolean;\n run(command: string): boolean;\n}\n\nexport interface MarkdownInsertionTarget {\n insertMarkdown(markdown: string): boolean;\n}\n\nexport interface UploadedMarkdown {\n readonly markdown: string;\n rollback(cause: unknown): void | Promise<void>;\n}\n\nexport type MarkdownUploadResult = string | UploadedMarkdown | undefined;\n\nexport interface CapturedMarkdownInsertion {\n insert(markdown: string): boolean;\n cancel(): void;\n}\n\n/** Insert through the active visual surface, or fall back to the canonical controller selection. */\nexport function insertMarkdownAtSelection(\n controller: EditorController,\n target: MarkdownInsertionTarget | null | undefined,\n markdown: string,\n selection?: TextSelection,\n): void {\n if (!selection && target?.insertMarkdown(markdown)) return;\n const state = controller.getState();\n const insertionSelection = selection ?? (state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length });\n const from = Math.min(insertionSelection.anchor, insertionSelection.head);\n const to = Math.max(insertionSelection.anchor, insertionSelection.head);\n controller.dispatch(\n new Transaction()\n .replaceSource(from, to, markdown)\n .setSelection({ kind: \"text\", anchor: from + markdown.length, head: from + markdown.length })\n .withSource(\"components:file-insert\"),\n );\n}\n\n/** Keep an asynchronous file insertion anchored to the selection where it started. */\nexport function captureMarkdownInsertion(controller: EditorController, signal?: AbortSignal): CapturedMarkdownInsertion {\n const state = controller.getState();\n let selection: TextSelection = state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length };\n let active = true;\n const unsubscribe = controller.subscribe((change) => {\n if (!active || change.changedRanges.length === 0) return;\n if (change.source.startsWith(\"history:\") && change.changedRanges.some((range) =>\n range.from === 0 && range.to === change.previous.markdown.length && range.insertedLength === change.current.markdown.length\n )) {\n cancel();\n return;\n }\n const mapped = mapSelection(selection, change.changedRanges);\n if (mapped?.kind === \"text\") selection = mapped;\n });\n const cancel = (): void => {\n if (!active) return;\n active = false;\n unsubscribe();\n signal?.removeEventListener(\"abort\", cancel);\n };\n if (signal?.aborted) cancel();\n else signal?.addEventListener(\"abort\", cancel, { once: true });\n return {\n insert(markdown) {\n if (!active) return false;\n cancel();\n insertMarkdownAtSelection(controller, null, markdown, selection);\n return true;\n },\n cancel,\n };\n}\n\n/** Complete an upload and compensate durable assets if canonical insertion fails or is cancelled. */\nexport async function insertUploadedMarkdown(\n insertion: CapturedMarkdownInsertion,\n upload: Promise<MarkdownUploadResult>,\n): Promise<void> {\n const result = await upload;\n if (!result) {\n insertion.cancel();\n return;\n }\n const markdown = typeof result === \"string\" ? result : result.markdown;\n try {\n if (!insertion.insert(markdown)) throw new Error(\"MDFN_MARKDOWN_INSERTION_CANCELLED\");\n } catch (error) {\n if (typeof result !== \"string\") await result.rollback(error);\n throw error;\n }\n}\n\nexport const defaultToolbarGroups: readonly ToolbarGroup[] = Object.freeze([\n { id: \"history\", label: \"History\", actions: [{ id: \"undo\", label: \"Undo\", shortcut: \"Mod-z\" }, { id: \"redo\", label: \"Redo\", shortcut: \"Mod-Shift-z\" }] },\n { id: \"inline\", label: \"Inline formatting\", actions: [{ id: \"bold\", label: \"Bold\", command: \"bold\", shortcut: \"Mod-b\" }, { id: \"italic\", label: \"Italic\", command: \"italic\", shortcut: \"Mod-i\" }, { id: \"code\", label: \"Code\", command: \"inline-code\" }] },\n { id: \"blocks\", label: \"Blocks\", actions: [{ id: \"heading-2\", label: \"Heading\", command: \"heading-2\" }, { id: \"bullet-list\", label: \"Bullet list\", command: \"bullet-list\" }, { id: \"ordered-list\", label: \"Numbered list\", command: \"ordered-list\" }, { id: \"blockquote\", label: \"Quote\", command: \"blockquote\" }, { id: \"code-block\", label: \"Code block\", command: \"code-block\" }] },\n]);\n\nexport interface SlashCommand {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly keywords: readonly string[];\n readonly kind: \"command\" | \"link\" | \"table\" | \"file\" | \"comment\";\n readonly command?: string;\n}\n\nexport const defaultSlashCommands: readonly SlashCommand[] = Object.freeze([\n { id: \"paragraph\", label: \"Paragraph\", description: \"Start a text paragraph\", keywords: [\"text\", \"body\"], kind: \"command\", command: \"paragraph\" },\n { id: \"heading-1\", label: \"Heading 1\", description: \"Insert a top-level heading\", keywords: [\"title\", \"h1\"], kind: \"command\", command: \"heading-1\" },\n { id: \"heading-2\", label: \"Heading 2\", description: \"Insert a section heading\", keywords: [\"subtitle\", \"h2\"], kind: \"command\", command: \"heading-2\" },\n { id: \"bullet-list\", label: \"Bullet list\", description: \"Create an unordered list\", keywords: [\"ul\", \"list\"], kind: \"command\", command: \"bullet-list\" },\n { id: \"ordered-list\", label: \"Numbered list\", description: \"Create an ordered list\", keywords: [\"ol\", \"steps\"], kind: \"command\", command: \"ordered-list\" },\n { id: \"blockquote\", label: \"Quote\", description: \"Create a block quote\", keywords: [\"quote\", \"citation\"], kind: \"command\", command: \"blockquote\" },\n { id: \"code-block\", label: \"Code block\", description: \"Create a fenced code block\", keywords: [\"code\", \"fence\"], kind: \"command\", command: \"code-block\" },\n { id: \"link\", label: \"Link\", description: \"Add or edit a safe link\", keywords: [\"url\", \"href\"], kind: \"link\" },\n { id: \"table\", label: \"Table\", description: \"Insert a table\", keywords: [\"grid\", \"rows\", \"columns\"], kind: \"table\" },\n { id: \"file\", label: \"File or image\", description: \"Select or upload an asset\", keywords: [\"asset\", \"upload\", \"image\"], kind: \"file\" },\n { id: \"comment\", label: \"Comment\", description: \"Comment on the current selection\", keywords: [\"review\", \"note\"], kind: \"comment\" },\n]);\n\nexport function filterSlashCommands(query: string, commands: readonly SlashCommand[] = defaultSlashCommands): readonly SlashCommand[] {\n const terms = query.toLocaleLowerCase().trim().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return commands;\n return commands.filter((command) => {\n const haystack = [command.label, command.description, command.id, ...command.keywords].join(\" \").toLocaleLowerCase();\n return terms.every((term) => haystack.includes(term));\n });\n}\n\nexport interface OutlineItem {\n readonly id: string;\n readonly level: number;\n readonly text: string;\n readonly from?: number;\n}\n\nfunction plainText(node: MdfnNode): string {\n if (node.type === \"text\" || node.type === \"inlineCode\") return node.text ?? \"\";\n return (node.content ?? []).map(plainText).join(\"\");\n}\n\nexport interface AuthoringModel {\n readonly version: number;\n readonly mode: EditorMode;\n readonly compact: boolean;\n readonly toolbar: ToolbarModel;\n readonly bubble: ToolbarModel;\n readonly floating: ToolbarModel;\n readonly bubbleVisible: boolean;\n readonly floatingVisible: boolean;\n readonly slashOpen: boolean;\n readonly slashCommands: readonly SlashCommand[];\n readonly outline: readonly OutlineItem[];\n readonly diagnostics: readonly MdfnDiagnostic[];\n readonly comments: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"comments\"];\n readonly suggestions: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"suggestions\"];\n readonly reviewState: ReviewState;\n readonly audit: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"audit\"];\n}\n\nexport function createAuthoringModel(\n controller: EditorController,\n options: { readonly mode?: EditorMode; readonly compact?: boolean; readonly slashQuery?: string; readonly slashOpen?: boolean; readonly commandTarget?: ToolbarCommandTarget | null } = {},\n): AuthoringModel {\n const state = controller.getState();\n const selection = state.selection?.kind === \"text\" ? state.selection : null;\n const selectionFrom = selection ? Math.min(selection.anchor, selection.head) : 0;\n const selectionTo = selection ? Math.max(selection.anchor, selection.head) : 0;\n const beforeCaret = selection && selectionFrom === selectionTo ? state.markdown.slice(state.markdown.lastIndexOf(\"\\n\", selectionFrom - 1) + 1, selectionFrom) : \"\";\n const slashMatch = /^\\s*\\/([^\\s/]*)$/.exec(beforeCaret);\n const inlineGroups = defaultToolbarGroups.filter((group) => group.id === \"inline\");\n const blockGroups = defaultToolbarGroups.filter((group) => group.id === \"blocks\");\n return {\n version: state.version,\n mode: options.mode ?? \"visual\",\n compact: options.compact ?? false,\n toolbar: createToolbarModel(controller, defaultToolbarGroups, \"Markdown authoring toolbar\", options.commandTarget),\n bubble: createToolbarModel(controller, inlineGroups, \"Selection formatting\", options.commandTarget),\n floating: createToolbarModel(controller, blockGroups, \"Block formatting\", options.commandTarget),\n bubbleVisible: Boolean(selection && selectionFrom !== selectionTo),\n floatingVisible: Boolean(selection && selectionFrom === selectionTo),\n slashOpen: options.slashOpen === true || Boolean(slashMatch),\n slashCommands: filterSlashCommands(options.slashQuery ?? slashMatch?.[1] ?? \"\"),\n outline: state.document.content.flatMap((node, index) => node.type === \"heading\" ? [{ id: node.id ?? `heading-${index}`, level: typeof node.attrs?.level === \"number\" ? node.attrs.level : 1, text: plainText(node), from: node.source?.from }] : []),\n diagnostics: state.diagnostics,\n comments: state.sidecar?.comments ?? [],\n suggestions: state.sidecar?.suggestions ?? [],\n reviewState: state.sidecar?.reviewState ?? \"draft\",\n audit: state.sidecar?.audit ?? [],\n };\n}\n\n/** Framework-neutral version descriptor used by every authoring adapter. */\nexport interface AuthoringVersion {\n readonly version: number;\n readonly createdAt?: string;\n readonly authorId?: string;\n readonly changeSource?: string;\n}\n\nexport function createToolbarModel(controller: EditorController, groups: readonly ToolbarGroup[] = defaultToolbarGroups, ariaLabel = \"Markdown formatting\", commandTarget?: ToolbarCommandTarget | null): ToolbarModel {\n const canRun = (command: string): boolean => commandTarget?.can?.(command) ?? controller.can(command);\n return {\n ariaLabel,\n groups: groups.map((group) => ({\n ...group,\n actions: group.actions.map((action) => ({\n ...action,\n disabled: action.id === \"undo\" ? !(commandTarget?.can?.(\"undo\") ?? controller.canUndo()) : action.id === \"redo\" ? !(commandTarget?.can?.(\"redo\") ?? controller.canRedo()) : action.command ? !canRun(action.command) : action.disabled,\n })),\n })),\n };\n}\n\nexport function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean {\n if (action.disabled) return false;\n if (commandTarget) return commandTarget.run(action.command ?? action.id);\n if (action.id === \"undo\") return controller.undo();\n if (action.id === \"redo\") return controller.redo();\n return action.command ? controller.run(action.command) : false;\n}\n\nexport const MDFN_COMPONENTS_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Transaction, mapSelection, type EditorController, type MdfnDiagnostic, type MdfnNode, type ReviewState, type TextSelection } from \"@mdfn/core\";\n\nexport type EditorMode = \"visual\" | \"source\" | \"split\" | \"preview\" | \"read-only\";\n\nexport interface ToolbarAction {\n readonly id: string;\n readonly label: string;\n readonly command?: string;\n readonly shortcut?: string;\n readonly pressed?: boolean;\n readonly disabled?: boolean;\n}\n\nexport interface ToolbarGroup {\n readonly id: string;\n readonly label: string;\n readonly actions: readonly ToolbarAction[];\n}\n\nexport interface ToolbarModel {\n readonly ariaLabel: string;\n readonly groups: readonly ToolbarGroup[];\n}\n\nexport interface ToolbarCommandTarget {\n can?(command: string): boolean;\n run(command: string): boolean;\n}\n\nexport interface MarkdownInsertionTarget {\n insertMarkdown(markdown: string): boolean;\n}\n\nexport interface UploadedMarkdown {\n readonly markdown: string;\n rollback(cause: unknown): void | Promise<void>;\n}\n\nexport type MarkdownUploadResult = string | UploadedMarkdown | undefined;\n\nexport interface CapturedMarkdownInsertion {\n insert(markdown: string): boolean;\n cancel(): void;\n}\n\n/** Insert through the active visual surface, or fall back to the canonical controller selection. */\nexport function insertMarkdownAtSelection(\n controller: EditorController,\n target: MarkdownInsertionTarget | null | undefined,\n markdown: string,\n selection?: TextSelection,\n): void {\n if (!selection && target?.insertMarkdown(markdown)) return;\n const state = controller.getState();\n const insertionSelection = selection ?? (state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length });\n const from = Math.min(insertionSelection.anchor, insertionSelection.head);\n const to = Math.max(insertionSelection.anchor, insertionSelection.head);\n controller.dispatch(\n new Transaction()\n .replaceSource(from, to, markdown)\n .setSelection({ kind: \"text\", anchor: from + markdown.length, head: from + markdown.length })\n .withSource(\"components:file-insert\"),\n );\n}\n\n/** Keep an asynchronous file insertion anchored to the selection where it started. */\nexport function captureMarkdownInsertion(controller: EditorController, signal?: AbortSignal): CapturedMarkdownInsertion {\n const state = controller.getState();\n let selection: TextSelection = state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length };\n let active = true;\n const unsubscribe = controller.subscribe((change) => {\n if (!active || change.changedRanges.length === 0) return;\n if (change.source.startsWith(\"history:\") && change.changedRanges.some((range) =>\n range.from === 0 && range.to === change.previous.markdown.length && range.insertedLength === change.current.markdown.length\n )) {\n cancel();\n return;\n }\n const mapped = mapSelection(selection, change.changedRanges);\n if (mapped?.kind === \"text\") selection = mapped;\n });\n const cancel = (): void => {\n if (!active) return;\n active = false;\n unsubscribe();\n signal?.removeEventListener(\"abort\", cancel);\n };\n if (signal?.aborted) cancel();\n else signal?.addEventListener(\"abort\", cancel, { once: true });\n return {\n insert(markdown) {\n if (!active) return false;\n cancel();\n insertMarkdownAtSelection(controller, null, markdown, selection);\n return true;\n },\n cancel,\n };\n}\n\n/** Complete an upload and compensate durable assets if canonical insertion fails or is cancelled. */\nexport async function insertUploadedMarkdown(\n insertion: CapturedMarkdownInsertion,\n upload: Promise<MarkdownUploadResult>,\n): Promise<void> {\n const result = await upload;\n if (!result) {\n insertion.cancel();\n return;\n }\n const markdown = typeof result === \"string\" ? result : result.markdown;\n try {\n if (!insertion.insert(markdown)) throw new Error(\"MDFN_MARKDOWN_INSERTION_CANCELLED\");\n } catch (error) {\n if (typeof result !== \"string\") await result.rollback(error);\n throw error;\n }\n}\n\nexport const defaultToolbarGroups: readonly ToolbarGroup[] = Object.freeze([\n { id: \"history\", label: \"History\", actions: [{ id: \"undo\", label: \"Undo\", shortcut: \"Mod-z\" }, { id: \"redo\", label: \"Redo\", shortcut: \"Mod-Shift-z\" }] },\n { id: \"inline\", label: \"Inline formatting\", actions: [{ id: \"bold\", label: \"Bold\", command: \"bold\", shortcut: \"Mod-b\" }, { id: \"italic\", label: \"Italic\", command: \"italic\", shortcut: \"Mod-i\" }, { id: \"code\", label: \"Code\", command: \"inline-code\" }] },\n { id: \"blocks\", label: \"Blocks\", actions: [{ id: \"heading-2\", label: \"Heading\", command: \"heading-2\" }, { id: \"bullet-list\", label: \"Bullet list\", command: \"bullet-list\" }, { id: \"ordered-list\", label: \"Numbered list\", command: \"ordered-list\" }, { id: \"blockquote\", label: \"Quote\", command: \"blockquote\" }, { id: \"code-block\", label: \"Code block\", command: \"code-block\" }] },\n]);\n\nexport interface SlashCommand {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly keywords: readonly string[];\n readonly kind: \"command\" | \"link\" | \"table\" | \"file\" | \"comment\";\n readonly command?: string;\n}\n\nexport const defaultSlashCommands: readonly SlashCommand[] = Object.freeze([\n { id: \"paragraph\", label: \"Paragraph\", description: \"Start a text paragraph\", keywords: [\"text\", \"body\"], kind: \"command\", command: \"paragraph\" },\n { id: \"heading-1\", label: \"Heading 1\", description: \"Insert a top-level heading\", keywords: [\"title\", \"h1\"], kind: \"command\", command: \"heading-1\" },\n { id: \"heading-2\", label: \"Heading 2\", description: \"Insert a section heading\", keywords: [\"subtitle\", \"h2\"], kind: \"command\", command: \"heading-2\" },\n { id: \"bullet-list\", label: \"Bullet list\", description: \"Create an unordered list\", keywords: [\"ul\", \"list\"], kind: \"command\", command: \"bullet-list\" },\n { id: \"ordered-list\", label: \"Numbered list\", description: \"Create an ordered list\", keywords: [\"ol\", \"steps\"], kind: \"command\", command: \"ordered-list\" },\n { id: \"blockquote\", label: \"Quote\", description: \"Create a block quote\", keywords: [\"quote\", \"citation\"], kind: \"command\", command: \"blockquote\" },\n { id: \"code-block\", label: \"Code block\", description: \"Create a fenced code block\", keywords: [\"code\", \"fence\"], kind: \"command\", command: \"code-block\" },\n { id: \"link\", label: \"Link\", description: \"Add or edit a safe link\", keywords: [\"url\", \"href\"], kind: \"link\" },\n { id: \"table\", label: \"Table\", description: \"Insert a table\", keywords: [\"grid\", \"rows\", \"columns\"], kind: \"table\" },\n { id: \"file\", label: \"File or image\", description: \"Select or upload an asset\", keywords: [\"asset\", \"upload\", \"image\"], kind: \"file\" },\n { id: \"comment\", label: \"Comment\", description: \"Comment on the current selection\", keywords: [\"review\", \"note\"], kind: \"comment\" },\n]);\n\nexport function filterSlashCommands(query: string, commands: readonly SlashCommand[] = defaultSlashCommands): readonly SlashCommand[] {\n const terms = query.toLocaleLowerCase().trim().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return commands;\n return commands.filter((command) => {\n const haystack = [command.label, command.description, command.id, ...command.keywords].join(\" \").toLocaleLowerCase();\n return terms.every((term) => haystack.includes(term));\n });\n}\n\nexport interface OutlineItem {\n readonly id: string;\n readonly level: number;\n readonly text: string;\n readonly from?: number;\n}\n\nfunction plainText(node: MdfnNode): string {\n if (node.type === \"text\" || node.type === \"inlineCode\") return node.text ?? \"\";\n return (node.content ?? []).map(plainText).join(\"\");\n}\n\nexport interface AuthoringModel {\n readonly version: number;\n readonly mode: EditorMode;\n readonly compact: boolean;\n readonly toolbar: ToolbarModel;\n readonly bubble: ToolbarModel;\n readonly floating: ToolbarModel;\n readonly bubbleVisible: boolean;\n readonly floatingVisible: boolean;\n readonly slashOpen: boolean;\n readonly slashCommands: readonly SlashCommand[];\n readonly outline: readonly OutlineItem[];\n readonly diagnostics: readonly MdfnDiagnostic[];\n readonly comments: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"comments\"];\n readonly suggestions: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"suggestions\"];\n readonly reviewState: ReviewState;\n readonly audit: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"audit\"];\n}\n\nexport function createAuthoringModel(\n controller: EditorController,\n options: { readonly mode?: EditorMode; readonly compact?: boolean; readonly slashQuery?: string; readonly slashOpen?: boolean; readonly commandTarget?: ToolbarCommandTarget | null } = {},\n): AuthoringModel {\n const state = controller.getState();\n const selection = state.selection?.kind === \"text\" ? state.selection : null;\n const selectionFrom = selection ? Math.min(selection.anchor, selection.head) : 0;\n const selectionTo = selection ? Math.max(selection.anchor, selection.head) : 0;\n const beforeCaret = selection && selectionFrom === selectionTo ? state.markdown.slice(state.markdown.lastIndexOf(\"\\n\", selectionFrom - 1) + 1, selectionFrom) : \"\";\n const slashMatch = /^\\s*\\/([^\\s/]*)$/.exec(beforeCaret);\n const inlineGroups = defaultToolbarGroups.filter((group) => group.id === \"inline\");\n const blockGroups = defaultToolbarGroups.filter((group) => group.id === \"blocks\");\n return {\n version: state.version,\n mode: options.mode ?? \"visual\",\n compact: options.compact ?? false,\n toolbar: createToolbarModel(controller, defaultToolbarGroups, \"Markdown authoring toolbar\", options.commandTarget),\n bubble: createToolbarModel(controller, inlineGroups, \"Selection formatting\", options.commandTarget),\n floating: createToolbarModel(controller, blockGroups, \"Block formatting\", options.commandTarget),\n bubbleVisible: Boolean(selection && selectionFrom !== selectionTo),\n floatingVisible: Boolean(selection && selectionFrom === selectionTo),\n slashOpen: options.slashOpen === true || Boolean(slashMatch),\n slashCommands: filterSlashCommands(options.slashQuery ?? slashMatch?.[1] ?? \"\"),\n outline: state.document.content.flatMap((node, index) => node.type === \"heading\" ? [{ id: node.id ?? `heading-${index}`, level: typeof node.attrs?.level === \"number\" ? node.attrs.level : 1, text: plainText(node), from: node.source?.from }] : []),\n diagnostics: state.diagnostics,\n comments: state.sidecar?.comments ?? [],\n suggestions: state.sidecar?.suggestions ?? [],\n reviewState: state.sidecar?.reviewState ?? \"draft\",\n audit: state.sidecar?.audit ?? [],\n };\n}\n\n/** Framework-neutral version descriptor used by every authoring adapter. */\nexport interface AuthoringVersion {\n readonly version: number;\n readonly createdAt?: string;\n readonly authorId?: string;\n readonly changeSource?: string;\n}\n\nexport function createToolbarModel(controller: EditorController, groups: readonly ToolbarGroup[] = defaultToolbarGroups, ariaLabel = \"Markdown formatting\", commandTarget?: ToolbarCommandTarget | null): ToolbarModel {\n const canRun = (command: string): boolean => commandTarget?.can?.(command) ?? controller.can(command);\n return {\n ariaLabel,\n groups: groups.map((group) => ({\n ...group,\n actions: group.actions.map((action) => ({\n ...action,\n disabled: action.id === \"undo\" ? !(commandTarget?.can?.(\"undo\") ?? controller.canUndo()) : action.id === \"redo\" ? !(commandTarget?.can?.(\"redo\") ?? controller.canRedo()) : action.command ? !canRun(action.command) : action.disabled,\n })),\n })),\n };\n}\n\nexport function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean {\n if (action.disabled) return false;\n if (commandTarget) return commandTarget.run(action.command ?? action.id);\n if (action.id === \"undo\") return controller.undo();\n if (action.id === \"redo\") return controller.redo();\n return action.command ? controller.run(action.command) : false;\n}\n\nexport const MDFN_COMPONENTS_VERSION = \"0.1.1\" as const;\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -91,6 +91,6 @@ interface AuthoringVersion {
|
|
|
91
91
|
}
|
|
92
92
|
declare function createToolbarModel(controller: EditorController, groups?: readonly ToolbarGroup[], ariaLabel?: string, commandTarget?: ToolbarCommandTarget | null): ToolbarModel;
|
|
93
93
|
declare function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean;
|
|
94
|
-
declare const MDFN_COMPONENTS_VERSION: "0.1.
|
|
94
|
+
declare const MDFN_COMPONENTS_VERSION: "0.1.1";
|
|
95
95
|
|
|
96
96
|
export { type AuthoringModel, type AuthoringVersion, type CapturedMarkdownInsertion, type EditorMode, MDFN_COMPONENTS_VERSION, type MarkdownInsertionTarget, type MarkdownUploadResult, type OutlineItem, type SlashCommand, type ToolbarAction, type ToolbarCommandTarget, type ToolbarGroup, type ToolbarModel, type UploadedMarkdown, captureMarkdownInsertion, createAuthoringModel, createToolbarModel, defaultSlashCommands, defaultToolbarGroups, filterSlashCommands, insertMarkdownAtSelection, insertUploadedMarkdown, runToolbarAction };
|
package/dist/index.d.ts
CHANGED
|
@@ -91,6 +91,6 @@ interface AuthoringVersion {
|
|
|
91
91
|
}
|
|
92
92
|
declare function createToolbarModel(controller: EditorController, groups?: readonly ToolbarGroup[], ariaLabel?: string, commandTarget?: ToolbarCommandTarget | null): ToolbarModel;
|
|
93
93
|
declare function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean;
|
|
94
|
-
declare const MDFN_COMPONENTS_VERSION: "0.1.
|
|
94
|
+
declare const MDFN_COMPONENTS_VERSION: "0.1.1";
|
|
95
95
|
|
|
96
96
|
export { type AuthoringModel, type AuthoringVersion, type CapturedMarkdownInsertion, type EditorMode, MDFN_COMPONENTS_VERSION, type MarkdownInsertionTarget, type MarkdownUploadResult, type OutlineItem, type SlashCommand, type ToolbarAction, type ToolbarCommandTarget, type ToolbarGroup, type ToolbarModel, type UploadedMarkdown, captureMarkdownInsertion, createAuthoringModel, createToolbarModel, defaultSlashCommands, defaultToolbarGroups, filterSlashCommands, insertMarkdownAtSelection, insertUploadedMarkdown, runToolbarAction };
|
package/dist/index.js
CHANGED
|
@@ -135,7 +135,7 @@ function runToolbarAction(controller, action, commandTarget) {
|
|
|
135
135
|
if (action.id === "redo") return controller.redo();
|
|
136
136
|
return action.command ? controller.run(action.command) : false;
|
|
137
137
|
}
|
|
138
|
-
var MDFN_COMPONENTS_VERSION = "0.1.
|
|
138
|
+
var MDFN_COMPONENTS_VERSION = "0.1.1";
|
|
139
139
|
export {
|
|
140
140
|
MDFN_COMPONENTS_VERSION,
|
|
141
141
|
captureMarkdownInsertion,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Transaction, mapSelection, type EditorController, type MdfnDiagnostic, type MdfnNode, type ReviewState, type TextSelection } from \"@mdfn/core\";\n\nexport type EditorMode = \"visual\" | \"source\" | \"split\" | \"preview\" | \"read-only\";\n\nexport interface ToolbarAction {\n readonly id: string;\n readonly label: string;\n readonly command?: string;\n readonly shortcut?: string;\n readonly pressed?: boolean;\n readonly disabled?: boolean;\n}\n\nexport interface ToolbarGroup {\n readonly id: string;\n readonly label: string;\n readonly actions: readonly ToolbarAction[];\n}\n\nexport interface ToolbarModel {\n readonly ariaLabel: string;\n readonly groups: readonly ToolbarGroup[];\n}\n\nexport interface ToolbarCommandTarget {\n can?(command: string): boolean;\n run(command: string): boolean;\n}\n\nexport interface MarkdownInsertionTarget {\n insertMarkdown(markdown: string): boolean;\n}\n\nexport interface UploadedMarkdown {\n readonly markdown: string;\n rollback(cause: unknown): void | Promise<void>;\n}\n\nexport type MarkdownUploadResult = string | UploadedMarkdown | undefined;\n\nexport interface CapturedMarkdownInsertion {\n insert(markdown: string): boolean;\n cancel(): void;\n}\n\n/** Insert through the active visual surface, or fall back to the canonical controller selection. */\nexport function insertMarkdownAtSelection(\n controller: EditorController,\n target: MarkdownInsertionTarget | null | undefined,\n markdown: string,\n selection?: TextSelection,\n): void {\n if (!selection && target?.insertMarkdown(markdown)) return;\n const state = controller.getState();\n const insertionSelection = selection ?? (state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length });\n const from = Math.min(insertionSelection.anchor, insertionSelection.head);\n const to = Math.max(insertionSelection.anchor, insertionSelection.head);\n controller.dispatch(\n new Transaction()\n .replaceSource(from, to, markdown)\n .setSelection({ kind: \"text\", anchor: from + markdown.length, head: from + markdown.length })\n .withSource(\"components:file-insert\"),\n );\n}\n\n/** Keep an asynchronous file insertion anchored to the selection where it started. */\nexport function captureMarkdownInsertion(controller: EditorController, signal?: AbortSignal): CapturedMarkdownInsertion {\n const state = controller.getState();\n let selection: TextSelection = state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length };\n let active = true;\n const unsubscribe = controller.subscribe((change) => {\n if (!active || change.changedRanges.length === 0) return;\n if (change.source.startsWith(\"history:\") && change.changedRanges.some((range) =>\n range.from === 0 && range.to === change.previous.markdown.length && range.insertedLength === change.current.markdown.length\n )) {\n cancel();\n return;\n }\n const mapped = mapSelection(selection, change.changedRanges);\n if (mapped?.kind === \"text\") selection = mapped;\n });\n const cancel = (): void => {\n if (!active) return;\n active = false;\n unsubscribe();\n signal?.removeEventListener(\"abort\", cancel);\n };\n if (signal?.aborted) cancel();\n else signal?.addEventListener(\"abort\", cancel, { once: true });\n return {\n insert(markdown) {\n if (!active) return false;\n cancel();\n insertMarkdownAtSelection(controller, null, markdown, selection);\n return true;\n },\n cancel,\n };\n}\n\n/** Complete an upload and compensate durable assets if canonical insertion fails or is cancelled. */\nexport async function insertUploadedMarkdown(\n insertion: CapturedMarkdownInsertion,\n upload: Promise<MarkdownUploadResult>,\n): Promise<void> {\n const result = await upload;\n if (!result) {\n insertion.cancel();\n return;\n }\n const markdown = typeof result === \"string\" ? result : result.markdown;\n try {\n if (!insertion.insert(markdown)) throw new Error(\"MDFN_MARKDOWN_INSERTION_CANCELLED\");\n } catch (error) {\n if (typeof result !== \"string\") await result.rollback(error);\n throw error;\n }\n}\n\nexport const defaultToolbarGroups: readonly ToolbarGroup[] = Object.freeze([\n { id: \"history\", label: \"History\", actions: [{ id: \"undo\", label: \"Undo\", shortcut: \"Mod-z\" }, { id: \"redo\", label: \"Redo\", shortcut: \"Mod-Shift-z\" }] },\n { id: \"inline\", label: \"Inline formatting\", actions: [{ id: \"bold\", label: \"Bold\", command: \"bold\", shortcut: \"Mod-b\" }, { id: \"italic\", label: \"Italic\", command: \"italic\", shortcut: \"Mod-i\" }, { id: \"code\", label: \"Code\", command: \"inline-code\" }] },\n { id: \"blocks\", label: \"Blocks\", actions: [{ id: \"heading-2\", label: \"Heading\", command: \"heading-2\" }, { id: \"bullet-list\", label: \"Bullet list\", command: \"bullet-list\" }, { id: \"ordered-list\", label: \"Numbered list\", command: \"ordered-list\" }, { id: \"blockquote\", label: \"Quote\", command: \"blockquote\" }, { id: \"code-block\", label: \"Code block\", command: \"code-block\" }] },\n]);\n\nexport interface SlashCommand {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly keywords: readonly string[];\n readonly kind: \"command\" | \"link\" | \"table\" | \"file\" | \"comment\";\n readonly command?: string;\n}\n\nexport const defaultSlashCommands: readonly SlashCommand[] = Object.freeze([\n { id: \"paragraph\", label: \"Paragraph\", description: \"Start a text paragraph\", keywords: [\"text\", \"body\"], kind: \"command\", command: \"paragraph\" },\n { id: \"heading-1\", label: \"Heading 1\", description: \"Insert a top-level heading\", keywords: [\"title\", \"h1\"], kind: \"command\", command: \"heading-1\" },\n { id: \"heading-2\", label: \"Heading 2\", description: \"Insert a section heading\", keywords: [\"subtitle\", \"h2\"], kind: \"command\", command: \"heading-2\" },\n { id: \"bullet-list\", label: \"Bullet list\", description: \"Create an unordered list\", keywords: [\"ul\", \"list\"], kind: \"command\", command: \"bullet-list\" },\n { id: \"ordered-list\", label: \"Numbered list\", description: \"Create an ordered list\", keywords: [\"ol\", \"steps\"], kind: \"command\", command: \"ordered-list\" },\n { id: \"blockquote\", label: \"Quote\", description: \"Create a block quote\", keywords: [\"quote\", \"citation\"], kind: \"command\", command: \"blockquote\" },\n { id: \"code-block\", label: \"Code block\", description: \"Create a fenced code block\", keywords: [\"code\", \"fence\"], kind: \"command\", command: \"code-block\" },\n { id: \"link\", label: \"Link\", description: \"Add or edit a safe link\", keywords: [\"url\", \"href\"], kind: \"link\" },\n { id: \"table\", label: \"Table\", description: \"Insert a table\", keywords: [\"grid\", \"rows\", \"columns\"], kind: \"table\" },\n { id: \"file\", label: \"File or image\", description: \"Select or upload an asset\", keywords: [\"asset\", \"upload\", \"image\"], kind: \"file\" },\n { id: \"comment\", label: \"Comment\", description: \"Comment on the current selection\", keywords: [\"review\", \"note\"], kind: \"comment\" },\n]);\n\nexport function filterSlashCommands(query: string, commands: readonly SlashCommand[] = defaultSlashCommands): readonly SlashCommand[] {\n const terms = query.toLocaleLowerCase().trim().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return commands;\n return commands.filter((command) => {\n const haystack = [command.label, command.description, command.id, ...command.keywords].join(\" \").toLocaleLowerCase();\n return terms.every((term) => haystack.includes(term));\n });\n}\n\nexport interface OutlineItem {\n readonly id: string;\n readonly level: number;\n readonly text: string;\n readonly from?: number;\n}\n\nfunction plainText(node: MdfnNode): string {\n if (node.type === \"text\" || node.type === \"inlineCode\") return node.text ?? \"\";\n return (node.content ?? []).map(plainText).join(\"\");\n}\n\nexport interface AuthoringModel {\n readonly version: number;\n readonly mode: EditorMode;\n readonly compact: boolean;\n readonly toolbar: ToolbarModel;\n readonly bubble: ToolbarModel;\n readonly floating: ToolbarModel;\n readonly bubbleVisible: boolean;\n readonly floatingVisible: boolean;\n readonly slashOpen: boolean;\n readonly slashCommands: readonly SlashCommand[];\n readonly outline: readonly OutlineItem[];\n readonly diagnostics: readonly MdfnDiagnostic[];\n readonly comments: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"comments\"];\n readonly suggestions: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"suggestions\"];\n readonly reviewState: ReviewState;\n readonly audit: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"audit\"];\n}\n\nexport function createAuthoringModel(\n controller: EditorController,\n options: { readonly mode?: EditorMode; readonly compact?: boolean; readonly slashQuery?: string; readonly slashOpen?: boolean; readonly commandTarget?: ToolbarCommandTarget | null } = {},\n): AuthoringModel {\n const state = controller.getState();\n const selection = state.selection?.kind === \"text\" ? state.selection : null;\n const selectionFrom = selection ? Math.min(selection.anchor, selection.head) : 0;\n const selectionTo = selection ? Math.max(selection.anchor, selection.head) : 0;\n const beforeCaret = selection && selectionFrom === selectionTo ? state.markdown.slice(state.markdown.lastIndexOf(\"\\n\", selectionFrom - 1) + 1, selectionFrom) : \"\";\n const slashMatch = /^\\s*\\/([^\\s/]*)$/.exec(beforeCaret);\n const inlineGroups = defaultToolbarGroups.filter((group) => group.id === \"inline\");\n const blockGroups = defaultToolbarGroups.filter((group) => group.id === \"blocks\");\n return {\n version: state.version,\n mode: options.mode ?? \"visual\",\n compact: options.compact ?? false,\n toolbar: createToolbarModel(controller, defaultToolbarGroups, \"Markdown authoring toolbar\", options.commandTarget),\n bubble: createToolbarModel(controller, inlineGroups, \"Selection formatting\", options.commandTarget),\n floating: createToolbarModel(controller, blockGroups, \"Block formatting\", options.commandTarget),\n bubbleVisible: Boolean(selection && selectionFrom !== selectionTo),\n floatingVisible: Boolean(selection && selectionFrom === selectionTo),\n slashOpen: options.slashOpen === true || Boolean(slashMatch),\n slashCommands: filterSlashCommands(options.slashQuery ?? slashMatch?.[1] ?? \"\"),\n outline: state.document.content.flatMap((node, index) => node.type === \"heading\" ? [{ id: node.id ?? `heading-${index}`, level: typeof node.attrs?.level === \"number\" ? node.attrs.level : 1, text: plainText(node), from: node.source?.from }] : []),\n diagnostics: state.diagnostics,\n comments: state.sidecar?.comments ?? [],\n suggestions: state.sidecar?.suggestions ?? [],\n reviewState: state.sidecar?.reviewState ?? \"draft\",\n audit: state.sidecar?.audit ?? [],\n };\n}\n\n/** Framework-neutral version descriptor used by every authoring adapter. */\nexport interface AuthoringVersion {\n readonly version: number;\n readonly createdAt?: string;\n readonly authorId?: string;\n readonly changeSource?: string;\n}\n\nexport function createToolbarModel(controller: EditorController, groups: readonly ToolbarGroup[] = defaultToolbarGroups, ariaLabel = \"Markdown formatting\", commandTarget?: ToolbarCommandTarget | null): ToolbarModel {\n const canRun = (command: string): boolean => commandTarget?.can?.(command) ?? controller.can(command);\n return {\n ariaLabel,\n groups: groups.map((group) => ({\n ...group,\n actions: group.actions.map((action) => ({\n ...action,\n disabled: action.id === \"undo\" ? !(commandTarget?.can?.(\"undo\") ?? controller.canUndo()) : action.id === \"redo\" ? !(commandTarget?.can?.(\"redo\") ?? controller.canRedo()) : action.command ? !canRun(action.command) : action.disabled,\n })),\n })),\n };\n}\n\nexport function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean {\n if (action.disabled) return false;\n if (commandTarget) return commandTarget.run(action.command ?? action.id);\n if (action.id === \"undo\") return controller.undo();\n if (action.id === \"redo\") return controller.redo();\n return action.command ? controller.run(action.command) : false;\n}\n\nexport const MDFN_COMPONENTS_VERSION = \"0.1.0\" as const;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Transaction, mapSelection, type EditorController, type MdfnDiagnostic, type MdfnNode, type ReviewState, type TextSelection } from \"@mdfn/core\";\n\nexport type EditorMode = \"visual\" | \"source\" | \"split\" | \"preview\" | \"read-only\";\n\nexport interface ToolbarAction {\n readonly id: string;\n readonly label: string;\n readonly command?: string;\n readonly shortcut?: string;\n readonly pressed?: boolean;\n readonly disabled?: boolean;\n}\n\nexport interface ToolbarGroup {\n readonly id: string;\n readonly label: string;\n readonly actions: readonly ToolbarAction[];\n}\n\nexport interface ToolbarModel {\n readonly ariaLabel: string;\n readonly groups: readonly ToolbarGroup[];\n}\n\nexport interface ToolbarCommandTarget {\n can?(command: string): boolean;\n run(command: string): boolean;\n}\n\nexport interface MarkdownInsertionTarget {\n insertMarkdown(markdown: string): boolean;\n}\n\nexport interface UploadedMarkdown {\n readonly markdown: string;\n rollback(cause: unknown): void | Promise<void>;\n}\n\nexport type MarkdownUploadResult = string | UploadedMarkdown | undefined;\n\nexport interface CapturedMarkdownInsertion {\n insert(markdown: string): boolean;\n cancel(): void;\n}\n\n/** Insert through the active visual surface, or fall back to the canonical controller selection. */\nexport function insertMarkdownAtSelection(\n controller: EditorController,\n target: MarkdownInsertionTarget | null | undefined,\n markdown: string,\n selection?: TextSelection,\n): void {\n if (!selection && target?.insertMarkdown(markdown)) return;\n const state = controller.getState();\n const insertionSelection = selection ?? (state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length });\n const from = Math.min(insertionSelection.anchor, insertionSelection.head);\n const to = Math.max(insertionSelection.anchor, insertionSelection.head);\n controller.dispatch(\n new Transaction()\n .replaceSource(from, to, markdown)\n .setSelection({ kind: \"text\", anchor: from + markdown.length, head: from + markdown.length })\n .withSource(\"components:file-insert\"),\n );\n}\n\n/** Keep an asynchronous file insertion anchored to the selection where it started. */\nexport function captureMarkdownInsertion(controller: EditorController, signal?: AbortSignal): CapturedMarkdownInsertion {\n const state = controller.getState();\n let selection: TextSelection = state.selection?.kind === \"text\"\n ? state.selection\n : { kind: \"text\", anchor: state.markdown.length, head: state.markdown.length };\n let active = true;\n const unsubscribe = controller.subscribe((change) => {\n if (!active || change.changedRanges.length === 0) return;\n if (change.source.startsWith(\"history:\") && change.changedRanges.some((range) =>\n range.from === 0 && range.to === change.previous.markdown.length && range.insertedLength === change.current.markdown.length\n )) {\n cancel();\n return;\n }\n const mapped = mapSelection(selection, change.changedRanges);\n if (mapped?.kind === \"text\") selection = mapped;\n });\n const cancel = (): void => {\n if (!active) return;\n active = false;\n unsubscribe();\n signal?.removeEventListener(\"abort\", cancel);\n };\n if (signal?.aborted) cancel();\n else signal?.addEventListener(\"abort\", cancel, { once: true });\n return {\n insert(markdown) {\n if (!active) return false;\n cancel();\n insertMarkdownAtSelection(controller, null, markdown, selection);\n return true;\n },\n cancel,\n };\n}\n\n/** Complete an upload and compensate durable assets if canonical insertion fails or is cancelled. */\nexport async function insertUploadedMarkdown(\n insertion: CapturedMarkdownInsertion,\n upload: Promise<MarkdownUploadResult>,\n): Promise<void> {\n const result = await upload;\n if (!result) {\n insertion.cancel();\n return;\n }\n const markdown = typeof result === \"string\" ? result : result.markdown;\n try {\n if (!insertion.insert(markdown)) throw new Error(\"MDFN_MARKDOWN_INSERTION_CANCELLED\");\n } catch (error) {\n if (typeof result !== \"string\") await result.rollback(error);\n throw error;\n }\n}\n\nexport const defaultToolbarGroups: readonly ToolbarGroup[] = Object.freeze([\n { id: \"history\", label: \"History\", actions: [{ id: \"undo\", label: \"Undo\", shortcut: \"Mod-z\" }, { id: \"redo\", label: \"Redo\", shortcut: \"Mod-Shift-z\" }] },\n { id: \"inline\", label: \"Inline formatting\", actions: [{ id: \"bold\", label: \"Bold\", command: \"bold\", shortcut: \"Mod-b\" }, { id: \"italic\", label: \"Italic\", command: \"italic\", shortcut: \"Mod-i\" }, { id: \"code\", label: \"Code\", command: \"inline-code\" }] },\n { id: \"blocks\", label: \"Blocks\", actions: [{ id: \"heading-2\", label: \"Heading\", command: \"heading-2\" }, { id: \"bullet-list\", label: \"Bullet list\", command: \"bullet-list\" }, { id: \"ordered-list\", label: \"Numbered list\", command: \"ordered-list\" }, { id: \"blockquote\", label: \"Quote\", command: \"blockquote\" }, { id: \"code-block\", label: \"Code block\", command: \"code-block\" }] },\n]);\n\nexport interface SlashCommand {\n readonly id: string;\n readonly label: string;\n readonly description: string;\n readonly keywords: readonly string[];\n readonly kind: \"command\" | \"link\" | \"table\" | \"file\" | \"comment\";\n readonly command?: string;\n}\n\nexport const defaultSlashCommands: readonly SlashCommand[] = Object.freeze([\n { id: \"paragraph\", label: \"Paragraph\", description: \"Start a text paragraph\", keywords: [\"text\", \"body\"], kind: \"command\", command: \"paragraph\" },\n { id: \"heading-1\", label: \"Heading 1\", description: \"Insert a top-level heading\", keywords: [\"title\", \"h1\"], kind: \"command\", command: \"heading-1\" },\n { id: \"heading-2\", label: \"Heading 2\", description: \"Insert a section heading\", keywords: [\"subtitle\", \"h2\"], kind: \"command\", command: \"heading-2\" },\n { id: \"bullet-list\", label: \"Bullet list\", description: \"Create an unordered list\", keywords: [\"ul\", \"list\"], kind: \"command\", command: \"bullet-list\" },\n { id: \"ordered-list\", label: \"Numbered list\", description: \"Create an ordered list\", keywords: [\"ol\", \"steps\"], kind: \"command\", command: \"ordered-list\" },\n { id: \"blockquote\", label: \"Quote\", description: \"Create a block quote\", keywords: [\"quote\", \"citation\"], kind: \"command\", command: \"blockquote\" },\n { id: \"code-block\", label: \"Code block\", description: \"Create a fenced code block\", keywords: [\"code\", \"fence\"], kind: \"command\", command: \"code-block\" },\n { id: \"link\", label: \"Link\", description: \"Add or edit a safe link\", keywords: [\"url\", \"href\"], kind: \"link\" },\n { id: \"table\", label: \"Table\", description: \"Insert a table\", keywords: [\"grid\", \"rows\", \"columns\"], kind: \"table\" },\n { id: \"file\", label: \"File or image\", description: \"Select or upload an asset\", keywords: [\"asset\", \"upload\", \"image\"], kind: \"file\" },\n { id: \"comment\", label: \"Comment\", description: \"Comment on the current selection\", keywords: [\"review\", \"note\"], kind: \"comment\" },\n]);\n\nexport function filterSlashCommands(query: string, commands: readonly SlashCommand[] = defaultSlashCommands): readonly SlashCommand[] {\n const terms = query.toLocaleLowerCase().trim().split(/\\s+/).filter(Boolean);\n if (terms.length === 0) return commands;\n return commands.filter((command) => {\n const haystack = [command.label, command.description, command.id, ...command.keywords].join(\" \").toLocaleLowerCase();\n return terms.every((term) => haystack.includes(term));\n });\n}\n\nexport interface OutlineItem {\n readonly id: string;\n readonly level: number;\n readonly text: string;\n readonly from?: number;\n}\n\nfunction plainText(node: MdfnNode): string {\n if (node.type === \"text\" || node.type === \"inlineCode\") return node.text ?? \"\";\n return (node.content ?? []).map(plainText).join(\"\");\n}\n\nexport interface AuthoringModel {\n readonly version: number;\n readonly mode: EditorMode;\n readonly compact: boolean;\n readonly toolbar: ToolbarModel;\n readonly bubble: ToolbarModel;\n readonly floating: ToolbarModel;\n readonly bubbleVisible: boolean;\n readonly floatingVisible: boolean;\n readonly slashOpen: boolean;\n readonly slashCommands: readonly SlashCommand[];\n readonly outline: readonly OutlineItem[];\n readonly diagnostics: readonly MdfnDiagnostic[];\n readonly comments: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"comments\"];\n readonly suggestions: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"suggestions\"];\n readonly reviewState: ReviewState;\n readonly audit: NonNullable<ReturnType<EditorController[\"getState\"]>[\"sidecar\"]>[\"audit\"];\n}\n\nexport function createAuthoringModel(\n controller: EditorController,\n options: { readonly mode?: EditorMode; readonly compact?: boolean; readonly slashQuery?: string; readonly slashOpen?: boolean; readonly commandTarget?: ToolbarCommandTarget | null } = {},\n): AuthoringModel {\n const state = controller.getState();\n const selection = state.selection?.kind === \"text\" ? state.selection : null;\n const selectionFrom = selection ? Math.min(selection.anchor, selection.head) : 0;\n const selectionTo = selection ? Math.max(selection.anchor, selection.head) : 0;\n const beforeCaret = selection && selectionFrom === selectionTo ? state.markdown.slice(state.markdown.lastIndexOf(\"\\n\", selectionFrom - 1) + 1, selectionFrom) : \"\";\n const slashMatch = /^\\s*\\/([^\\s/]*)$/.exec(beforeCaret);\n const inlineGroups = defaultToolbarGroups.filter((group) => group.id === \"inline\");\n const blockGroups = defaultToolbarGroups.filter((group) => group.id === \"blocks\");\n return {\n version: state.version,\n mode: options.mode ?? \"visual\",\n compact: options.compact ?? false,\n toolbar: createToolbarModel(controller, defaultToolbarGroups, \"Markdown authoring toolbar\", options.commandTarget),\n bubble: createToolbarModel(controller, inlineGroups, \"Selection formatting\", options.commandTarget),\n floating: createToolbarModel(controller, blockGroups, \"Block formatting\", options.commandTarget),\n bubbleVisible: Boolean(selection && selectionFrom !== selectionTo),\n floatingVisible: Boolean(selection && selectionFrom === selectionTo),\n slashOpen: options.slashOpen === true || Boolean(slashMatch),\n slashCommands: filterSlashCommands(options.slashQuery ?? slashMatch?.[1] ?? \"\"),\n outline: state.document.content.flatMap((node, index) => node.type === \"heading\" ? [{ id: node.id ?? `heading-${index}`, level: typeof node.attrs?.level === \"number\" ? node.attrs.level : 1, text: plainText(node), from: node.source?.from }] : []),\n diagnostics: state.diagnostics,\n comments: state.sidecar?.comments ?? [],\n suggestions: state.sidecar?.suggestions ?? [],\n reviewState: state.sidecar?.reviewState ?? \"draft\",\n audit: state.sidecar?.audit ?? [],\n };\n}\n\n/** Framework-neutral version descriptor used by every authoring adapter. */\nexport interface AuthoringVersion {\n readonly version: number;\n readonly createdAt?: string;\n readonly authorId?: string;\n readonly changeSource?: string;\n}\n\nexport function createToolbarModel(controller: EditorController, groups: readonly ToolbarGroup[] = defaultToolbarGroups, ariaLabel = \"Markdown formatting\", commandTarget?: ToolbarCommandTarget | null): ToolbarModel {\n const canRun = (command: string): boolean => commandTarget?.can?.(command) ?? controller.can(command);\n return {\n ariaLabel,\n groups: groups.map((group) => ({\n ...group,\n actions: group.actions.map((action) => ({\n ...action,\n disabled: action.id === \"undo\" ? !(commandTarget?.can?.(\"undo\") ?? controller.canUndo()) : action.id === \"redo\" ? !(commandTarget?.can?.(\"redo\") ?? controller.canRedo()) : action.command ? !canRun(action.command) : action.disabled,\n })),\n })),\n };\n}\n\nexport function runToolbarAction(controller: EditorController, action: ToolbarAction, commandTarget?: ToolbarCommandTarget | null): boolean {\n if (action.disabled) return false;\n if (commandTarget) return commandTarget.run(action.command ?? action.id);\n if (action.id === \"undo\") return controller.undo();\n if (action.id === \"redo\") return controller.redo();\n return action.command ? controller.run(action.command) : false;\n}\n\nexport const MDFN_COMPONENTS_VERSION = \"0.1.1\" as const;\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdfn/components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Framework-neutral editor toolbar and chrome models for mdfn",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./styles.css": "./styles.css"
|
|
16
|
+
},
|
|
10
17
|
"scripts": {
|
|
11
18
|
"build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean",
|
|
12
19
|
"test": "vitest run",
|
|
@@ -14,13 +21,39 @@
|
|
|
14
21
|
"lint": "tsc --noEmit -p tsconfig.json",
|
|
15
22
|
"prepack": "npm run build"
|
|
16
23
|
},
|
|
17
|
-
"dependencies": {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@mdfn/core": "0.1.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@mdfn/markdown": "0.1.1",
|
|
29
|
+
"tsup": "^8.0.0",
|
|
30
|
+
"typescript": "^5.3.0",
|
|
31
|
+
"vitest": "3.2.4"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"styles.css",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"sideEffects": [
|
|
39
|
+
"styles.css"
|
|
40
|
+
],
|
|
21
41
|
"license": "MIT",
|
|
22
|
-
"engines": {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20 <25"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/21nCo/superfunctions.git",
|
|
48
|
+
"directory": "mdfn/components"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"mdfn": {
|
|
54
|
+
"status": "stable-candidate",
|
|
55
|
+
"layer": "components",
|
|
56
|
+
"schemaVersion": 1
|
|
57
|
+
},
|
|
58
|
+
"gitHead": "699d9d09932199d660333c57fe7bc646492ea3bf"
|
|
26
59
|
}
|