Socket
Socket
Sign inDemoInstall

prosemirror-suggest

Package Overview
Dependencies
Maintainers
2
Versions
273
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prosemirror-suggest - npm Package Compare versions

Comparing version 0.0.0-pr2169.2 to 0.0.0-pr2222.1

dist/prosemirror-suggest.d.mts

1196

dist/prosemirror-suggest.d.ts

@@ -1,70 +0,1126 @@

export { addSuggester } from './_tsup-dts-rollup';
export { getSuggestPluginState } from './_tsup-dts-rollup';
export { ignoreUpdateForSuggest } from './_tsup-dts-rollup';
export { removeSuggester } from './_tsup-dts-rollup';
export { suggest } from './_tsup-dts-rollup';
export { isChangeReason } from './_tsup-dts-rollup';
export { isExitReason } from './_tsup-dts-rollup';
export { isInvalidSplitReason } from './_tsup-dts-rollup';
export { isJumpReason } from './_tsup-dts-rollup';
export { isRemovedReason } from './_tsup-dts-rollup';
export { isSelectionChangeReason } from './_tsup-dts-rollup';
export { isSelectionExitReason } from './_tsup-dts-rollup';
export { isSplitReason } from './_tsup-dts-rollup';
export { isValidMatch } from './_tsup-dts-rollup';
export { selectionOutsideMatch } from './_tsup-dts-rollup';
export { SuggestState } from './_tsup-dts-rollup';
export { createRegexFromSuggester } from './_tsup-dts-rollup';
export { DEFAULT_SUGGESTER } from './_tsup-dts-rollup';
export { findFromSuggesters } from './_tsup-dts-rollup';
export { getSuggesterWithDefaults } from './_tsup-dts-rollup';
export { IGNORE_SUGGEST_META_KEY } from './_tsup-dts-rollup';
export { markActiveInRange } from './_tsup-dts-rollup';
export { positionHasMarks } from './_tsup-dts-rollup';
export { rangeHasMarks } from './_tsup-dts-rollup';
export { Suggester } from './_tsup-dts-rollup';
export { CheckNextValidSelection } from './_tsup-dts-rollup';
export { ShouldDisableDecorations } from './_tsup-dts-rollup';
export { ExitReason } from './_tsup-dts-rollup';
export { ChangeReason } from './_tsup-dts-rollup';
export { AddIgnoredProps } from './_tsup-dts-rollup';
export { RemoveIgnoredProps } from './_tsup-dts-rollup';
export { SuggestIgnoreProps } from './_tsup-dts-rollup';
export { MatchValue } from './_tsup-dts-rollup';
export { RangeWithCursor } from './_tsup-dts-rollup';
export { ResolvedRangeWithCursor } from './_tsup-dts-rollup';
export { SuggestMatch } from './_tsup-dts-rollup';
export { DocChangedProps } from './_tsup-dts-rollup';
export { SuggestStateMatchProps } from './_tsup-dts-rollup';
export { SuggestMarkProps } from './_tsup-dts-rollup';
export { ReasonProps } from './_tsup-dts-rollup';
export { SuggestChangeHandlerProps } from './_tsup-dts-rollup';
export { SuggestChangeHandler } from './_tsup-dts-rollup';
export { SuggesterProps } from './_tsup-dts-rollup';
export { SuggestMatchWithReason } from './_tsup-dts-rollup';
export { SuggestReasonMap } from './_tsup-dts-rollup';
export { ReasonMatchProps } from './_tsup-dts-rollup';
export { CompareMatchProps } from './_tsup-dts-rollup';
export { MakeOptional } from './_tsup-dts-rollup';
export { EditorSchema } from './_tsup-dts-rollup';
export { ProsemirrorNode } from './_tsup-dts-rollup';
export { Transaction } from './_tsup-dts-rollup';
export { TransactionProps } from './_tsup-dts-rollup';
export { EditorState } from './_tsup-dts-rollup';
export { EditorStateProps } from './_tsup-dts-rollup';
export { ResolvedPos } from './_tsup-dts-rollup';
export { ResolvedPosProps } from './_tsup-dts-rollup';
export { TextProps } from './_tsup-dts-rollup';
export { EditorView } from './_tsup-dts-rollup';
export { EditorViewProps } from './_tsup-dts-rollup';
export { SelectionProps } from './_tsup-dts-rollup';
export { isChange } from './_tsup-dts-rollup';
export { isIdentical } from './_tsup-dts-rollup';
export { isMove } from './_tsup-dts-rollup';
export { isEntry } from './_tsup-dts-rollup';
export { isExit } from './_tsup-dts-rollup';
export { isJump } from './_tsup-dts-rollup';
export { isTextSelection } from './_tsup-dts-rollup';
export { suggestPluginKey } from './_tsup-dts-rollup';
export { findReason } from './_tsup-dts-rollup';
export { getCharAsRegex } from './_tsup-dts-rollup';
import * as PMState from 'prosemirror-state';
import { Selection, TextSelection, Plugin } from 'prosemirror-state';
import * as PMView from 'prosemirror-view';
import { DecorationSet } from 'prosemirror-view';
import * as PMModel from 'prosemirror-model';
import { PickPartial } from '@remirror/types';
/**
* This [[`Suggester`]] interface defines all the options required to create a
* suggestion within your editor.
*
* @remarks
*
* The options are passed to the [[`suggest`]] method which uses them.
*/
interface Suggester {
/**
* The activation character(s) to match against.
*
* @remarks
*
* For example if building a mention plugin you might want to set this to `@`.
* Multi string characters are theoretically supported (although currently
* untested).
*
* The character does not have to be unique amongst the suggesters and the
* eventually matched suggester will depend on the order in which the
* suggesters are added to the plugin.
*
* Please note that when this is a plain string, it is assumed to be a plain
* string. Which means that it will be matched as it is and **not** as a
* string representation of `RegExp`.
*
* It can also be regex, but the regex support has a few caveats.
*
* - All flags specified will be ignored.
* - Avoid using `^` to denote the start of line since that can conflict with
* the [[`Suggester.startOfLine`]] value and cause an invalid regex.
*/
char: RegExp | string;
/**
* A unique identifier for the suggester.
*
* @remarks
*
* This should be globally unique amongst all suggesters registered with this
* plugin. The plugin will throw an error if duplicates names are used.
*
* Typically this value will be appended to classes to uniquely identify them
* amongst the suggesters and even in your own nodes and mark.
*/
name: string;
/**
* Set this to true so that the `onChange` handler is called in the
* `appendTransaction` ProseMirror plugin hook instead of the the view update
* handler.
*
* This tends to work better with updates that are run multiple times while
* preserving the redo/undo history stack.
*
* Please note this should only be set to true if updates are expected to be
* synchronous and immediately available. If you're planning on packaging the
* update into a command which dispatches the update in response to user
* interaction, then you're better off leaving this as false.
*
* An example of how it's being used is in the `autoLink` functionality for
* the `LinkExtension` in remirror. Since autolinking is purely based on
* configuration and not on user interaction it's possible to create the links
* automatically within the `appendTransaction` hook.
*
* @defaultValue false
*/
appendTransaction?: boolean;
/**
* Called whenever a suggester becomes active or changes in any way.
*
* @remarks
*
* It receives a parameters object with the `changeReason` or `exitReason` to
* let you know whether the change was an exit and what caused the change.
*/
onChange: SuggestChangeHandler;
/**
* The priority for this suggester.
*
* A higher number means that this will be added to the list earlier. If
* you're using this within the context of `remirror` you can also use the
* `ExtensionPriority` from the `remirror/core` library.
*
* @defaultValue 50
*/
priority?: number;
/**
* When set to true, matches will only be recognised at the start of a new
* line.
*
* @defaultValue false
*/
startOfLine?: boolean;
/**
* A regex containing all supported characters when within an active
* suggester.
*
* @defaultValue /[\w\d_]+/
*/
supportedCharacters?: RegExp | string;
/**
* A regex expression used to validate the text directly before the match.
*
* @remarks
*
* This will be used when {@link Suggester.invalidPrefixCharacters} is not
* provided.
*
* @defaultValue /^[\s\0]?$/ - translation: only space and zero width characters
* allowed.
*/
validPrefixCharacters?: RegExp | string;
/**
* A regex expression used to invalidate the text directly before the match.
*
* @remarks
*
* This has preference over the `validPrefixCharacters` option and when it is
* defined only it will be looked at in determining whether a prefix is valid.
*
* @defaultValue ''
*/
invalidPrefixCharacters?: RegExp | string | null;
/**
* Sets the characters that need to be present after the initial character
* match before a match is triggered.
*
* @remarks
*
* For example with `char` = `@` the following is true.
*
* - `matchOffset: 0` matches `'@'` immediately
* - `matchOffset: 1` matches `'@a'` but not `'@'`
* - `matchOffset: 2` matches `'@ab'` but not `'@a'` or `'@'`
* - `matchOffset: 3` matches `'@abc'` but not `'@ab'` or `'@a'` or `'@'`
* - And so on...
*
* @defaultValue 0
*/
matchOffset?: number;
/**
* Class name to use for the decoration while the suggester is active.
*
* @defaultValue 'suggest'
*/
suggestClassName?: string;
/**
* Tag for the prosemirror decoration which wraps an active match.
*
* @defaultValue 'span'
*/
suggestTag?: string;
/**
* Set a class for the ignored suggester decoration.
*
* @defaultValue null
*/
ignoredClassName?: string | null;
/**
* Set a tag for the ignored suggester decoration.
*
* @defaultValue 'span'
*/
ignoredTag?: string;
/**
* When true, decorations are not created when this mention is being edited.
*/
disableDecorations?: boolean | ShouldDisableDecorations;
/**
* A list of node names which will be marked as invalid.
*
* @defaultValue []
*/
invalidNodes?: string[];
/**
* A list of node names which will be marked as invalid. This takes priority
* over `invalidNodes` if both properties are present.
*
* Setting this to an empty array would mean that this [[`Suggester`]] can
* never match.
*
* @defaultValue null
*/
validNodes?: string[] | null;
/**
* A list of node names which will be marked as invalid.
*
* @defaultValue []
*/
invalidMarks?: string[];
/**
* A list of node names which will be marked as invalid. This takes priority
* over `invalidMarks` if both properties are present.
*
* By setting this value to the empty array `[]`, you are telling this
* [[`Suggester`]] to never match if any marks are found.
*
* @defaultValue null
*/
validMarks?: string[] | null;
/**
* This is run after the `valid` and `invalid` node and mark checks regardless
* of their outcomes and only when the current suggester has found a match at
* the current position.
*
* It is a method of doing more advanced checking of the resolved position.
* Perhaps checking the attributes on the marks `resolvedRange.$to.marks`, or
* the checking the attributes of the direct parent node
* `resolvedRange.$to.parent.attrs` to check if something is missing.
*/
isValidPosition?: (resolvedRange: ResolvedRangeWithCursor, match: SuggestMatch) => boolean;
/**
* This is a utility option that may be necessary for you when building
* editable mentions using `prosemirror-suggest`.
*
* By default `prosemirror-suggest` searches backwards from the current cursor
* position to see if any text matches any of the configured suggesters. For
* the majority of use cases this is perfectly acceptable behaviour.
*
* However, [#639](https://github.com/remirror/remirror/issues/639) shows that
* it's possible to delete forward and make mentions invalid. Without adding
* this option, the only solution to this problem would have required,
* creating a custom plugin to check each state update and see if the next
* character is still valid.
*
* This method removes this requirement. It is run on every single update
* where there is a valid text selection after the current cursor position. It
* makes use of the `appendTransaction` ProseMirror plugin hook and provides
* you with a transaction (`tr`) which should be mutated with updates. These
* updates are added to the updates for the editor and makes it much easier to
* build `history` friendly functionality.
*
* This is called before all `onChange` handlers.
*
* @defaultValue null
*/
checkNextValidSelection?: CheckNextValidSelection | null;
/**
* Whether this suggester should only be valid for empty selections.
*
* @defaultValue false
*/
emptySelectionsOnly?: boolean;
/**
* Whether the match should be case insensitive and ignore the case. This adds
* the `i` flag to the regex used.
*
* @defaultValue false
*/
caseInsensitive?: boolean;
/**
* When true support matches across multiple lines.
*
* @defaultValue false
*/
multiline?: boolean;
/**
* When true support matches using Unicode Regex.
*
* @defaultValue false
*/
unicode?: boolean;
/**
* Whether to capture the `char character as the first capture group.
*
* When this is set to true it will be the first matching group with
* `match[1]`.
*
* @defaultValue true
*/
captureChar?: boolean;
}
/**
* A function for checking whether the next selection is valid.
*
* It is called for all registered suggesters before any of the onChange
* handlers are fired.
*
* @param $pos - the next valid position that supports text selections.
* @param tr - the transaction that can be mutated when `appendTransaction` is
* set to true.
* @param matches - the possibly undefined exit and change matcher names. These
* can be used to check if the name matches the current suggester.
*/
type CheckNextValidSelection = ($pos: ResolvedPos, tr: Transaction, matches: {
change?: string;
exit?: string;
}) => Transaction | null | void;
/**
* A function that can be used to determine whether the decoration should be set
* or not.
*
* @param match - the current active match
* @param resolvedRange - the range of the match with each position resolved.
*/
type ShouldDisableDecorations = (state: EditorState, match: Readonly<SuggestMatch>) => boolean;
/**
* The potential reasons for an exit of a mention.
*/
declare enum ExitReason {
/**
* The user has pasted some text with multiple characters or run a command
* that adds multiple characters.
*
* `onExit` should be called but the previous match should be retested as it's
* possible that it's been extended.
*/
End = "exit-end",
/**
* The suggestion has been removed.
*/
Removed = "delete",
/**
* The user has pasted some text with multiple characters or run a command
* that adds multiple characters somewhere within the active suggestion. e.g.
* `@abc` -> `@ab123 asdf aiti c`
*
* `onExit` should be called but the previous match should be retested as it's
* possible that it's been extended.
*/
Split = "exit-split",
/**
* The user has pasted some text with multiple characters or run a command
* that adds multiple characters right after the initial multi-character. e.g.
* `@abc` -> `@ this is newabc`
*
* In this case it is best to remove the mention completely.
*/
InvalidSplit = "invalid-exit-split",
/**
* User has moved out of the suggestion at the end. This can happen via using
* arrow keys, but can also be via the suggestion no longer matching as the
* user types, a mouse click or custom command. All that has changed is the
* cursor position.
*/
MoveEnd = "move-end",
/**
* User has moved out of the suggestion but from the beginning. This can be
* via the arrow keys but can also be via a mouse click or custom command. All
* that changed is the cursor position.
*/
MoveStart = "move-start",
/**
* The user has jumped to another suggestion which occurs afterwards in the
* editor. This can be via a click, a keyboard jump or custom commands. In
* this case since there is still an active suggestion it will trigger both an
* `onExit` and `onChange` call.
*/
JumpForward = "jump-forward-exit",
/**
* The user has jumped to another suggestion which occurs before the previous
* suggestion in the editor. This can happen via a click, a keyboard jump
* (END) or a custom command. In this case since there is still an active
* suggestion it will trigger both an `onExit` and `onChange` call.
*/
JumpBackward = "jump-backward-exit",
/**
* The user has selected some text outside the current selection, this can
* trigger an exit. This can be from a triple click to select the line or
* Ctrl-A to select all.
*/
SelectionOutside = "selection-outside"
}
/**
* The potential reason for changes
*/
declare enum ChangeReason {
/**
* The user has entered or started a new suggestion.
*/
Start = "start",
/**
* A changed happened to the character. This can be addition, deletion or
* replacement.
*/
Text = "change-character",
/**
* A change happened to the selection status which was not purely a move. The
* selection area may have been increased.
*/
SelectionInside = "selection-inside",
/**
* The cursor was moved.
*/
Move = "move",
/**
* The user has moved from one suggestion to another suggestion earlier in the
* document.
*/
JumpBackward = "jump-backward-change",
/**
* The user has moved from one suggestion to another suggestion further along
* in the document.
*/
JumpForward = "jump-forward-change"
}
/**
* The parameters needed for the [[`SuggestIgnoreProps.addIgnored`]] action
* method available to the suggest plugin handlers.
*
* @remarks
*
* See:
* - [[`RemoveIgnoredProps`]]
*/
interface AddIgnoredProps extends RemoveIgnoredProps {
/**
* When `false` this will ignore the range for all matching suggesters. When
* true the ignored suggesters will only be the ones provided by the name.
*/
specific?: boolean;
}
/**
* The parameters needed for the {@link SuggestIgnoreProps.removeIgnored}
* action method available to the suggest plugin handlers.
*/
interface RemoveIgnoredProps extends Pick<Suggester, 'name'> {
/**
* The starting point of the match that should be ignored.
*/
from: number;
}
/**
* A parameter builder interface describing the ignore methods available to the
* [[`Suggester`]] handlers.
*/
interface SuggestIgnoreProps {
/**
* Add a match target to the ignored matches.
*
* @remarks
*
* Until the activation character is deleted the `onChange` handler will no
* longer be triggered for the matched character. It will be like the match
* doesn't exist.
*
* By ignoring the activation character the plugin ensures that any further
* matches from the activation character will be ignored.
*
* There are a number of use cases for this. You may chose to ignore a match
* when:
*
* - The user presses the `escape` key to exit your suggestion dropdown.
* - The user continues typing without selecting any of the options for the
* selection drop down.
* - The user clicks outside of the suggesters dropdown.
*
* ```ts
* const suggester = {
* onChange: ({ addIgnored, range: { from }, suggester: { char, name } }: SuggestExitHandlerProps) => {
* addIgnored({ from, char, name }); // Ignore this suggester
* },
* }
* ```
*/
addIgnored: (props: AddIgnoredProps) => void;
/**
* When the name is provided remove all ignored decorations which match the
* named suggester. Otherwise remove **all** ignored decorations from the
* document.
*/
clearIgnored: (name?: string) => void;
/**
* Use this method to skip the next `onChange` when the reason is an exit.
*
* @remarks
*
* This is useful when you manually call a command which applies the
* suggestion outside of the `onChange` handler. When that happens `onChange`
* will still be triggered since the document has now changed. If you don't
* have the logic set up properly it may rerun your exit logic. This can lead
* to mismatched transaction errors since the `onChange` handler is provided
* the last active range and query when the reason is an exit, but these
* values are probably no longer valid.
*
* This helper method can be applied to make life easier. Call it when running
* a command in a click handler or key binding and you don't have to worry
* about your `onChange` handler being called again and leading to a
* mismatched transaction error.
*/
ignoreNextExit: () => void;
}
/**
* The match value with the full and partial text.
*
* @remarks
*
* For a suggester with a char `@` then the following text `@ab|c` where `|` is
* the current cursor position will create a queryText with the following
* signature.
*
* ```json
* { "full": "abc", "partial": "ab" }
* ```
*/
interface MatchValue {
/**
* The complete match independent of the cursor position.
*/
full: string;
/**
* This value is a partial match which ends at the position of the cursor
* within the matching text.
*/
partial: string;
}
/**
* A range with the cursor attached.
*
* - `from` - describes the start position of the query, including the
* activation character.
* - `to` - describes the end position of the match, so the point at which there
* is no longer an active suggest.
* - `cursor` describes the cursor potion within that match.
*
* Depending on the use case you can decide which is most important in your
* application.
*
* If you want to replace the whole match regardless of cursor position, then
* `from` and `to` are all that you need.
*
* If you want to split the match and only replace up until the cursor while
* preserving the remaining part of the match, then you can use `from`, `cursor`
* for the initial replacement and then take the value between `cursor` and `to`
* and append it in whatever way you feel works.
*/
interface RangeWithCursor {
/**
* The absolute starting point of the matching string.
*/
from: number;
/**
* The current cursor position, which may not be at the end of the full match.
*/
cursor: number;
/**
* The absolute end of the matching string.
*/
to: number;
}
interface ResolvedRangeWithCursor {
/**
* The absolute starting point of the matching string as a [resolved
* position](https://prosemirror.net/docs/ref/#model.Resolved_Positions).
*/
$from: ResolvedPos;
/**
* The current cursor position as a [resolved
* position](https://prosemirror.net/docs/ref/#model.Resolved_Positions),
* which may not be at the end of the full match.
*/
$cursor: ResolvedPos;
/**
* The absolute end of the matching string as a [resolved
* position](https://prosemirror.net/docs/ref/#model.Resolved_Positions).
*/
$to: ResolvedPos;
}
/**
* Describes the properties of a match which includes range and the text as well
* as information of the suggester that created the match.
*
*/
interface SuggestMatch extends SuggesterProps {
/**
* Range of current match; for example `@foo|bar` (where | is the cursor)
* - `from` is the start (= 0)
* - `to` is cursor position (= 4)
* - `end` is the end of the match (= 7)
*/
range: RangeWithCursor;
/**
* Current query of match which doesn't include the activation character.
*/
query: MatchValue;
/**
* Full text of match including the activation character
*
* @remarks
*
* For a `char` of `'@'` and query of `'awesome'` `text.full` would be
* `'@awesome'`.
*/
text: MatchValue;
/**
* The raw regex match which caused this suggester to be triggered.
*
* - `rawMatch[0]` is always the full match.
* - `rawMatch[1]` is always the matching character (or regex pattern).
*
* To make use of this you can set the [[`Suggester.supportedCharacters`]]
* property to be a regex which included matching capture group segments.
*/
match: RegExpExecArray;
/**
* The text after full match, up until the end of the text block.
*/
textAfter: string;
/**
* The text before the full match, up until the beginning of the node.
*/
textBefore: string;
}
interface DocChangedProps {
/**
* - `true` when there was a changed in the editor content.
* - `false` when only the selection changed.
*
* TODO currently unused. Should be used to differentiate between a cursor
* exit using the keyboard navigation and a document update change typing
* invalid character, space, etc...
*/
docChanged: boolean;
}
/**
* A parameter builder interface describing match found by the suggest plugin.
*/
interface SuggestStateMatchProps {
/**
* The match that will be triggered.
*/
match: SuggestMatch;
}
/**
* A special parameter needed when creating editable suggester using prosemirror
* `Marks`. The method should be called when removing a suggestion that was
* identified by a prosemirror `Mark`.
*/
interface SuggestMarkProps {
/**
* When managing suggesters with marks it is possible to remove a mark without
* the change reflecting in the prosemirror state. This method should be used
* when removing a suggestion if you are using prosemirror `Marks` to identify
* the suggestion.
*
* When this method is called, `prosemirror-suggest` will handle the removal
* of the mark in the next state update (during apply).
*/
setMarkRemoved: () => void;
}
/**
* A parameter builder interface indicating the reason the handler was called.
*
* @typeParam Reason - Whether this is change or an exit reason.
*/
interface ReasonProps {
/**
* The reason for the exit. Either this or the change reason must have a
* value.
*/
exitReason?: ExitReason;
/**
* The reason for the change. Either this or change reason must have a value..
*/
changeReason?: ChangeReason;
}
/**
* The parameter passed to the [[`Suggester.onChange`]] method. It the
* properties `changeReason` and `exitReason` which are available depending on
* whether this is an exit or change.
*
* Exactly **ONE** will always be available. Unfortunately that's quite hard to
* model in TypeScript without complicating all dependent types.
*/
interface SuggestChangeHandlerProps extends SuggestMatchWithReason, EditorViewProps, SuggestIgnoreProps, SuggestMarkProps, Pick<Suggester, 'name' | 'char'> {
}
/**
* The type signature of the `onChange` handler method.
*
* @param changeDetails - all the information related to the change that caused
* this to be called.
* @param tr - the transaction that can be updated when `appendTransaction` is
* set to true.
*/
type SuggestChangeHandler = (changeDetails: SuggestChangeHandlerProps, tr: Transaction) => void;
interface SuggesterProps {
/**
* The suggester to use for finding matches.
*/
suggester: Required<Suggester>;
}
/**
* The matching suggester along with the reason, whether it is a `changeReason`
* or an `exitReason`.
*/
interface SuggestMatchWithReason extends SuggestMatch, ReasonProps {
}
/**
* A mapping of the handler matches with their reasons for occurring within the
* suggest state.
*/
interface SuggestReasonMap {
/**
* Change reasons for triggering the change handler.
*/
change?: SuggestMatchWithReason;
/**
* Exit reasons for triggering the change handler.
*/
exit?: SuggestMatchWithReason;
}
/**
* A parameter builder interface which adds the match property.
*
* @remarks
*
* This is used to build parameters for {@link Suggester} handler methods.
*
* @typeParam Reason - Whether this is change or an exit reason.
*/
interface ReasonMatchProps {
/**
* The match with its reason property.
*/
match: SuggestMatchWithReason;
}
/**
* A parameter builder interface which compares the previous and next match.
*
* @remarks
*
* It is used within the codebase to determine the kind of change that has
* occurred (i.e. change or exit see {@link SuggestReasonMap}) and the reason
* for that that change. See {@link ExitReason} {@link ChangeReason}
*/
interface CompareMatchProps {
/**
* The initial match
*/
prev: SuggestMatch;
/**
* The current match
*/
next: SuggestMatch;
}
/**
* Makes specified keys of an interface optional while the rest stay the same.
*/
type MakeOptional<Type extends object, Keys extends keyof Type> = Omit<Type, Keys> & {
[Key in Keys]+?: Type[Key];
};
type EditorSchema = PMModel.Schema;
type ProsemirrorNode = PMModel.Node;
type Transaction = PMState.Transaction;
/**
* A parameter builder interface containing the `tr` property.
*
* @typeParam Schema - the underlying editor schema.
*/
interface TransactionProps {
/**
* The prosemirror transaction
*/
tr: Transaction;
}
type EditorState = PMState.EditorState;
/**
* A parameter builder interface containing the `state` property.
*
* @typeParam Schema - the underlying editor schema.
*/
interface EditorStateProps {
/**
* A snapshot of the prosemirror editor state.
*/
state: EditorState;
}
type ResolvedPos = PMModel.ResolvedPos;
/**
* @typeParam Schema - the underlying editor schema.
*/
interface ResolvedPosProps {
/**
* A prosemirror resolved pos with provides helpful context methods when
* working with a position in the editor.
*
* In prosemirror suggest this always uses the lower bound of the text
* selection.
*/
$pos: ResolvedPos;
}
interface TextProps {
/**
* The text to insert or work with.
*/
text: string;
}
type EditorView = PMView.EditorView;
/**
* A parameter builder interface containing the `view` property.
*
* @typeParam Schema - the underlying editor schema.
*/
interface EditorViewProps {
/**
* An instance of the ProseMirror editor `view`.
*/
view: EditorView;
}
interface SelectionProps {
/**
* The text editor selection
*/
selection: PMState.Selection;
}
/**
* The `prosemirror-suggest` state which manages the list of suggesters.
*/
declare class SuggestState {
#private;
/**
* Create an instance of the SuggestState class.
*/
static create(suggesters: Suggester[]): SuggestState;
/**
* Holds a copy of the view
*/
private view;
/**
* The set of all decorations.
*/
get decorationSet(): DecorationSet;
/**
* True when the most recent change was to remove a mention.
*
* @remarks
*
* This is needed because sometimes removing a prosemirror `Mark` has no
* effect. Hence we need to keep track of whether it's removed and then later
* in the apply step check that a removal has happened and reset the
* `handlerMatches` to prevent an infinite loop.
*/
get removed(): boolean;
/**
* Returns the current active suggester state field if one exists
*/
get match(): Readonly<SuggestMatch> | undefined;
/**
* Create the state for the `prosemirror-suggest` plugin.
*
* @remarks
*
* Each suggester must provide a name value which is globally unique since it
* acts as the identifier.
*
* It is possible to register multiple suggesters with identical `char`
* properties. The matched suggester is based on the specificity of the
* `regex` and the order in which they are passed in. Earlier suggesters are
* prioritized.
*/
constructor(suggesters: Suggester[]);
/**
* Initialize the SuggestState with a view which is stored for use later.
*/
init(view: EditorView): this;
/**
* Sets the removed property to be true.
*
* This is useful when working with marks.
*/
readonly setMarkRemoved: () => void;
/**
* Create the props which should be passed into each action handler
*/
private createProps;
/**
* Check whether the exit callback is valid at this time.
*/
private shouldRunExit;
/**
* Find the next text selection from the current selection.
*/
readonly findNextTextSelection: (selection: Selection) => TextSelection | void;
/**
* Update all the suggesters with the next valid selection. This is called
* within the `appendTransaction` ProseMirror method before any of the change
* handlers are called.
*
* @internal
*/
updateWithNextSelection(tr: Transaction): void;
/**
* Call the `onChange` handlers.
*
* @internal
*/
changeHandler(tr: Transaction, appendTransaction: boolean): void;
/**
* Update the current ignored decorations based on the latest changes to the
* prosemirror document.
*/
private mapIgnoredDecorations;
/**
* This sets the next exit to not trigger the exit reason inside the
* `onChange` callback.
*
* This can be useful when you trigger a command, that exists the suggestion
* match and want to prevent further onChanges from occurring for the
* currently active suggester.
*/
readonly ignoreNextExit: () => void;
/**
* Ignores the match specified. Until the match is deleted no more `onChange`
* handler will be triggered. It will be like the match doesn't exist.
*
* @remarks
*
* All we need to ignore is the match character. This means that any further
* matches from the activation character will be ignored.
*/
readonly addIgnored: ({ from, name, specific }: AddIgnoredProps) => void;
/**
* Removes a single match character from the ignored decorations.
*
* @remarks
*
* After this point event handlers will begin to be called again for the match
* character.
*/
readonly removeIgnored: ({ from, name }: RemoveIgnoredProps) => void;
/**
* Removes all the ignored sections of the document. Once this happens
* suggesters will be able to activate in the previously ignored sections.
*/
readonly clearIgnored: (name?: string) => void;
/**
* Checks whether a match should be ignored.
*
* TODO add logic here to decide whether to ignore a match based on the active
* node, or mark.
*/
private shouldIgnoreMatch;
/**
* Reset the state.
*/
private resetState;
/**
* Update the next state value.
*/
private updateReasons;
/**
* A helper method to check is a match exists for the provided suggester name
* at the provided position.
*/
readonly findMatchAtPosition: ($pos: ResolvedPos, name?: string) => SuggestMatch | undefined;
/**
* Add a new suggest or replace it if it already exists.
*/
addSuggester(suggester: Suggester): () => void;
/**
* Remove a suggester if it exists.
*/
removeSuggester(suggester: Suggester | string): void;
toJSON(): SuggestMatch | undefined;
/**
* Applies updates to the state to be used within the plugins apply method.
*
* @param - params
*/
apply(props: TransactionProps & EditorStateProps): this;
/**
* Handle the decorations which wrap the mention while it is active and not
* yet complete.
*/
createDecorations(state: EditorState): DecorationSet;
/**
* Set that the last change was caused by an appended transaction.
*
* @internal
*/
setLastChangeFromAppend: () => void;
}
/**
* Get the state of the suggest plugin.
*
* @param state - the editor state.
*/
declare function getSuggestPluginState(state: EditorState): SuggestState;
/**
* Add a new suggester or replace it if the name already exists in the existing
* configuration.
*
* Will return a function for disposing of the added suggester.
*/
declare function addSuggester(state: EditorState, suggester: Suggester): () => void;
/**
* Call this method with a transaction to skip the suggest plugin checks for the
* next update.
*
* This can be used for updates that don't need to trigger a recheck of the
* suggest state.
*/
declare function ignoreUpdateForSuggest(tr: Transaction): void;
/**
* Remove a suggester if it exists. Pass in the name or the full suggester
* object.
*/
declare function removeSuggester(state: EditorState, suggester: Suggester | string): void;
/**
* This creates a suggest plugin with all the suggesters that you provide.
*
* The priority of the suggesters is the order in which they are passed into
* this function.
*
* - `const plugin = suggest(two, one, three)` - Here `two` will be checked
* first, then `one` and then `three`.
*
* Only one suggester can match at any given time. The order and specificity of
* the regex parameters help determines which suggester will be active.
*
* @param suggesters - a list of suggesters in the order they should be
* evaluated.
*/
declare function suggest(...suggesters: Suggester[]): Plugin<SuggestState>;
/**
* Check that the passed in value is an [[`ExitReason`]].
*/
declare function isExitReason(value: unknown): value is ExitReason;
/**
* Check that that the passed in value is a [[`ChangeReason`]].
*/
declare function isChangeReason(value: unknown): value is ChangeReason;
declare const selectionExitReasons: readonly [ExitReason.MoveEnd, ExitReason.MoveStart, ExitReason.SelectionOutside, ExitReason.JumpForward, ExitReason.JumpBackward];
/**
* An exit which is caused by a change in the selection and no other change in
* the document.
*/
declare function isSelectionExitReason(value: unknown): value is (typeof selectionExitReasons)[number];
declare const selectionChangeReasons: readonly [ChangeReason.JumpBackward, ChangeReason.JumpForward, ChangeReason.Move, ChangeReason.SelectionInside];
declare function isSelectionChangeReason(value: unknown): value is (typeof selectionChangeReasons)[number];
/**
* Checks that the reason passed is a split reason. This typically means that we
* should default to a partial update / creation of the mention.
*/
declare function isSplitReason(value?: unknown): value is ExitReason.Split;
/**
* Checks that the reason was caused by a split at a point where there is no
* query.
*/
declare function isInvalidSplitReason(value?: unknown): value is ExitReason.InvalidSplit;
/**
* Checks that the reason was caused by a deletion.
*/
declare function isRemovedReason(value?: unknown): value is ExitReason.Removed;
/**
* Checks to see if this is a jump reason.
*/
declare function isJumpReason(map: SuggestReasonMap): map is Required<SuggestReasonMap>;
/**
* True when the match is currently active (i.e. it's query has a value)
*/
declare function isValidMatch(match: SuggestMatch | undefined): match is SuggestMatch;
/**
* True when the current selection is outside the match.
*/
declare function selectionOutsideMatch(props: Partial<SuggestStateMatchProps> & SelectionProps): boolean;
interface FindFromSuggestersProps extends ResolvedPosProps, DocChangedProps {
/**
* The matchers to search through.
*/
suggesters: Array<Required<Suggester>>;
/**
* When `true` the selection is empty.
*/
selectionEmpty: boolean;
}
/**
* Check whether the mark is active anywhere between `$from` and `$end`.
*
* Currently this is not doing exactly what it should. I've decided to be lazy
* and only check the following.
*
* - Do any of the requested marks span the entire range using `rangeHasMarks`?
* - Does the starting position have a mark?
* - Does the cursor have a mark?
* - Does the end position have a mark?
*
* In reality I should also check for each position within the range to see if a
* target mark is active but I won't for now.
*/
declare function markActiveInRange(resolvedRange: Omit<ResolvedRangeWithCursor, '$cursor'>, marks: string[]): boolean;
/**
* Check if the entire matching range `from` the start point all the way through
* `to` the end point, has any of the provided marks that span it.
*/
declare function rangeHasMarks(resolvedRange: Omit<ResolvedRangeWithCursor, '$cursor'>, marks: string[]): boolean;
/**
* Check if the provided position has the given marks.
*/
declare function positionHasMarks($pos: ResolvedPos, marks: string[]): boolean;
/**
* Find a match for the provided matchers.
*/
declare function findFromSuggesters(props: FindFromSuggestersProps): SuggestMatch | undefined;
interface CreateRegExpFromSuggesterProps extends Pick<Required<Suggester>, 'startOfLine' | 'char' | 'supportedCharacters' | 'matchOffset'>, Pick<Suggester, 'multiline' | 'caseInsensitive' | 'captureChar' | 'unicode'> {
}
/**
* Create a regex expression which evaluate matches directly from the suggester
* properties.
*/
declare function createRegexFromSuggester(props: CreateRegExpFromSuggesterProps): RegExp;
/**
* The default value for the suggester.
*/
declare const DEFAULT_SUGGESTER: PickPartial<Suggester>;
/**
* This can be added to the meta data of an update to let the suggestion plugin
* know that it should ignore the update.
*/
declare const IGNORE_SUGGEST_META_KEY = "__ignore_prosemirror_suggest_update__";
/**
* Takes the passed through `suggester` and adds all the missing default values.
*/
declare function getSuggesterWithDefaults(suggester: Suggester): Required<Suggester>;
export { type AddIgnoredProps, ChangeReason, type CheckNextValidSelection, type CompareMatchProps, DEFAULT_SUGGESTER, type DocChangedProps, type EditorSchema, type EditorState, type EditorStateProps, type EditorView, type EditorViewProps, ExitReason, IGNORE_SUGGEST_META_KEY, type MakeOptional, type MatchValue, type ProsemirrorNode, type RangeWithCursor, type ReasonMatchProps, type ReasonProps, type RemoveIgnoredProps, type ResolvedPos, type ResolvedPosProps, type ResolvedRangeWithCursor, type SelectionProps, type ShouldDisableDecorations, type SuggestChangeHandler, type SuggestChangeHandlerProps, type SuggestIgnoreProps, type SuggestMarkProps, type SuggestMatch, type SuggestMatchWithReason, type SuggestReasonMap, SuggestState, type SuggestStateMatchProps, type Suggester, type SuggesterProps, type TextProps, type Transaction, type TransactionProps, addSuggester, createRegexFromSuggester, findFromSuggesters, getSuggestPluginState, getSuggesterWithDefaults, ignoreUpdateForSuggest, isChangeReason, isExitReason, isInvalidSplitReason, isJumpReason, isRemovedReason, isSelectionChangeReason, isSelectionExitReason, isSplitReason, isValidMatch, markActiveInRange, positionHasMarks, rangeHasMarks, removeSuggester, selectionOutsideMatch, suggest };

