@atlaskit/editor-plugin-hyperlink 1.3.1 → 1.4.0
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 +10 -0
- package/dist/cjs/pm-plugins/input-rule.js +29 -1
- package/dist/cjs/pm-plugins/keymap.js +10 -0
- package/dist/es2019/pm-plugins/input-rule.js +31 -2
- package/dist/es2019/pm-plugins/keymap.js +11 -1
- package/dist/esm/pm-plugins/input-rule.js +31 -2
- package/dist/esm/pm-plugins/keymap.js +11 -1
- package/dist/types/pm-plugins/input-rule.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/input-rule.d.ts +3 -0
- package/package.json +8 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-hyperlink
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#84430](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/84430) [`2981b2835973`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/2981b2835973) - [ux] EDM-9111 Prevent linkification of links with suspicious tlds
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
3
13
|
## 1.3.1
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -12,8 +12,12 @@ var _analytics = require("@atlaskit/editor-common/analytics");
|
|
|
12
12
|
var _card = require("@atlaskit/editor-common/card");
|
|
13
13
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
14
14
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
15
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
15
16
|
var _prosemirrorInputRules = require("@atlaskit/prosemirror-input-rules");
|
|
16
17
|
var _toolbarButtons = require("./toolbar-buttons");
|
|
18
|
+
/**
|
|
19
|
+
* Called when space after link, but not on enter
|
|
20
|
+
*/
|
|
17
21
|
function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
18
22
|
// Plain typed text (eg, typing 'www.google.com') should convert to a hyperlink
|
|
19
23
|
return (0, _utils.createRule)(regexp, function (state, match, start, end) {
|
|
@@ -23,7 +27,27 @@ function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
|
23
27
|
return null;
|
|
24
28
|
}
|
|
25
29
|
var link = match;
|
|
26
|
-
var url
|
|
30
|
+
var url;
|
|
31
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
32
|
+
// Property 'url' does not exist on type 'RegExpExecArray', the type of `match`.
|
|
33
|
+
// This check is in case the match is not a Linkify match, which has a url property.
|
|
34
|
+
if (link.url === undefined) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (!(0, _utils.shouldAutoLinkifyMatch)(link)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
url = (0, _utils.normalizeUrl)(link.url);
|
|
41
|
+
|
|
42
|
+
// Not previously handled; don't create a link if the URL is empty.
|
|
43
|
+
// This will only happen if the `regexp` matches more links than the normalizeUrl validation;
|
|
44
|
+
// if they both use the same linkify instance this shouldn't happen.
|
|
45
|
+
if (url === '') {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
url = (0, _utils.normalizeUrl)(link.url);
|
|
50
|
+
}
|
|
27
51
|
var markType = schema.mark('link', {
|
|
28
52
|
href: url
|
|
29
53
|
});
|
|
@@ -74,6 +98,10 @@ function createInputRulePlugin(schema, editorAnalyticsApi) {
|
|
|
74
98
|
prefix = _match[1],
|
|
75
99
|
linkText = _match[2],
|
|
76
100
|
linkUrl = _match[3];
|
|
101
|
+
|
|
102
|
+
// We don't filter this match here by shouldAutoLinkifyMatch
|
|
103
|
+
// because the intent of creating a link is clear
|
|
104
|
+
|
|
77
105
|
var url = (0, _utils.normalizeUrl)(linkUrl).trim();
|
|
78
106
|
var markType = schema.mark('link', {
|
|
79
107
|
href: url
|
|
@@ -11,6 +11,7 @@ var _card = require("@atlaskit/editor-common/card");
|
|
|
11
11
|
var _keymaps = require("@atlaskit/editor-common/keymaps");
|
|
12
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
13
13
|
var _keymap = require("@atlaskit/editor-prosemirror/keymap");
|
|
14
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
14
15
|
var _commands = require("../commands");
|
|
15
16
|
var _main = require("../pm-plugins/main");
|
|
16
17
|
var _toolbarButtons = require("./toolbar-buttons");
|
|
@@ -32,6 +33,10 @@ function createKeymapPlugin(editorAnalyticsApi) {
|
|
|
32
33
|
}, list);
|
|
33
34
|
return (0, _keymap.keymap)(list);
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert the last word before the selection to a hyperlink if it's a valid URL with a tld we want to linkify
|
|
39
|
+
*/
|
|
35
40
|
var mayConvertLastWordToHyperlink = function mayConvertLastWordToHyperlink(editorAnalyticsApi) {
|
|
36
41
|
return function (state, dispatch) {
|
|
37
42
|
var _toolbarKey$getState$, _toolbarKey$getState;
|
|
@@ -44,6 +49,11 @@ var mayConvertLastWordToHyperlink = function mayConvertLastWordToHyperlink(edito
|
|
|
44
49
|
var lastWord = words[words.length - 1];
|
|
45
50
|
var match = (0, _adfSchema.getLinkMatch)(lastWord);
|
|
46
51
|
if (match) {
|
|
52
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
53
|
+
if (!(0, _utils.shouldAutoLinkifyMatch)(match)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
47
57
|
var hyperlinkedText = match.raw;
|
|
48
58
|
var start = state.selection.$from.pos - hyperlinkedText.length;
|
|
49
59
|
var end = state.selection.$from.pos;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
3
3
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
|
-
import { createRule, findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, LinkMatcher, normalizeUrl } from '@atlaskit/editor-common/utils';
|
|
4
|
+
import { createRule, findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, LinkMatcher, normalizeUrl, shouldAutoLinkifyMatch } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
5
6
|
import { createPlugin } from '@atlaskit/prosemirror-input-rules';
|
|
6
7
|
import { toolbarKey } from './toolbar-buttons';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Called when space after link, but not on enter
|
|
11
|
+
*/
|
|
7
12
|
export function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
8
13
|
// Plain typed text (eg, typing 'www.google.com') should convert to a hyperlink
|
|
9
14
|
return createRule(regexp, (state, match, start, end) => {
|
|
@@ -15,7 +20,27 @@ export function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
|
15
20
|
return null;
|
|
16
21
|
}
|
|
17
22
|
const link = match;
|
|
18
|
-
|
|
23
|
+
let url;
|
|
24
|
+
if (getBooleanFF('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
25
|
+
// Property 'url' does not exist on type 'RegExpExecArray', the type of `match`.
|
|
26
|
+
// This check is in case the match is not a Linkify match, which has a url property.
|
|
27
|
+
if (link.url === undefined) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (!shouldAutoLinkifyMatch(link)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
url = normalizeUrl(link.url);
|
|
34
|
+
|
|
35
|
+
// Not previously handled; don't create a link if the URL is empty.
|
|
36
|
+
// This will only happen if the `regexp` matches more links than the normalizeUrl validation;
|
|
37
|
+
// if they both use the same linkify instance this shouldn't happen.
|
|
38
|
+
if (url === '') {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
url = normalizeUrl(link.url);
|
|
43
|
+
}
|
|
19
44
|
const markType = schema.mark('link', {
|
|
20
45
|
href: url
|
|
21
46
|
});
|
|
@@ -65,6 +90,10 @@ export function createInputRulePlugin(schema, editorAnalyticsApi) {
|
|
|
65
90
|
schema
|
|
66
91
|
} = state;
|
|
67
92
|
const [, prefix, linkText, linkUrl] = match;
|
|
93
|
+
|
|
94
|
+
// We don't filter this match here by shouldAutoLinkifyMatch
|
|
95
|
+
// because the intent of creating a link is clear
|
|
96
|
+
|
|
68
97
|
const url = normalizeUrl(linkUrl).trim();
|
|
69
98
|
const markType = schema.mark('link', {
|
|
70
99
|
href: url
|
|
@@ -2,8 +2,9 @@ import { getLinkMatch } from '@atlaskit/adf-schema';
|
|
|
2
2
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
3
3
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
4
4
|
import { addLink, bindKeymapWithCommand, bindKeymapWithEditorCommand, enter, escape, insertNewLine } from '@atlaskit/editor-common/keymaps';
|
|
5
|
-
import { findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, shouldAutoLinkifyMatch } from '@atlaskit/editor-common/utils';
|
|
6
6
|
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
|
|
7
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
8
|
import { hideLinkToolbar, showLinkToolbar } from '../commands';
|
|
8
9
|
import { stateKey } from '../pm-plugins/main';
|
|
9
10
|
import { toolbarKey } from './toolbar-buttons';
|
|
@@ -25,6 +26,10 @@ export function createKeymapPlugin(editorAnalyticsApi) {
|
|
|
25
26
|
}, list);
|
|
26
27
|
return keymap(list);
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Convert the last word before the selection to a hyperlink if it's a valid URL with a tld we want to linkify
|
|
32
|
+
*/
|
|
28
33
|
const mayConvertLastWordToHyperlink = editorAnalyticsApi => {
|
|
29
34
|
return function (state, dispatch) {
|
|
30
35
|
var _toolbarKey$getState$, _toolbarKey$getState;
|
|
@@ -37,6 +42,11 @@ const mayConvertLastWordToHyperlink = editorAnalyticsApi => {
|
|
|
37
42
|
const lastWord = words[words.length - 1];
|
|
38
43
|
const match = getLinkMatch(lastWord);
|
|
39
44
|
if (match) {
|
|
45
|
+
if (getBooleanFF('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
46
|
+
if (!shouldAutoLinkifyMatch(match)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
40
50
|
const hyperlinkedText = match.raw;
|
|
41
51
|
const start = state.selection.$from.pos - hyperlinkedText.length;
|
|
42
52
|
const end = state.selection.$from.pos;
|
|
@@ -2,9 +2,14 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
2
2
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
3
3
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
4
4
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
|
-
import { createRule, findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, LinkMatcher, normalizeUrl } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { createRule, findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, LinkMatcher, normalizeUrl, shouldAutoLinkifyMatch } from '@atlaskit/editor-common/utils';
|
|
6
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
6
7
|
import { createPlugin } from '@atlaskit/prosemirror-input-rules';
|
|
7
8
|
import { toolbarKey } from './toolbar-buttons';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Called when space after link, but not on enter
|
|
12
|
+
*/
|
|
8
13
|
export function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
9
14
|
// Plain typed text (eg, typing 'www.google.com') should convert to a hyperlink
|
|
10
15
|
return createRule(regexp, function (state, match, start, end) {
|
|
@@ -14,7 +19,27 @@ export function createLinkInputRule(regexp, editorAnalyticsApi) {
|
|
|
14
19
|
return null;
|
|
15
20
|
}
|
|
16
21
|
var link = match;
|
|
17
|
-
var url
|
|
22
|
+
var url;
|
|
23
|
+
if (getBooleanFF('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
24
|
+
// Property 'url' does not exist on type 'RegExpExecArray', the type of `match`.
|
|
25
|
+
// This check is in case the match is not a Linkify match, which has a url property.
|
|
26
|
+
if (link.url === undefined) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (!shouldAutoLinkifyMatch(link)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
url = normalizeUrl(link.url);
|
|
33
|
+
|
|
34
|
+
// Not previously handled; don't create a link if the URL is empty.
|
|
35
|
+
// This will only happen if the `regexp` matches more links than the normalizeUrl validation;
|
|
36
|
+
// if they both use the same linkify instance this shouldn't happen.
|
|
37
|
+
if (url === '') {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
url = normalizeUrl(link.url);
|
|
42
|
+
}
|
|
18
43
|
var markType = schema.mark('link', {
|
|
19
44
|
href: url
|
|
20
45
|
});
|
|
@@ -65,6 +90,10 @@ export function createInputRulePlugin(schema, editorAnalyticsApi) {
|
|
|
65
90
|
prefix = _match[1],
|
|
66
91
|
linkText = _match[2],
|
|
67
92
|
linkUrl = _match[3];
|
|
93
|
+
|
|
94
|
+
// We don't filter this match here by shouldAutoLinkifyMatch
|
|
95
|
+
// because the intent of creating a link is clear
|
|
96
|
+
|
|
68
97
|
var url = normalizeUrl(linkUrl).trim();
|
|
69
98
|
var markType = schema.mark('link', {
|
|
70
99
|
href: url
|
|
@@ -2,8 +2,9 @@ import { getLinkMatch } from '@atlaskit/adf-schema';
|
|
|
2
2
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
3
3
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
4
4
|
import { addLink, bindKeymapWithCommand, bindKeymapWithEditorCommand, enter, escape, insertNewLine } from '@atlaskit/editor-common/keymaps';
|
|
5
|
-
import { findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { findFilepaths, getLinkCreationAnalyticsEvent, isLinkInMatches, shouldAutoLinkifyMatch } from '@atlaskit/editor-common/utils';
|
|
6
6
|
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
|
|
7
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
8
|
import { hideLinkToolbar, showLinkToolbar } from '../commands';
|
|
8
9
|
import { stateKey } from '../pm-plugins/main';
|
|
9
10
|
import { toolbarKey } from './toolbar-buttons';
|
|
@@ -25,6 +26,10 @@ export function createKeymapPlugin(editorAnalyticsApi) {
|
|
|
25
26
|
}, list);
|
|
26
27
|
return keymap(list);
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Convert the last word before the selection to a hyperlink if it's a valid URL with a tld we want to linkify
|
|
32
|
+
*/
|
|
28
33
|
var mayConvertLastWordToHyperlink = function mayConvertLastWordToHyperlink(editorAnalyticsApi) {
|
|
29
34
|
return function (state, dispatch) {
|
|
30
35
|
var _toolbarKey$getState$, _toolbarKey$getState;
|
|
@@ -37,6 +42,11 @@ var mayConvertLastWordToHyperlink = function mayConvertLastWordToHyperlink(edito
|
|
|
37
42
|
var lastWord = words[words.length - 1];
|
|
38
43
|
var match = getLinkMatch(lastWord);
|
|
39
44
|
if (match) {
|
|
45
|
+
if (getBooleanFF('platform.linking-platform.prevent-suspicious-linkification')) {
|
|
46
|
+
if (!shouldAutoLinkifyMatch(match)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
40
50
|
var hyperlinkedText = match.raw;
|
|
41
51
|
var start = state.selection.$from.pos - hyperlinkedText.length;
|
|
42
52
|
var end = state.selection.$from.pos;
|
|
@@ -2,6 +2,9 @@ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import type { InputRuleWrapper } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
/**
|
|
6
|
+
* Called when space after link, but not on enter
|
|
7
|
+
*/
|
|
5
8
|
export declare function createLinkInputRule(regexp: RegExp, editorAnalyticsApi: EditorAnalyticsAPI | undefined): InputRuleWrapper;
|
|
6
9
|
export declare function createInputRulePlugin(schema: Schema, editorAnalyticsApi: EditorAnalyticsAPI | undefined): SafePlugin | undefined;
|
|
7
10
|
export default createInputRulePlugin;
|
|
@@ -2,6 +2,9 @@ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import type { InputRuleWrapper } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
/**
|
|
6
|
+
* Called when space after link, but not on enter
|
|
7
|
+
*/
|
|
5
8
|
export declare function createLinkInputRule(regexp: RegExp, editorAnalyticsApi: EditorAnalyticsAPI | undefined): InputRuleWrapper;
|
|
6
9
|
export declare function createInputRulePlugin(schema: Schema, editorAnalyticsApi: EditorAnalyticsAPI | undefined): SafePlugin | undefined;
|
|
7
10
|
export default createInputRulePlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-hyperlink",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Hyperlink plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,10 +34,11 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@atlaskit/adf-schema": "^35.8.0",
|
|
36
36
|
"@atlaskit/analytics-next": "^9.2.0",
|
|
37
|
-
"@atlaskit/editor-common": "^78.
|
|
37
|
+
"@atlaskit/editor-common": "^78.23.0",
|
|
38
38
|
"@atlaskit/editor-plugin-analytics": "^1.0.0",
|
|
39
39
|
"@atlaskit/editor-prosemirror": "3.0.0",
|
|
40
40
|
"@atlaskit/icon": "^22.1.0",
|
|
41
|
+
"@atlaskit/platform-feature-flags": "^0.2.5",
|
|
41
42
|
"@atlaskit/prosemirror-input-rules": "^3.0.0",
|
|
42
43
|
"@babel/runtime": "^7.0.0",
|
|
43
44
|
"uuid": "^3.1.0"
|
|
@@ -91,5 +92,9 @@
|
|
|
91
92
|
}
|
|
92
93
|
},
|
|
93
94
|
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.0",
|
|
94
|
-
"platform-feature-flags": {
|
|
95
|
+
"platform-feature-flags": {
|
|
96
|
+
"platform.linking-platform.prevent-suspicious-linkification": {
|
|
97
|
+
"type": "boolean"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
95
100
|
}
|