@atlaskit/prosemirror-input-rules 2.1.7 → 2.1.9
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/CHANGELOG.md +13 -0
- package/dist/cjs/handler.js +12 -2
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/handler.js +11 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/handler.js +11 -2
- package/dist/esm/version.json +1 -1
- package/package.json +8 -5
- package/report.api.md +39 -14
- package/src/handler.ts +69 -54
- package/src/plugin.ts +2 -4
- package/tsconfig.json +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @atlaskit/prosemirror-input-rules
|
|
2
2
|
|
|
3
|
+
## 2.1.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`0606572f9b8`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0606572f9b8) - [ux] ED-15348 docs(changeset): ED-15348 Fix a bug preventing typeahead actions to be fired from a gap cursor. Typing a typeahead trigger key (/, : or @) should pop-up a typeahead menu. However, if the current selection is inside a gap cursor, the trigger character is inserted and the pop-up menu doesn't open. This changeset fixes that.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
|
|
10
|
+
## 2.1.8
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
|
|
3
16
|
## 2.1.7
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/cjs/handler.js
CHANGED
|
@@ -9,6 +9,8 @@ exports.createInputEventHandler = void 0;
|
|
|
9
9
|
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
11
|
|
|
12
|
+
var _selection = require("@atlaskit/editor-common/selection");
|
|
13
|
+
|
|
12
14
|
var _constants = require("./constants");
|
|
13
15
|
|
|
14
16
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
@@ -87,8 +89,16 @@ function findMatchOnRules(_ref3) {
|
|
|
87
89
|
state = _ref3.state;
|
|
88
90
|
|
|
89
91
|
for (var i = 0; i < rules.length; i++) {
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
+
var _textBefore$at;
|
|
93
|
+
|
|
94
|
+
var rule = rules[i]; // Some plugins like Typeahead require a whitespace before a trigger character.
|
|
95
|
+
// We want them to fire inside a gap cursor. Yet, a gap cursor is not considered a whitespace,
|
|
96
|
+
// and `textBefore` contains the text in the previous block before the gap cursor.
|
|
97
|
+
// Here is a workaround: if we inside a gap cursor, match the input rule only against the last typed character
|
|
98
|
+
// (which may be a typeahead trigger) and ignore the rest.
|
|
99
|
+
|
|
100
|
+
var matchString = state.selection instanceof _selection.GapCursorSelection ? (_textBefore$at = textBefore.at(-1)) !== null && _textBefore$at !== void 0 ? _textBefore$at : '' : textBefore;
|
|
101
|
+
var match = rule.match.exec(matchString);
|
|
92
102
|
|
|
93
103
|
if (!match) {
|
|
94
104
|
continue;
|
package/dist/cjs/version.json
CHANGED
package/dist/es2019/handler.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
1
2
|
import { leafNodeReplacementCharacter, MAX_REGEX_MATCH, TEXT_INPUT_RULE_TRANSACTION_KEY } from './constants';
|
|
2
3
|
export const createInputEventHandler = ({
|
|
3
4
|
rules,
|
|
@@ -68,8 +69,16 @@ function findMatchOnRules({
|
|
|
68
69
|
state
|
|
69
70
|
}) {
|
|
70
71
|
for (let i = 0; i < rules.length; i++) {
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
var _textBefore$at;
|
|
73
|
+
|
|
74
|
+
const rule = rules[i]; // Some plugins like Typeahead require a whitespace before a trigger character.
|
|
75
|
+
// We want them to fire inside a gap cursor. Yet, a gap cursor is not considered a whitespace,
|
|
76
|
+
// and `textBefore` contains the text in the previous block before the gap cursor.
|
|
77
|
+
// Here is a workaround: if we inside a gap cursor, match the input rule only against the last typed character
|
|
78
|
+
// (which may be a typeahead trigger) and ignore the rest.
|
|
79
|
+
|
|
80
|
+
const matchString = state.selection instanceof GapCursorSelection ? (_textBefore$at = textBefore.at(-1)) !== null && _textBefore$at !== void 0 ? _textBefore$at : '' : textBefore;
|
|
81
|
+
const match = rule.match.exec(matchString);
|
|
73
82
|
|
|
74
83
|
if (!match) {
|
|
75
84
|
continue;
|
package/dist/es2019/version.json
CHANGED
package/dist/esm/handler.js
CHANGED
|
@@ -4,6 +4,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
4
4
|
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
6
|
|
|
7
|
+
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
7
8
|
import { leafNodeReplacementCharacter, MAX_REGEX_MATCH, TEXT_INPUT_RULE_TRANSACTION_KEY } from './constants';
|
|
8
9
|
export var createInputEventHandler = function createInputEventHandler(_ref) {
|
|
9
10
|
var rules = _ref.rules,
|
|
@@ -75,8 +76,16 @@ function findMatchOnRules(_ref3) {
|
|
|
75
76
|
state = _ref3.state;
|
|
76
77
|
|
|
77
78
|
for (var i = 0; i < rules.length; i++) {
|
|
78
|
-
var
|
|
79
|
-
|
|
79
|
+
var _textBefore$at;
|
|
80
|
+
|
|
81
|
+
var rule = rules[i]; // Some plugins like Typeahead require a whitespace before a trigger character.
|
|
82
|
+
// We want them to fire inside a gap cursor. Yet, a gap cursor is not considered a whitespace,
|
|
83
|
+
// and `textBefore` contains the text in the previous block before the gap cursor.
|
|
84
|
+
// Here is a workaround: if we inside a gap cursor, match the input rule only against the last typed character
|
|
85
|
+
// (which may be a typeahead trigger) and ignore the rest.
|
|
86
|
+
|
|
87
|
+
var matchString = state.selection instanceof GapCursorSelection ? (_textBefore$at = textBefore.at(-1)) !== null && _textBefore$at !== void 0 ? _textBefore$at : '' : textBefore;
|
|
88
|
+
var match = rule.match.exec(matchString);
|
|
80
89
|
|
|
81
90
|
if (!match) {
|
|
82
91
|
continue;
|
package/dist/esm/version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/prosemirror-input-rules",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.9",
|
|
4
4
|
"description": "A package that contains helpers to create autoformatting rules for ProseMirror",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"releaseModel": "scheduled"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@atlaskit/editor-common": "^
|
|
22
|
+
"@atlaskit/editor-common": "^71.0.0",
|
|
23
23
|
"@babel/runtime": "^7.0.0",
|
|
24
24
|
"prosemirror-state": "1.3.4"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@atlaskit/adf-schema": "^
|
|
28
|
-
"@atlaskit/editor-test-helpers": "^17.
|
|
27
|
+
"@atlaskit/adf-schema": "^24.0.0",
|
|
28
|
+
"@atlaskit/editor-test-helpers": "^17.2.0",
|
|
29
29
|
"@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
|
|
30
30
|
"@types/prosemirror-history": "^1.0.1",
|
|
31
31
|
"@types/prosemirror-model": "^1.11.0",
|
|
@@ -41,7 +41,10 @@
|
|
|
41
41
|
"import-structure": "atlassian-conventions"
|
|
42
42
|
},
|
|
43
43
|
"@repo/internal": {
|
|
44
|
-
"deprecation": "no-deprecated-imports"
|
|
44
|
+
"deprecation": "no-deprecated-imports",
|
|
45
|
+
"styling": [
|
|
46
|
+
"emotion"
|
|
47
|
+
]
|
|
45
48
|
}
|
|
46
49
|
},
|
|
47
50
|
"af:exports": {
|
package/report.api.md
CHANGED
|
@@ -1,57 +1,82 @@
|
|
|
1
|
+
<!-- API Report Version: 2.2 -->
|
|
2
|
+
|
|
1
3
|
## API Report File for "@atlaskit/prosemirror-input-rules"
|
|
2
4
|
|
|
3
|
-
> Do not edit this file.
|
|
5
|
+
> Do not edit this file. This report is auto-generated using [API Extractor](https://api-extractor.com/).
|
|
6
|
+
> [Learn more about API reports](https://hello.atlassian.net/wiki/spaces/UR/pages/1825484529/Package+API+Reports)
|
|
7
|
+
|
|
8
|
+
### Table of contents
|
|
9
|
+
|
|
10
|
+
- [Main Entry Types](#main-entry-types)
|
|
11
|
+
|
|
12
|
+
### Main Entry Types
|
|
13
|
+
|
|
14
|
+
<!--SECTION START: Main Entry Types-->
|
|
4
15
|
|
|
5
16
|
```ts
|
|
6
17
|
import type { EditorState } from 'prosemirror-state';
|
|
7
18
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
8
19
|
import type { Transaction } from 'prosemirror-state';
|
|
9
20
|
|
|
10
|
-
|
|
21
|
+
// @public (undocumented)
|
|
22
|
+
export function createInputRulePlugin(
|
|
11
23
|
pluginName: string,
|
|
12
24
|
rules: InputRuleWrapper[],
|
|
13
25
|
options?: Options,
|
|
14
26
|
): SafePlugin;
|
|
15
27
|
|
|
16
|
-
|
|
28
|
+
// @public (undocumented)
|
|
29
|
+
export type InputRuleHandler = (
|
|
17
30
|
state: EditorState,
|
|
18
31
|
matchResult: RegExpExecArray,
|
|
19
32
|
start: number,
|
|
20
33
|
end: number,
|
|
21
34
|
) => Transaction | null;
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
// @public (undocumented)
|
|
37
|
+
export interface InputRuleWrapper {
|
|
38
|
+
// (undocumented)
|
|
25
39
|
handler: InputRuleHandler;
|
|
40
|
+
// (undocumented)
|
|
41
|
+
match: RegExp;
|
|
42
|
+
// (undocumented)
|
|
26
43
|
onHandlerApply?: OnHandlerApply;
|
|
27
44
|
}
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
// @public (undocumented)
|
|
47
|
+
export const leafNodeReplacementCharacter = '\uFFFC';
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
// @public (undocumented)
|
|
50
|
+
export const MAX_REGEX_MATCH = 500;
|
|
32
51
|
|
|
33
|
-
|
|
52
|
+
// @public (undocumented)
|
|
53
|
+
type OnBeforeRegexMatch = (tr: Transaction) => void;
|
|
34
54
|
|
|
35
|
-
|
|
55
|
+
// @public (undocumented)
|
|
56
|
+
export type OnHandlerApply = (
|
|
36
57
|
state: EditorState,
|
|
37
58
|
tr: Transaction,
|
|
38
59
|
matchResult: RegExpExecArray,
|
|
39
60
|
) => void;
|
|
40
61
|
|
|
41
|
-
|
|
62
|
+
// @public (undocumented)
|
|
63
|
+
export type OnInputEvent = (props: {
|
|
42
64
|
state: EditorState;
|
|
43
65
|
from: number;
|
|
44
66
|
to: number;
|
|
45
67
|
}) => boolean;
|
|
46
68
|
|
|
47
|
-
|
|
69
|
+
// @public (undocumented)
|
|
70
|
+
type Options = {
|
|
48
71
|
allowInsertTextOnDocument?: boolean;
|
|
49
72
|
onInputEvent?: OnInputEvent;
|
|
50
73
|
onBeforeRegexMatch?: OnBeforeRegexMatch;
|
|
51
74
|
};
|
|
52
75
|
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
// @public (undocumented)
|
|
77
|
+
export const TEXT_INPUT_RULE_TRANSACTION_KEY = 'input_rule_plugin_transaction';
|
|
55
78
|
|
|
56
|
-
|
|
79
|
+
// (No @packageDocumentation comment for this package)
|
|
57
80
|
```
|
|
81
|
+
|
|
82
|
+
<!--SECTION END: Main Entry Types-->
|
package/src/handler.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { EditorState, PluginKey, Transaction } from 'prosemirror-state';
|
|
2
2
|
|
|
3
|
+
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
4
|
+
|
|
3
5
|
import {
|
|
4
6
|
leafNodeReplacementCharacter,
|
|
5
7
|
MAX_REGEX_MATCH,
|
|
@@ -22,65 +24,67 @@ type Options = {
|
|
|
22
24
|
onBeforeRegexMatch?: OnBeforeRegexMatch;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
|
-
export const createInputEventHandler =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
export const createInputEventHandler =
|
|
28
|
+
({
|
|
29
|
+
rules,
|
|
30
|
+
pluginKey,
|
|
31
|
+
allowInsertTextOnDocument,
|
|
32
|
+
onInputEvent,
|
|
33
|
+
onBeforeRegexMatch,
|
|
34
|
+
}: Options): HandleInputEvent =>
|
|
35
|
+
({ view, from, to, text }) => {
|
|
36
|
+
if (view.composing) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
const state = view.state;
|
|
41
|
+
const $from = state.doc.resolve(from);
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
if ($from.parent.type.spec.code) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (onInputEvent && !onInputEvent({ state, from, to })) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
const textBefore =
|
|
51
|
+
$from.parent.textBetween(
|
|
52
|
+
Math.max(0, $from.parentOffset - MAX_REGEX_MATCH),
|
|
53
|
+
$from.parentOffset,
|
|
54
|
+
undefined,
|
|
55
|
+
leafNodeReplacementCharacter,
|
|
56
|
+
) + text;
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!result) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
58
|
+
const result = findMatchOnRules({
|
|
59
|
+
rules,
|
|
60
|
+
textBefore,
|
|
61
|
+
from,
|
|
62
|
+
to,
|
|
63
|
+
state,
|
|
64
|
+
});
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
tr.setMeta(TEXT_INPUT_RULE_TRANSACTION_KEY, true);
|
|
70
|
-
tr.setMeta(pluginKey, {
|
|
71
|
-
textInserted: text,
|
|
72
|
-
from: result.from,
|
|
73
|
-
to: result.to,
|
|
74
|
-
matchedRule: result.matchedRule,
|
|
75
|
-
} as InputRulePluginState);
|
|
76
|
-
|
|
77
|
-
if (onBeforeRegexMatch) {
|
|
78
|
-
onBeforeRegexMatch(tr);
|
|
79
|
-
}
|
|
66
|
+
if (!result) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
80
69
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
const tr = allowInsertTextOnDocument
|
|
71
|
+
? state.tr.insertText(text, from, to)
|
|
72
|
+
: state.tr;
|
|
73
|
+
tr.setMeta(TEXT_INPUT_RULE_TRANSACTION_KEY, true);
|
|
74
|
+
tr.setMeta(pluginKey, {
|
|
75
|
+
textInserted: text,
|
|
76
|
+
from: result.from,
|
|
77
|
+
to: result.to,
|
|
78
|
+
matchedRule: result.matchedRule,
|
|
79
|
+
} as InputRulePluginState);
|
|
80
|
+
|
|
81
|
+
if (onBeforeRegexMatch) {
|
|
82
|
+
onBeforeRegexMatch(tr);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
view.dispatch(tr);
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
84
88
|
|
|
85
89
|
type FindMatchOnRulesProps = {
|
|
86
90
|
rules: InputRuleWrapper[];
|
|
@@ -103,7 +107,18 @@ function findMatchOnRules({
|
|
|
103
107
|
}: FindMatchOnRulesProps): RuleMatchedResult | null {
|
|
104
108
|
for (let i = 0; i < rules.length; i++) {
|
|
105
109
|
const rule = rules[i];
|
|
106
|
-
|
|
110
|
+
|
|
111
|
+
// Some plugins like Typeahead require a whitespace before a trigger character.
|
|
112
|
+
// We want them to fire inside a gap cursor. Yet, a gap cursor is not considered a whitespace,
|
|
113
|
+
// and `textBefore` contains the text in the previous block before the gap cursor.
|
|
114
|
+
// Here is a workaround: if we inside a gap cursor, match the input rule only against the last typed character
|
|
115
|
+
// (which may be a typeahead trigger) and ignore the rest.
|
|
116
|
+
const matchString: string =
|
|
117
|
+
state.selection instanceof GapCursorSelection
|
|
118
|
+
? textBefore.at(-1) ?? ''
|
|
119
|
+
: textBefore;
|
|
120
|
+
|
|
121
|
+
const match = rule.match.exec(matchString);
|
|
107
122
|
if (!match) {
|
|
108
123
|
continue;
|
|
109
124
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -56,10 +56,8 @@ export function createInputRulePlugin(
|
|
|
56
56
|
tr.getMeta(pluginKey),
|
|
57
57
|
);
|
|
58
58
|
|
|
59
|
-
const pluginState:
|
|
60
|
-
|
|
61
|
-
| undefined
|
|
62
|
-
| null = transactionWithInputRuleMeta?.getMeta(pluginKey);
|
|
59
|
+
const pluginState: InputRulePluginState | undefined | null =
|
|
60
|
+
transactionWithInputRuleMeta?.getMeta(pluginKey);
|
|
63
61
|
|
|
64
62
|
if (!pluginState || !transactionWithInputRuleMeta) {
|
|
65
63
|
return null;
|