521

dist/prosemirror-suggest.js

@@ -1,5 +0,5 @@

// src/suggest-plugin.ts
// packages/prosemirror-suggest/src/suggest-plugin.ts
import { Plugin } from "prosemirror-state";
// src/suggest-state.ts
// packages/prosemirror-suggest/src/suggest-state.ts
import { PluginKey, Selection } from "prosemirror-state";

@@ -9,8 +9,8 @@ import { Decoration, DecorationSet } from "prosemirror-view";

// src/suggest-predicates.ts
// packages/prosemirror-suggest/src/suggest-predicates.ts
import { TextSelection } from "prosemirror-state";
import { includes, isObject, isString } from "@remirror/core-helpers";
// src/suggest-types.ts
var ExitReason = /* @__PURE__ */(ExitReason2 => {
// packages/prosemirror-suggest/src/suggest-types.ts
var ExitReason = /* @__PURE__ */ ((ExitReason2) => {
ExitReason2["End"] = "exit-end";

@@ -27,3 +27,3 @@ ExitReason2["Removed"] = "delete";

})(ExitReason || {});
var ChangeReason = /* @__PURE__ */(ChangeReason2 => {
var ChangeReason = /* @__PURE__ */ ((ChangeReason2) => {
ChangeReason2["Start"] = "start";

@@ -38,3 +38,3 @@ ChangeReason2["Text"] = "change-character";

// src/suggest-predicates.ts
// packages/prosemirror-suggest/src/suggest-predicates.ts
function isChange(compare) {

@@ -61,9 +61,18 @@ return !!(compare.prev && compare.next && compare.prev.text.full !== compare.next.text.full);

}
var selectionExitReasons = ["move-end" /* MoveEnd */, "move-start" /* MoveStart */, "selection-outside" /* SelectionOutside */, "jump-forward-exit" /* JumpForward */, "jump-backward-exit" /* JumpBackward */];
var selectionExitReasons = [
"move-end" /* MoveEnd */,
"move-start" /* MoveStart */,
"selection-outside" /* SelectionOutside */,
"jump-forward-exit" /* JumpForward */,
"jump-backward-exit" /* JumpBackward */
];
function isSelectionExitReason(value) {
return includes(selectionExitReasons, value);
}
var selectionChangeReasons = ["jump-backward-change" /* JumpBackward */, "jump-forward-change" /* JumpForward */, "move" /* Move */, "selection-inside" /* SelectionInside */];
var selectionChangeReasons = [
"jump-backward-change" /* JumpBackward */,
"jump-forward-change" /* JumpForward */,
"move" /* Move */,
"selection-inside" /* SelectionInside */
];
function isSelectionChangeReason(value) {

@@ -75,11 +84,8 @@ return includes(selectionChangeReasons, value);

}
function isInvalidSplitReason(value) {
return value === "invalid-exit-split" /* InvalidSplit */;
}
function isRemovedReason(value) {
return value === "delete" /* Removed */;
}
var exitJump = ["jump-backward-exit" /* JumpBackward */, "jump-forward-exit" /* JumpForward */];

@@ -94,6 +100,3 @@ var changeJump = ["jump-backward-change" /* JumpBackward */, "jump-forward-change" /* JumpForward */];

function selectionOutsideMatch(props) {
const {
match,
selection
} = props;
const { match, selection } = props;
return !!match && (selection.from < match.range.from || selection.from > match.range.to);

@@ -105,12 +108,15 @@ }

// src/suggest-utils.ts
// packages/prosemirror-suggest/src/suggest-utils.ts
import escapeStringRegex from "escape-string-regexp";
import { NULL_CHARACTER } from "@remirror/core-constants";
import { findMatches, isEmptyArray, isRegExp, isString as isString2, object, range } from "@remirror/core-helpers";
import {
findMatches,
isEmptyArray,
isRegExp,
isString as isString2,
object,
range
} from "@remirror/core-helpers";
function createMatchWithReason(props) {
const {
match,
changeReason,
exitReason
} = props;
const { match, changeReason, exitReason } = props;
return {

@@ -123,6 +129,3 @@ ...match,

function isPrefixValid(prefix, options) {
const {
invalidPrefixCharacters,
validPrefixCharacters
} = options;
const { invalidPrefixCharacters, validPrefixCharacters } = options;
if (invalidPrefixCharacters) {

@@ -138,11 +141,6 @@ const regex = new RegExp(regexToString(invalidPrefixCharacters));

function findPosition(props) {
const {
text,
regexp,
$pos,
suggester
} = props;
const { text, regexp, $pos, suggester } = props;
const start = $pos.start();
let position;
findMatches(text, regexp).forEach(match => {
findMatches(text, regexp).forEach((match) => {
const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index);

@@ -161,7 +159,3 @@ if (isPrefixValid(matchPrefix, suggester)) {

position = {
range: {
from,
to,
cursor
},
range: { from, to, cursor },
match,

@@ -172,6 +166,3 @@ query: {

},
text: {
partial: fullMatch.slice(0, matchLength),
full: fullMatch
},
text: { partial: fullMatch.slice(0, matchLength), full: fullMatch },
textAfter: $pos.doc.textBetween(to, $pos.end(), NULL_CHARACTER, NULL_CHARACTER),

@@ -187,7 +178,4 @@ textBefore: $pos.doc.textBetween(start, from, NULL_CHARACTER, NULL_CHARACTER),

function findMatch(props) {
const { $pos, suggester } = props;
const {
$pos,
suggester
} = props;
const {
char,

@@ -222,6 +210,3 @@ name,

function recheckMatch(props) {
const {
state,
match
} = props;
const { state, match } = props;
try {

@@ -237,7 +222,3 @@ return findMatch({

function createInsertReason(props) {
const {
prev,
next,
state
} = props;
const { prev, next, state } = props;
if (!next && prev.range.from >= state.doc.nodeSize) {

@@ -251,3 +232,2 @@ return {

}
if (!next || !prev.query.partial) {

@@ -261,123 +241,47 @@ return {

}
if (prev.range.to === next.range.cursor) {
return {
exit: createMatchWithReason({
match: next,
exitReason: "exit-end" /* End */
})
};
return { exit: createMatchWithReason({ match: next, exitReason: "exit-end" /* End */ }) };
}
if (prev.query.partial) {
return {
exit: createMatchWithReason({
match: next,
exitReason: "exit-split" /* Split */
})
};
return { exit: createMatchWithReason({ match: next, exitReason: "exit-split" /* Split */ }) };
}
return {};
}
function findJumpReason(props) {
const {
prev,
next,
state
} = props;
const { prev, next, state } = props;
const value = object();
const updatedPrevious = recheckMatch({
state,
match: prev
});
const {
exit
} = updatedPrevious && updatedPrevious.query.full !== prev.query.full ? createInsertReason({
prev,
next: updatedPrevious,
state
}) : value;
const updatedPrevious = recheckMatch({ state, match: prev });
const { exit } = updatedPrevious && updatedPrevious.query.full !== prev.query.full ? createInsertReason({ prev, next: updatedPrevious, state }) : value;
const isJumpForward = prev.range.from < next.range.from;
if (isJumpForward) {
return {
exit: exit ?? createMatchWithReason({
match: prev,
exitReason: "jump-forward-exit" /* JumpForward */
}),
change: createMatchWithReason({
match: next,
changeReason: "jump-forward-change" /* JumpForward */
})
exit: exit ?? createMatchWithReason({ match: prev, exitReason: "jump-forward-exit" /* JumpForward */ }),
change: createMatchWithReason({ match: next, changeReason: "jump-forward-change" /* JumpForward */ })
};
}
return {
exit: exit ?? createMatchWithReason({
match: prev,
exitReason: "jump-backward-exit" /* JumpBackward */
}),
change: createMatchWithReason({
match: next,
changeReason: "jump-backward-change" /* JumpBackward */
})
exit: exit ?? createMatchWithReason({ match: prev, exitReason: "jump-backward-exit" /* JumpBackward */ }),
change: createMatchWithReason({ match: next, changeReason: "jump-backward-change" /* JumpBackward */ })
};
}
function findExitReason(props) {
const {
match,
state,
$pos
} = props;
const {
selection
} = state;
const updatedPrevious = recheckMatch({
match,
state
});
const { match, state, $pos } = props;
const { selection } = state;
const updatedPrevious = recheckMatch({ match, state });
if (!updatedPrevious || updatedPrevious.text.full !== match.text.full) {
return createInsertReason({
prev: match,
next: updatedPrevious,
state
});
return createInsertReason({ prev: match, next: updatedPrevious, state });
}
if (!selection.empty && (selection.from <= match.range.from || selection.to >= match.range.to)) {
return {
exit: createMatchWithReason({
match,
exitReason: "selection-outside" /* SelectionOutside */
})
};
return { exit: createMatchWithReason({ match, exitReason: "selection-outside" /* SelectionOutside */ }) };
}
if ($pos.pos > match.range.to) {
return {
exit: createMatchWithReason({
match,
exitReason: "move-end" /* MoveEnd */
})
};
return { exit: createMatchWithReason({ match, exitReason: "move-end" /* MoveEnd */ }) };
}
if ($pos.pos <= match.range.from) {
return {
exit: createMatchWithReason({
match,
exitReason: "move-start" /* MoveStart */
})
};
return { exit: createMatchWithReason({ match, exitReason: "move-start" /* MoveStart */ }) };
}
return {};
}
function findReason(props) {
const {
prev,
next,
state,
$pos
} = props;
const { prev, next, state, $pos } = props;
const value = object();

@@ -387,38 +291,19 @@ if (!prev && !next) {

}
const compare = {
prev,
next
};
const compare = { prev, next };
if (isJump(compare)) {
return findJumpReason({
prev: compare.prev,
next: compare.next,
state
});
return findJumpReason({ prev: compare.prev, next: compare.next, state });
}
if (isEntry(compare)) {
return {
change: createMatchWithReason({
match: compare.next,
changeReason: "start" /* Start */
})
change: createMatchWithReason({ match: compare.next, changeReason: "start" /* Start */ })
};
}
if (isExit(compare)) {
return findExitReason({
$pos,
match: compare.prev,
state
});
return findExitReason({ $pos, match: compare.prev, state });
}
if (isChange(compare)) {
return {
change: createMatchWithReason({
match: compare.next,
changeReason: "change-character" /* Text */
})
change: createMatchWithReason({ match: compare.next, changeReason: "change-character" /* Text */ })
};
}
if (isMove(compare)) {

@@ -432,3 +317,2 @@ return {

}
return value;

@@ -446,33 +330,22 @@ }

function markActiveInRange(resolvedRange, marks) {
const {
$from,
$to
} = resolvedRange;
const { $from, $to } = resolvedRange;
if (rangeHasMarks(resolvedRange, marks)) {
return true;
}
return range($from.pos, $to.pos).some(value => positionHasMarks($from.doc.resolve(value), marks));
return range($from.pos, $to.pos).some(
(value) => positionHasMarks($from.doc.resolve(value), marks)
);
}
function rangeHasMarks(resolvedRange, marks) {
const {
$from,
$to
} = resolvedRange;
const setOfMarks = new Set(($from.marksAcross($to) ?? []).map(mark => mark.type.name));
return marks.some(item => setOfMarks.has(item));
const { $from, $to } = resolvedRange;
const setOfMarks = new Set(($from.marksAcross($to) ?? []).map((mark) => mark.type.name));
return marks.some((item) => setOfMarks.has(item));
}
function positionHasMarks($pos, marks) {
const setOfMarks = new Set($pos.marks().map(mark => mark.type.name));
return marks.some(item => setOfMarks.has(item));
const setOfMarks = new Set($pos.marks().map((mark) => mark.type.name));
return marks.some((item) => setOfMarks.has(item));
}
function isPositionValidForSuggester(suggester, resolvedRange) {
const {
$cursor
} = resolvedRange;
const {
validMarks,
validNodes,
invalidMarks,
invalidNodes
} = suggester;
const { $cursor } = resolvedRange;
const { validMarks, validNodes, invalidMarks, invalidNodes } = suggester;
if (!validMarks && !validNodes && isEmptyArray(invalidMarks) && isEmptyArray(invalidNodes)) {

@@ -496,7 +369,3 @@ return true;

function findFromSuggesters(props) {
const {
suggesters,
$pos,
selectionEmpty
} = props;
const { suggesters, $pos, selectionEmpty } = props;
for (const suggester of suggesters) {

@@ -507,6 +376,3 @@ if (suggester.emptySelectionsOnly && !selectionEmpty) {

try {
const match = findMatch({
suggester,
$pos
});
const match = findMatch({ suggester, $pos });
if (!match) {

@@ -523,3 +389,4 @@ continue;

}
} catch {}
} catch {
}
}

@@ -556,3 +423,9 @@ return;

}
return new RegExp(`${getRegexPrefix(startOfLine)}${charRegex}${getRegexSupportedCharacters(supportedCharacters, matchOffset)}`, flags);
return new RegExp(
`${getRegexPrefix(startOfLine)}${charRegex}${getRegexSupportedCharacters(
supportedCharacters,
matchOffset
)}`,
flags
);
}

@@ -586,9 +459,6 @@ var DEFAULT_SUGGESTER = {

function getSuggesterWithDefaults(suggester) {
return {
...DEFAULT_SUGGESTER,
...suggester
};
return { ...DEFAULT_SUGGESTER, ...suggester };
}
// src/suggest-state.ts
// packages/prosemirror-suggest/src/suggest-state.ts
var SuggestState = class _SuggestState {

@@ -703,6 +573,3 @@ /**

createProps(match) {
const {
name,
char
} = match.suggester;
const { name, char } = match.suggester;
return {

@@ -732,3 +599,3 @@ view: this.view,

*/
findNextTextSelection = selection => {
findNextTextSelection = (selection) => {
const doc = selection.$from.doc;

@@ -758,6 +625,3 @@ const pos = Math.min(doc.nodeSize - 2, selection.to + 1);

const exit = this.#handlerMatches.exit?.suggester.name;
suggester.checkNextValidSelection?.(nextSelection.$from, tr, {
change,
exit
});
suggester.checkNextValidSelection?.(nextSelection.$from, tr, { change, exit });
}

@@ -771,6 +635,3 @@ }

changeHandler(tr, appendTransaction) {
const {
change,
exit
} = this.#handlerMatches;
const { change, exit } = this.#handlerMatches;
const match = this.match;

@@ -785,6 +646,3 @@ if (!change && !exit || !isValidMatch(match)) {

}
if (change && exit && isJumpReason({
change,
exit
})) {
if (change && exit && isJumpReason({ change, exit })) {
const exitDetails = this.createProps(exit);

@@ -824,7 +682,3 @@ const changeDetails = this.createProps(change);

const decorations = ignored.find();
const invalid = decorations.filter(({
from,
to,
spec
}) => {
const invalid = decorations.filter(({ from, to, spec }) => {
const charLength = isString3(spec.char) ? spec.char.length : 1;

@@ -858,8 +712,4 @@ if (to - from !== charLength) {

*/
addIgnored = ({
from,
name,
specific = false
}) => {
const suggester = this.#suggesters.find(value => value.name === name);
addIgnored = ({ from, name, specific = false }) => {
const suggester = this.#suggesters.find((value) => value.name === name);
if (!suggester) {

@@ -870,13 +720,9 @@ throw new Error(`No suggester exists for the name provided: ${name}`);

const to = from + offset;
const attributes = suggester.ignoredClassName ? {
class: suggester.ignoredClassName
} : {};
const decoration = Decoration.inline(from, to, {
nodeName: suggester.ignoredTag,
...attributes
}, {
name,
specific,
char: suggester.char
});
const attributes = suggester.ignoredClassName ? { class: suggester.ignoredClassName } : {};
const decoration = Decoration.inline(
from,
to,
{ nodeName: suggester.ignoredTag, ...attributes },
{ name, specific, char: suggester.char }
);
this.#ignored = this.#ignored.add(this.view.state.doc, [decoration]);

@@ -892,7 +738,4 @@ };

*/
removeIgnored = ({
from,
name
}) => {
const suggester = this.#suggesters.find(value => value.name === name);
removeIgnored = ({ from, name }) => {
const suggester = this.#suggesters.find((value) => value.name === name);
if (!suggester) {

@@ -912,3 +755,3 @@ throw new Error(`No suggester exists for the name provided: ${name}`);

*/
clearIgnored = name => {
clearIgnored = (name) => {
if (!name) {

@@ -919,5 +762,3 @@ this.#ignored = DecorationSet.empty;

const decorations = this.#ignored.find();
const decorationsToClear = decorations.filter(({
spec
}) => spec.name === name);
const decorationsToClear = decorations.filter(({ spec }) => spec.name === name);
this.#ignored = this.#ignored.remove(decorationsToClear);

@@ -931,13 +772,5 @@ };

*/
shouldIgnoreMatch({
range: range2,
suggester: {
name
}
}) {
shouldIgnoreMatch({ range: range2, suggester: { name } }) {
const decorations = this.#ignored.find();
const shouldIgnore = decorations.some(({
spec,
from
}) => {
const shouldIgnore = decorations.some(({ spec, from }) => {
if (from !== range2.from) {

@@ -963,22 +796,9 @@ return false;

updateReasons(props) {
const {
$pos,
state
} = props;
const { $pos, state } = props;
const docChanged = this.#docChanged;
const suggesters = this.#suggesters;
const selectionEmpty = state.selection.empty;
const match = isTextSelection(state.selection) ? findFromSuggesters({
suggesters,
$pos,
docChanged,
selectionEmpty
}) : void 0;
const match = isTextSelection(state.selection) ? findFromSuggesters({ suggesters, $pos, docChanged, selectionEmpty }) : void 0;
this.#next = match && this.shouldIgnoreMatch(match) ? void 0 : match;
this.#handlerMatches = findReason({
next: this.#next,
prev: this.#prev,
state,
$pos
});
this.#handlerMatches = findReason({ next: this.#next, prev: this.#prev, state, $pos });
}

@@ -990,9 +810,4 @@ /**

findMatchAtPosition = ($pos, name) => {
const suggesters = name ? this.#suggesters.filter(suggester => suggester.name === name) : this.#suggesters;
return findFromSuggesters({
suggesters,
$pos,
docChanged: false,
selectionEmpty: true
});
const suggesters = name ? this.#suggesters.filter((suggester) => suggester.name === name) : this.#suggesters;
return findFromSuggesters({ suggesters, $pos, docChanged: false, selectionEmpty: true });
};

@@ -1003,6 +818,8 @@ /**

addSuggester(suggester) {
const previous = this.#suggesters.find(item => item.name === suggester.name);
const previous = this.#suggesters.find((item) => item.name === suggester.name);
const mapper = createSuggesterMapper();
if (previous) {
this.#suggesters = this.#suggesters.map(item => item === previous ? mapper(suggester) : item);
this.#suggesters = this.#suggesters.map(
(item) => item === previous ? mapper(suggester) : item
);
} else {

@@ -1019,3 +836,3 @@ const suggesters = [...this.#suggesters, mapper(suggester)];

const name = isString3(suggester) ? suggester : suggester.name;
this.#suggesters = this.#suggesters.filter(item => item.name !== name);
this.#suggesters = this.#suggesters.filter((item) => item.name !== name);
this.clearIgnored(name);

@@ -1032,6 +849,3 @@ }

apply(props) {
const {
exit,
change
} = this.#handlerMatches;
const { exit, change } = this.#handlerMatches;
if (this.#lastChangeFromAppend) {

@@ -1043,6 +857,3 @@ this.#lastChangeFromAppend = false;

}
const {
tr,
state
} = props;
const { tr, state } = props;
const transactionHasChanged = tr.docChanged || tr.selectionSet;

@@ -1059,6 +870,3 @@ const shouldIgnoreUpdate = tr.getMeta(IGNORE_SUGGEST_META_KEY);

this.#prev = this.#next;
this.updateReasons({
$pos: tr.selection.$from,
state
});
this.updateReasons({ $pos: tr.selection.$from, state });
return this;

@@ -1075,5 +883,3 @@ }

}
const {
disableDecorations
} = match.suggester;
const { disableDecorations } = match.suggester;
const shouldSkip = isFunction(disableDecorations) ? disableDecorations(state, match) : disableDecorations;

@@ -1083,21 +889,16 @@ if (shouldSkip) {

}
const {
range: range2,
suggester
} = match;
const {
name,
suggestTag,
suggestClassName
} = suggester;
const {
from,
to
} = range2;
return this.shouldIgnoreMatch(match) ? this.#ignored : this.#ignored.add(state.doc, [Decoration.inline(from, to, {
nodeName: suggestTag,
class: name ? `${suggestClassName} suggest-${name}` : suggestClassName
}, {
name
})]);
const { range: range2, suggester } = match;
const { name, suggestTag, suggestClassName } = suggester;
const { from, to } = range2;
return this.shouldIgnoreMatch(match) ? this.#ignored : this.#ignored.add(state.doc, [
Decoration.inline(
from,
to,
{
nodeName: suggestTag,
class: name ? `${suggestClassName} suggest-${name}` : suggestClassName
},
{ name }
)
]);
}

@@ -1114,11 +915,10 @@ /**

function createSuggesterMapper() {
const names = /* @__PURE__ */new Set();
return suggester => {
const names = /* @__PURE__ */ new Set();
return (suggester) => {
if (names.has(suggester.name)) {
throw new Error(`A suggester already exists with the name '${suggester.name}'. The name provided must be unique.`);
throw new Error(
`A suggester already exists with the name '${suggester.name}'. The name provided must be unique.`
);
}
const suggesterWithDefaults = {
...DEFAULT_SUGGESTER,
...suggester
};
const suggesterWithDefaults = { ...DEFAULT_SUGGESTER, ...suggester };
names.add(suggester.name);

@@ -1130,3 +930,3 @@ return suggesterWithDefaults;

// src/suggest-plugin.ts
// packages/prosemirror-suggest/src/suggest-plugin.ts
function getSuggestPluginState(state) {

@@ -1149,6 +949,6 @@ return suggestPluginKey.getState(state);

// Handle the plugin view
view: view => {
view: (view) => {
pluginState.init(view);
return {
update: view2 => pluginState.changeHandler(view2.state.tr, false)
update: (view2) => pluginState.changeHandler(view2.state.tr, false)
};

@@ -1160,6 +960,3 @@ },

// Apply changes to the state
apply: (tr, _pluginState, _oldState, state) => pluginState.apply({
tr,
state
})
apply: (tr, _pluginState, _oldState, state) => pluginState.apply({ tr, state })
},

@@ -1180,6 +977,32 @@ /** Append a transaction via the onChange handlers */

// decoration
decorations: state => pluginState.createDecorations(state)
decorations: (state) => pluginState.createDecorations(state)
}
});
}
export { ChangeReason, DEFAULT_SUGGESTER, ExitReason, IGNORE_SUGGEST_META_KEY, addSuggester, createRegexFromSuggester, findFromSuggesters, getSuggestPluginState, getSuggesterWithDefaults, ignoreUpdateForSuggest, isChangeReason, isExitReason, isInvalidSplitReason, isJumpReason, isRemovedReason, isSelectionChangeReason, isSelectionExitReason, isSplitReason, isValidMatch, markActiveInRange, positionHasMarks, rangeHasMarks, removeSuggester, selectionOutsideMatch, suggest };
export {
ChangeReason,
DEFAULT_SUGGESTER,
ExitReason,
IGNORE_SUGGEST_META_KEY,
addSuggester,
createRegexFromSuggester,
findFromSuggesters,
getSuggestPluginState,
getSuggesterWithDefaults,
ignoreUpdateForSuggest,
isChangeReason,
isExitReason,
isInvalidSplitReason,
isJumpReason,
isRemovedReason,
isSelectionChangeReason,
isSelectionExitReason,
isSplitReason,
isValidMatch,
markActiveInRange,
positionHasMarks,
rangeHasMarks,
removeSuggester,
selectionOutsideMatch,
suggest
};
{
"name": "prosemirror-suggest",
"version": "0.0.0-pr2169.2",
"version": "0.0.0-pr2222.1",
"description": "Primitives for building your prosemirror suggestion and autocomplete functionality",

@@ -34,12 +34,11 @@ "homepage": "https://github.com/remirror/remirror/tree/HEAD/packages/prosemirror-suggest",

"@babel/runtime": "^7.22.3",
"@remirror/core-constants": "0.0.0-pr2169.2",
"@remirror/core-helpers": "0.0.0-pr2169.2",
"@remirror/types": "0.0.0-pr2169.2",
"@remirror/core-constants": "0.0.0-pr2222.1",
"@remirror/core-helpers": "0.0.0-pr2222.1",
"@remirror/types": "0.0.0-pr2222.1",
"escape-string-regexp": "^4.0.0"
},
"devDependencies": {
"@remirror/cli": "0.0.0-pr2169.2",
"prosemirror-model": "^1.19.3",
"prosemirror-state": "^1.4.3",
"prosemirror-view": "^1.32.3"
"prosemirror-view": "^1.31.7"
},

@@ -49,3 +48,3 @@ "peerDependencies": {

"prosemirror-state": "^1.4.2",
"prosemirror-view": "^1.32.3"
"prosemirror-view": "^1.31.2"
},

@@ -58,6 +57,3 @@ "peerDependenciesMeta": {},

"sizeLimit": "10 KB"
},
"scripts": {
"build": "remirror-cli build"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc