From e67ddcfe6f144e40fdf651c342b3defda6e8373e Mon Sep 17 00:00:00 2001 From: ocavue Date: Sun, 6 Aug 2023 16:39:02 +0800 Subject: [PATCH] feat: warn for marks with `inclusive` as true (#19) --- README.md | 22 +++++++++++++++++++--- playground/index.html | 3 +-- playground/main.ts | 12 ++++++++++-- src/index.ts | 31 ++++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9758c8f..572821a 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,31 @@ npm install prosemirror-virtual-cursor ## Usage ```ts -import 'prosemirror-virtual-cursor/style/virtual-cursor.css' +import 'prosemirror-virtual-cursor/style/virtual-cursor.css'; -import { createVirtualCursor } from 'prosemirror-virtual-cursor' +import { createVirtualCursor } from 'prosemirror-virtual-cursor'; -const plugin = createVirtualCursor() +const plugin = createVirtualCursor(); ``` +## Options + +### Cursor color + The default color of the cursor is red. You can change it by overriding the CSS variable `--prosemirror-virtual-cursor-color`. You can also copy all the CSS rules from `style/virtual-cursor.css` to your own stylesheet and change more things. +### `skipWarning` + +By default, prosemirror-virtual-cursor will warn you if any mark has [`inclusive`](https://prosemirror.net/docs/ref/#model.MarkSpec.inclusive) set to `false`, as `inclusive` is not useful for prosemirror-virtual-cursor. You can disable this warning by setting `skipWarning` to `true`. You can also specify an array of mark names to skip the warning for specific marks. + +```ts +const plugin = createVirtualCursor({ skipWarning: true }); +``` + +```ts +const plugin = createVirtualCursor({ skipWarning: ['mark_type_name'] }); +``` + ## License MIT diff --git a/playground/index.html b/playground/index.html index 817dafe..8228cca 100644 --- a/playground/index.html +++ b/playground/index.html @@ -12,9 +12,8 @@
diff --git a/playground/main.ts b/playground/main.ts index efe66af..6d48b1c 100644 --- a/playground/main.ts +++ b/playground/main.ts @@ -15,9 +15,17 @@ import { exampleSetup } from 'prosemirror-example-setup'; import { createVirtualCursor } from '../src/index'; +const { marks, nodes } = schema.spec; + +marks.forEach((_key, value) => { + if (value.inclusive === false) { + value.inclusive = true; + } +}); + const demoSchema = new Schema({ - nodes: addListNodes(schema.spec.nodes as any, 'paragraph block*', 'block'), - marks: schema.spec.marks, + nodes: addListNodes(nodes, 'paragraph block*', 'block'), + marks, }); const plugins = [ diff --git a/src/index.ts b/src/index.ts index e93c123..b5506a6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,21 @@ -import type { ResolvedPos } from 'prosemirror-model'; +import type { ResolvedPos, Schema } from 'prosemirror-model'; import { Mark } from 'prosemirror-model'; import type { Selection } from 'prosemirror-state'; import { Plugin, PluginKey, TextSelection } from 'prosemirror-state'; import type { EditorView } from 'prosemirror-view'; import { Decoration, DecorationSet } from 'prosemirror-view'; -export function createVirtualCursor(): Plugin { - const key = new PluginKey('prosemirror-virtual-cursor'); +export interface VirtualCursorOptions { + /** + * An array of ProseMirror mark names that should be ignored when checking the + * [`inclusive`](https://prosemirror.net/docs/ref/#model.MarkSpec.inclusive) + * attribute. You can also set this to `true` to skip the warning altogether. + */ + skipWarning?: string[] | true; +} + +export function createVirtualCursor(options?: VirtualCursorOptions): Plugin { + const skipWarning = options?.skipWarning ?? false; let _cursor: HTMLElement | null = typeof document === 'undefined' ? null : document.createElement('div'); @@ -14,6 +23,10 @@ export function createVirtualCursor(): Plugin { return new Plugin({ key, view: (view) => { + if (skipWarning !== true) { + checkInclusive(view.state.schema, skipWarning || []); + } + const doc = view.dom.ownerDocument; _cursor = _cursor || document.createElement('div'); const cursor = _cursor; @@ -122,6 +135,8 @@ export function createVirtualCursor(): Plugin { }); } +const key = new PluginKey('prosemirror-virtual-cursor'); + function getCursorRect( view: EditorView, toStart: boolean @@ -208,3 +223,13 @@ function restartAnimation(element: HTMLElement, className: string) { // -> and re-adding the class element.classList.add(className); } + +function checkInclusive(schema: Schema, skipWarning: string[]) { + for (const [mark, type] of Object.entries(schema.marks)) { + if (type.spec.inclusive === false && !skipWarning.includes(mark)) { + console.warn( + `[prosemirror-virtual-cursor] Virtual cursor does not work well with marks that have inclusive set to false. Please consider removing the inclusive option from the "${mark}" mark or adding it to the "skipWarning" option.` + ); + } + } +}