@atlaskit/editor-plugin-hyperlink 2.0.5 → 2.1.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 +13 -0
- package/dist/cjs/plugin.js +3 -2
- package/dist/cjs/pm-plugins/decorations.js +28 -0
- package/dist/cjs/pm-plugins/main.js +83 -3
- package/dist/es2019/plugin.js +3 -2
- package/dist/es2019/pm-plugins/decorations.js +22 -0
- package/dist/es2019/pm-plugins/main.js +87 -2
- package/dist/esm/plugin.js +3 -2
- package/dist/esm/pm-plugins/decorations.js +21 -0
- package/dist/esm/pm-plugins/main.js +83 -3
- package/dist/types/pm-plugins/decorations.d.ts +7 -0
- package/dist/types/pm-plugins/main.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
- package/package.json +32 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-hyperlink
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#110802](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/110802)
|
|
8
|
+
[`5a5f54961cab7`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/5a5f54961cab7) -
|
|
9
|
+
[ux] Implemented an overlay button on hover of hyperlinks for live pages editor which selects the
|
|
10
|
+
hyperlink and opens the toolbar on click. (behind platform feature flag)
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
|
|
3
16
|
## 2.0.5
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/cjs/plugin.js
CHANGED
|
@@ -63,8 +63,9 @@ var hyperlinkPlugin = exports.hyperlinkPlugin = function hyperlinkPlugin(_ref) {
|
|
|
63
63
|
return [{
|
|
64
64
|
name: 'hyperlink',
|
|
65
65
|
plugin: function plugin(_ref2) {
|
|
66
|
-
var dispatch = _ref2.dispatch
|
|
67
|
-
|
|
66
|
+
var dispatch = _ref2.dispatch,
|
|
67
|
+
getIntl = _ref2.getIntl;
|
|
68
|
+
return (0, _main.plugin)(dispatch, getIntl(), options === null || options === void 0 ? void 0 : options.editorAppearance);
|
|
68
69
|
}
|
|
69
70
|
}, {
|
|
70
71
|
name: 'fakeCursorToolbarPlugin',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.ButtonWrapper = void 0;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _reactDom = require("react-dom");
|
|
10
|
+
var _reactIntlNext = require("react-intl-next");
|
|
11
|
+
var _link = require("@atlaskit/editor-common/link");
|
|
12
|
+
var ButtonWrapper = exports.ButtonWrapper = function ButtonWrapper(_ref) {
|
|
13
|
+
var editorView = _ref.editorView,
|
|
14
|
+
pos = _ref.pos,
|
|
15
|
+
intl = _ref.intl;
|
|
16
|
+
var wrapper = document.createElement('span');
|
|
17
|
+
wrapper.style.position = 'relative';
|
|
18
|
+
var nonBreakingCharacter = "\u2060";
|
|
19
|
+
(0, _reactDom.render)( /*#__PURE__*/_react.default.createElement(_reactIntlNext.IntlProvider, {
|
|
20
|
+
locale: intl.locale || 'en',
|
|
21
|
+
messages: intl.messages,
|
|
22
|
+
formats: intl.formats
|
|
23
|
+
}, /*#__PURE__*/_react.default.createElement(_link.OverlayButton, {
|
|
24
|
+
targetElementPos: pos,
|
|
25
|
+
editorView: editorView
|
|
26
|
+
}), nonBreakingCharacter), wrapper);
|
|
27
|
+
return wrapper;
|
|
28
|
+
};
|
|
@@ -10,7 +10,11 @@ var _uuid = _interopRequireDefault(require("uuid"));
|
|
|
10
10
|
var _link3 = require("@atlaskit/editor-common/link");
|
|
11
11
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
13
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
13
14
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
15
|
+
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
16
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
17
|
+
var _decorations = require("./decorations");
|
|
14
18
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
19
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
20
|
var isSelectionInsideLink = function isSelectionInsideLink(state) {
|
|
@@ -154,7 +158,7 @@ var getActiveText = function getActiveText(selection) {
|
|
|
154
158
|
return;
|
|
155
159
|
};
|
|
156
160
|
var stateKey = exports.stateKey = new _state.PluginKey('hyperlinkPlugin');
|
|
157
|
-
var plugin = exports.plugin = function plugin(dispatch, editorAppearance) {
|
|
161
|
+
var plugin = exports.plugin = function plugin(dispatch, intl, editorAppearance) {
|
|
158
162
|
return new _safePlugin.SafePlugin({
|
|
159
163
|
state: {
|
|
160
164
|
init: function init(_, state) {
|
|
@@ -196,6 +200,31 @@ var plugin = exports.plugin = function plugin(dispatch, editorAppearance) {
|
|
|
196
200
|
activeLinkMark: toState(state.activeLinkMark, action, newState),
|
|
197
201
|
editorAppearance: editorAppearance
|
|
198
202
|
}, stateForAnalytics);
|
|
203
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.smart-links-in-live-pages')) {
|
|
204
|
+
if (action === _link3.LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS) {
|
|
205
|
+
var configureButtonTargetPos = tr.getMeta(stateKey).pos;
|
|
206
|
+
var targetPosHasChanged = pluginState.configureButtonTargetPos !== configureButtonTargetPos;
|
|
207
|
+
var decorations = pluginState.decorations;
|
|
208
|
+
if (targetPosHasChanged) {
|
|
209
|
+
if (configureButtonTargetPos === undefined) {
|
|
210
|
+
decorations = _view.DecorationSet.empty;
|
|
211
|
+
} else {
|
|
212
|
+
var decoration = _view.Decoration.widget(configureButtonTargetPos, function (view) {
|
|
213
|
+
return (0, _decorations.ButtonWrapper)({
|
|
214
|
+
editorView: view,
|
|
215
|
+
pos: configureButtonTargetPos,
|
|
216
|
+
intl: intl
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
decorations = _view.DecorationSet.create(newState.doc, [decoration]);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
state = _objectSpread(_objectSpread({}, state), {}, {
|
|
223
|
+
configureButtonTargetPos: configureButtonTargetPos,
|
|
224
|
+
decorations: decorations
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
199
228
|
}
|
|
200
229
|
var hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
|
|
201
230
|
if (tr.selectionSet && hasPositionChanged) {
|
|
@@ -216,7 +245,17 @@ var plugin = exports.plugin = function plugin(dispatch, editorAppearance) {
|
|
|
216
245
|
}
|
|
217
246
|
},
|
|
218
247
|
key: stateKey,
|
|
219
|
-
props: {
|
|
248
|
+
props: _objectSpread({
|
|
249
|
+
decorations: function decorations(state) {
|
|
250
|
+
if ((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.smart-links-in-live-pages')) {
|
|
251
|
+
var _stateKey$getState;
|
|
252
|
+
var _ref = (_stateKey$getState = stateKey.getState(state)) !== null && _stateKey$getState !== void 0 ? _stateKey$getState : {},
|
|
253
|
+
decorations = _ref.decorations;
|
|
254
|
+
return decorations;
|
|
255
|
+
} else {
|
|
256
|
+
return _view.DecorationSet.empty;
|
|
257
|
+
}
|
|
258
|
+
},
|
|
220
259
|
handleDOMEvents: {
|
|
221
260
|
mouseup: function mouseup(_, event) {
|
|
222
261
|
// this prevents redundant selection transaction when clicking on link
|
|
@@ -247,7 +286,48 @@ var plugin = exports.plugin = function plugin(dispatch, editorAppearance) {
|
|
|
247
286
|
return false;
|
|
248
287
|
}
|
|
249
288
|
}
|
|
250
|
-
}
|
|
289
|
+
}, (0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.smart-links-in-live-pages') && {
|
|
290
|
+
markViews: {
|
|
291
|
+
link: function link(mark, view, inline) {
|
|
292
|
+
var toDOM = mark.type.spec.toDOM;
|
|
293
|
+
if (!toDOM) {
|
|
294
|
+
throw new Error('toDom method missing');
|
|
295
|
+
}
|
|
296
|
+
var dom = _model.DOMSerializer.renderSpec(document, toDOM(mark, inline)).dom;
|
|
297
|
+
if (!(dom instanceof HTMLElement)) {
|
|
298
|
+
throw new Error('Error rendering hyperlink spec to dom');
|
|
299
|
+
}
|
|
300
|
+
var setTargetElementPos = function setTargetElementPos(val) {
|
|
301
|
+
var tr = view.state.tr;
|
|
302
|
+
tr.setMeta(stateKey, {
|
|
303
|
+
type: _link3.LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS,
|
|
304
|
+
pos: val
|
|
305
|
+
});
|
|
306
|
+
view.dispatch(tr);
|
|
307
|
+
};
|
|
308
|
+
dom.onmouseenter = function () {
|
|
309
|
+
var _stateKey$getState2;
|
|
310
|
+
var _ref2 = (_stateKey$getState2 = stateKey.getState(view.state)) !== null && _stateKey$getState2 !== void 0 ? _stateKey$getState2 : {},
|
|
311
|
+
configureButtonTargetPos = _ref2.configureButtonTargetPos;
|
|
312
|
+
var nodePos = view.posAtDOM(dom, -1);
|
|
313
|
+
if (nodePos !== configureButtonTargetPos) {
|
|
314
|
+
setTargetElementPos(nodePos);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
dom.onmouseleave = function () {
|
|
318
|
+
var _stateKey$getState3;
|
|
319
|
+
var _ref3 = (_stateKey$getState3 = stateKey.getState(view.state)) !== null && _stateKey$getState3 !== void 0 ? _stateKey$getState3 : {},
|
|
320
|
+
configureButtonTargetPos = _ref3.configureButtonTargetPos;
|
|
321
|
+
if (configureButtonTargetPos !== undefined) {
|
|
322
|
+
setTargetElementPos(undefined);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
return {
|
|
326
|
+
dom: dom
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
})
|
|
251
331
|
});
|
|
252
332
|
};
|
|
253
333
|
function isLinkDirectTarget(event) {
|
package/dist/es2019/plugin.js
CHANGED
|
@@ -52,8 +52,9 @@ export const hyperlinkPlugin = ({
|
|
|
52
52
|
return [{
|
|
53
53
|
name: 'hyperlink',
|
|
54
54
|
plugin: ({
|
|
55
|
-
dispatch
|
|
56
|
-
|
|
55
|
+
dispatch,
|
|
56
|
+
getIntl
|
|
57
|
+
}) => plugin(dispatch, getIntl(), options === null || options === void 0 ? void 0 : options.editorAppearance)
|
|
57
58
|
}, {
|
|
58
59
|
name: 'fakeCursorToolbarPlugin',
|
|
59
60
|
plugin: () => fakeCursorToolbarPlugin
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from 'react-dom';
|
|
3
|
+
import { IntlProvider } from 'react-intl-next';
|
|
4
|
+
import { OverlayButton } from '@atlaskit/editor-common/link';
|
|
5
|
+
export const ButtonWrapper = ({
|
|
6
|
+
editorView,
|
|
7
|
+
pos,
|
|
8
|
+
intl
|
|
9
|
+
}) => {
|
|
10
|
+
const wrapper = document.createElement('span');
|
|
11
|
+
wrapper.style.position = 'relative';
|
|
12
|
+
const nonBreakingCharacter = '\u2060';
|
|
13
|
+
render( /*#__PURE__*/React.createElement(IntlProvider, {
|
|
14
|
+
locale: intl.locale || 'en',
|
|
15
|
+
messages: intl.messages,
|
|
16
|
+
formats: intl.formats
|
|
17
|
+
}, /*#__PURE__*/React.createElement(OverlayButton, {
|
|
18
|
+
targetElementPos: pos,
|
|
19
|
+
editorView: editorView
|
|
20
|
+
}), nonBreakingCharacter), wrapper);
|
|
21
|
+
return wrapper;
|
|
22
|
+
};
|
|
@@ -2,7 +2,11 @@ import uuid from 'uuid';
|
|
|
2
2
|
import { InsertStatus, LinkAction } from '@atlaskit/editor-common/link';
|
|
3
3
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
4
|
import { canLinkBeCreatedInRange, shallowEqual } from '@atlaskit/editor-common/utils';
|
|
5
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
5
6
|
import { PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
|
+
import { ButtonWrapper } from './decorations';
|
|
6
10
|
const isSelectionInsideLink = state => !!state.doc.type.schema.marks.link.isInSet(state.selection.$from.marks());
|
|
7
11
|
const isSelectionAroundLink = state => {
|
|
8
12
|
const {
|
|
@@ -155,7 +159,7 @@ const getActiveText = selection => {
|
|
|
155
159
|
return;
|
|
156
160
|
};
|
|
157
161
|
export const stateKey = new PluginKey('hyperlinkPlugin');
|
|
158
|
-
export const plugin = (dispatch, editorAppearance) => new SafePlugin({
|
|
162
|
+
export const plugin = (dispatch, intl, editorAppearance) => new SafePlugin({
|
|
159
163
|
state: {
|
|
160
164
|
init(_, state) {
|
|
161
165
|
const canInsertLink = canLinkBeCreatedInRange(state.selection.from, state.selection.to)(state);
|
|
@@ -197,6 +201,32 @@ export const plugin = (dispatch, editorAppearance) => new SafePlugin({
|
|
|
197
201
|
editorAppearance,
|
|
198
202
|
...stateForAnalytics
|
|
199
203
|
};
|
|
204
|
+
if (getBooleanFF('platform.linking-platform.smart-links-in-live-pages')) {
|
|
205
|
+
if (action === LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS) {
|
|
206
|
+
const configureButtonTargetPos = tr.getMeta(stateKey).pos;
|
|
207
|
+
const targetPosHasChanged = pluginState.configureButtonTargetPos !== configureButtonTargetPos;
|
|
208
|
+
let decorations = pluginState.decorations;
|
|
209
|
+
if (targetPosHasChanged) {
|
|
210
|
+
if (configureButtonTargetPos === undefined) {
|
|
211
|
+
decorations = DecorationSet.empty;
|
|
212
|
+
} else {
|
|
213
|
+
const decoration = Decoration.widget(configureButtonTargetPos, view => {
|
|
214
|
+
return ButtonWrapper({
|
|
215
|
+
editorView: view,
|
|
216
|
+
pos: configureButtonTargetPos,
|
|
217
|
+
intl
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
decorations = DecorationSet.create(newState.doc, [decoration]);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
state = {
|
|
224
|
+
...state,
|
|
225
|
+
configureButtonTargetPos,
|
|
226
|
+
decorations
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
200
230
|
}
|
|
201
231
|
const hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
|
|
202
232
|
if (tr.selectionSet && hasPositionChanged) {
|
|
@@ -218,6 +248,17 @@ export const plugin = (dispatch, editorAppearance) => new SafePlugin({
|
|
|
218
248
|
},
|
|
219
249
|
key: stateKey,
|
|
220
250
|
props: {
|
|
251
|
+
decorations: state => {
|
|
252
|
+
if (getBooleanFF('platform.linking-platform.smart-links-in-live-pages')) {
|
|
253
|
+
var _stateKey$getState;
|
|
254
|
+
const {
|
|
255
|
+
decorations
|
|
256
|
+
} = (_stateKey$getState = stateKey.getState(state)) !== null && _stateKey$getState !== void 0 ? _stateKey$getState : {};
|
|
257
|
+
return decorations;
|
|
258
|
+
} else {
|
|
259
|
+
return DecorationSet.empty;
|
|
260
|
+
}
|
|
261
|
+
},
|
|
221
262
|
handleDOMEvents: {
|
|
222
263
|
mouseup: (_, event) => {
|
|
223
264
|
// this prevents redundant selection transaction when clicking on link
|
|
@@ -253,7 +294,51 @@ export const plugin = (dispatch, editorAppearance) => new SafePlugin({
|
|
|
253
294
|
}
|
|
254
295
|
return false;
|
|
255
296
|
}
|
|
256
|
-
}
|
|
297
|
+
},
|
|
298
|
+
...(getBooleanFF('platform.linking-platform.smart-links-in-live-pages') && {
|
|
299
|
+
markViews: {
|
|
300
|
+
link: (mark, view, inline) => {
|
|
301
|
+
const toDOM = mark.type.spec.toDOM;
|
|
302
|
+
if (!toDOM) {
|
|
303
|
+
throw new Error('toDom method missing');
|
|
304
|
+
}
|
|
305
|
+
const dom = DOMSerializer.renderSpec(document, toDOM(mark, inline)).dom;
|
|
306
|
+
if (!(dom instanceof HTMLElement)) {
|
|
307
|
+
throw new Error('Error rendering hyperlink spec to dom');
|
|
308
|
+
}
|
|
309
|
+
const setTargetElementPos = val => {
|
|
310
|
+
const tr = view.state.tr;
|
|
311
|
+
tr.setMeta(stateKey, {
|
|
312
|
+
type: LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS,
|
|
313
|
+
pos: val
|
|
314
|
+
});
|
|
315
|
+
view.dispatch(tr);
|
|
316
|
+
};
|
|
317
|
+
dom.onmouseenter = () => {
|
|
318
|
+
var _stateKey$getState2;
|
|
319
|
+
const {
|
|
320
|
+
configureButtonTargetPos
|
|
321
|
+
} = (_stateKey$getState2 = stateKey.getState(view.state)) !== null && _stateKey$getState2 !== void 0 ? _stateKey$getState2 : {};
|
|
322
|
+
const nodePos = view.posAtDOM(dom, -1);
|
|
323
|
+
if (nodePos !== configureButtonTargetPos) {
|
|
324
|
+
setTargetElementPos(nodePos);
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
dom.onmouseleave = () => {
|
|
328
|
+
var _stateKey$getState3;
|
|
329
|
+
const {
|
|
330
|
+
configureButtonTargetPos
|
|
331
|
+
} = (_stateKey$getState3 = stateKey.getState(view.state)) !== null && _stateKey$getState3 !== void 0 ? _stateKey$getState3 : {};
|
|
332
|
+
if (configureButtonTargetPos !== undefined) {
|
|
333
|
+
setTargetElementPos(undefined);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
return {
|
|
337
|
+
dom: dom
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
})
|
|
257
342
|
}
|
|
258
343
|
});
|
|
259
344
|
function isLinkDirectTarget(event) {
|
package/dist/esm/plugin.js
CHANGED
|
@@ -56,8 +56,9 @@ export var hyperlinkPlugin = function hyperlinkPlugin(_ref) {
|
|
|
56
56
|
return [{
|
|
57
57
|
name: 'hyperlink',
|
|
58
58
|
plugin: function plugin(_ref2) {
|
|
59
|
-
var dispatch = _ref2.dispatch
|
|
60
|
-
|
|
59
|
+
var dispatch = _ref2.dispatch,
|
|
60
|
+
getIntl = _ref2.getIntl;
|
|
61
|
+
return _plugin(dispatch, getIntl(), options === null || options === void 0 ? void 0 : options.editorAppearance);
|
|
61
62
|
}
|
|
62
63
|
}, {
|
|
63
64
|
name: 'fakeCursorToolbarPlugin',
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from 'react-dom';
|
|
3
|
+
import { IntlProvider } from 'react-intl-next';
|
|
4
|
+
import { OverlayButton } from '@atlaskit/editor-common/link';
|
|
5
|
+
export var ButtonWrapper = function ButtonWrapper(_ref) {
|
|
6
|
+
var editorView = _ref.editorView,
|
|
7
|
+
pos = _ref.pos,
|
|
8
|
+
intl = _ref.intl;
|
|
9
|
+
var wrapper = document.createElement('span');
|
|
10
|
+
wrapper.style.position = 'relative';
|
|
11
|
+
var nonBreakingCharacter = "\u2060";
|
|
12
|
+
render( /*#__PURE__*/React.createElement(IntlProvider, {
|
|
13
|
+
locale: intl.locale || 'en',
|
|
14
|
+
messages: intl.messages,
|
|
15
|
+
formats: intl.formats
|
|
16
|
+
}, /*#__PURE__*/React.createElement(OverlayButton, {
|
|
17
|
+
targetElementPos: pos,
|
|
18
|
+
editorView: editorView
|
|
19
|
+
}), nonBreakingCharacter), wrapper);
|
|
20
|
+
return wrapper;
|
|
21
|
+
};
|
|
@@ -5,7 +5,11 @@ import uuid from 'uuid';
|
|
|
5
5
|
import { InsertStatus, LinkAction } from '@atlaskit/editor-common/link';
|
|
6
6
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
7
7
|
import { canLinkBeCreatedInRange, shallowEqual } from '@atlaskit/editor-common/utils';
|
|
8
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
8
9
|
import { PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
10
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
11
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
12
|
+
import { ButtonWrapper } from './decorations';
|
|
9
13
|
var isSelectionInsideLink = function isSelectionInsideLink(state) {
|
|
10
14
|
return !!state.doc.type.schema.marks.link.isInSet(state.selection.$from.marks());
|
|
11
15
|
};
|
|
@@ -147,7 +151,7 @@ var getActiveText = function getActiveText(selection) {
|
|
|
147
151
|
return;
|
|
148
152
|
};
|
|
149
153
|
export var stateKey = new PluginKey('hyperlinkPlugin');
|
|
150
|
-
export var plugin = function plugin(dispatch, editorAppearance) {
|
|
154
|
+
export var plugin = function plugin(dispatch, intl, editorAppearance) {
|
|
151
155
|
return new SafePlugin({
|
|
152
156
|
state: {
|
|
153
157
|
init: function init(_, state) {
|
|
@@ -189,6 +193,31 @@ export var plugin = function plugin(dispatch, editorAppearance) {
|
|
|
189
193
|
activeLinkMark: toState(state.activeLinkMark, action, newState),
|
|
190
194
|
editorAppearance: editorAppearance
|
|
191
195
|
}, stateForAnalytics);
|
|
196
|
+
if (getBooleanFF('platform.linking-platform.smart-links-in-live-pages')) {
|
|
197
|
+
if (action === LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS) {
|
|
198
|
+
var configureButtonTargetPos = tr.getMeta(stateKey).pos;
|
|
199
|
+
var targetPosHasChanged = pluginState.configureButtonTargetPos !== configureButtonTargetPos;
|
|
200
|
+
var decorations = pluginState.decorations;
|
|
201
|
+
if (targetPosHasChanged) {
|
|
202
|
+
if (configureButtonTargetPos === undefined) {
|
|
203
|
+
decorations = DecorationSet.empty;
|
|
204
|
+
} else {
|
|
205
|
+
var decoration = Decoration.widget(configureButtonTargetPos, function (view) {
|
|
206
|
+
return ButtonWrapper({
|
|
207
|
+
editorView: view,
|
|
208
|
+
pos: configureButtonTargetPos,
|
|
209
|
+
intl: intl
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
decorations = DecorationSet.create(newState.doc, [decoration]);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
state = _objectSpread(_objectSpread({}, state), {}, {
|
|
216
|
+
configureButtonTargetPos: configureButtonTargetPos,
|
|
217
|
+
decorations: decorations
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
192
221
|
}
|
|
193
222
|
var hasPositionChanged = oldState.selection.from !== newState.selection.from || oldState.selection.to !== newState.selection.to;
|
|
194
223
|
if (tr.selectionSet && hasPositionChanged) {
|
|
@@ -209,7 +238,17 @@ export var plugin = function plugin(dispatch, editorAppearance) {
|
|
|
209
238
|
}
|
|
210
239
|
},
|
|
211
240
|
key: stateKey,
|
|
212
|
-
props: {
|
|
241
|
+
props: _objectSpread({
|
|
242
|
+
decorations: function decorations(state) {
|
|
243
|
+
if (getBooleanFF('platform.linking-platform.smart-links-in-live-pages')) {
|
|
244
|
+
var _stateKey$getState;
|
|
245
|
+
var _ref = (_stateKey$getState = stateKey.getState(state)) !== null && _stateKey$getState !== void 0 ? _stateKey$getState : {},
|
|
246
|
+
decorations = _ref.decorations;
|
|
247
|
+
return decorations;
|
|
248
|
+
} else {
|
|
249
|
+
return DecorationSet.empty;
|
|
250
|
+
}
|
|
251
|
+
},
|
|
213
252
|
handleDOMEvents: {
|
|
214
253
|
mouseup: function mouseup(_, event) {
|
|
215
254
|
// this prevents redundant selection transaction when clicking on link
|
|
@@ -240,7 +279,48 @@ export var plugin = function plugin(dispatch, editorAppearance) {
|
|
|
240
279
|
return false;
|
|
241
280
|
}
|
|
242
281
|
}
|
|
243
|
-
}
|
|
282
|
+
}, getBooleanFF('platform.linking-platform.smart-links-in-live-pages') && {
|
|
283
|
+
markViews: {
|
|
284
|
+
link: function link(mark, view, inline) {
|
|
285
|
+
var toDOM = mark.type.spec.toDOM;
|
|
286
|
+
if (!toDOM) {
|
|
287
|
+
throw new Error('toDom method missing');
|
|
288
|
+
}
|
|
289
|
+
var dom = DOMSerializer.renderSpec(document, toDOM(mark, inline)).dom;
|
|
290
|
+
if (!(dom instanceof HTMLElement)) {
|
|
291
|
+
throw new Error('Error rendering hyperlink spec to dom');
|
|
292
|
+
}
|
|
293
|
+
var setTargetElementPos = function setTargetElementPos(val) {
|
|
294
|
+
var tr = view.state.tr;
|
|
295
|
+
tr.setMeta(stateKey, {
|
|
296
|
+
type: LinkAction.SET_CONFIGURE_BUTTON_TARGET_POS,
|
|
297
|
+
pos: val
|
|
298
|
+
});
|
|
299
|
+
view.dispatch(tr);
|
|
300
|
+
};
|
|
301
|
+
dom.onmouseenter = function () {
|
|
302
|
+
var _stateKey$getState2;
|
|
303
|
+
var _ref2 = (_stateKey$getState2 = stateKey.getState(view.state)) !== null && _stateKey$getState2 !== void 0 ? _stateKey$getState2 : {},
|
|
304
|
+
configureButtonTargetPos = _ref2.configureButtonTargetPos;
|
|
305
|
+
var nodePos = view.posAtDOM(dom, -1);
|
|
306
|
+
if (nodePos !== configureButtonTargetPos) {
|
|
307
|
+
setTargetElementPos(nodePos);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
dom.onmouseleave = function () {
|
|
311
|
+
var _stateKey$getState3;
|
|
312
|
+
var _ref3 = (_stateKey$getState3 = stateKey.getState(view.state)) !== null && _stateKey$getState3 !== void 0 ? _stateKey$getState3 : {},
|
|
313
|
+
configureButtonTargetPos = _ref3.configureButtonTargetPos;
|
|
314
|
+
if (configureButtonTargetPos !== undefined) {
|
|
315
|
+
setTargetElementPos(undefined);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
dom: dom
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
})
|
|
244
324
|
});
|
|
245
325
|
};
|
|
246
326
|
function isLinkDirectTarget(event) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type IntlShape } from 'react-intl-next';
|
|
2
|
+
import { type EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
export declare const ButtonWrapper: ({ editorView, pos, intl, }: {
|
|
4
|
+
editorView: EditorView;
|
|
5
|
+
pos?: number | undefined;
|
|
6
|
+
intl: IntlShape;
|
|
7
|
+
}) => HTMLSpanElement;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type IntlShape } from 'react-intl-next';
|
|
1
2
|
import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
2
3
|
import type { HyperlinkState } from '@atlaskit/editor-common/link';
|
|
3
4
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
5
|
import type { EditorAppearance } from '@atlaskit/editor-common/types';
|
|
5
6
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
7
|
export declare const stateKey: PluginKey<HyperlinkState>;
|
|
7
|
-
export declare const plugin: (dispatch: Dispatch, editorAppearance?: EditorAppearance) => SafePlugin<HyperlinkState>;
|
|
8
|
+
export declare const plugin: (dispatch: Dispatch, intl: IntlShape, editorAppearance?: EditorAppearance) => SafePlugin<HyperlinkState>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type IntlShape } from 'react-intl-next';
|
|
2
|
+
import { type EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
export declare const ButtonWrapper: ({ editorView, pos, intl, }: {
|
|
4
|
+
editorView: EditorView;
|
|
5
|
+
pos?: number | undefined;
|
|
6
|
+
intl: IntlShape;
|
|
7
|
+
}) => HTMLSpanElement;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type IntlShape } from 'react-intl-next';
|
|
1
2
|
import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
2
3
|
import type { HyperlinkState } from '@atlaskit/editor-common/link';
|
|
3
4
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
5
|
import type { EditorAppearance } from '@atlaskit/editor-common/types';
|
|
5
6
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
7
|
export declare const stateKey: PluginKey<HyperlinkState>;
|
|
7
|
-
export declare const plugin: (dispatch: Dispatch, editorAppearance?: EditorAppearance) => SafePlugin<HyperlinkState>;
|
|
8
|
+
export declare const plugin: (dispatch: Dispatch, intl: IntlShape, editorAppearance?: EditorAppearance) => SafePlugin<HyperlinkState>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-hyperlink",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Hyperlink plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -20,7 +20,10 @@
|
|
|
20
20
|
"types": "dist/types/index.d.ts",
|
|
21
21
|
"typesVersions": {
|
|
22
22
|
">=4.5 <4.9": {
|
|
23
|
-
"*": [
|
|
23
|
+
"*": [
|
|
24
|
+
"dist/types-ts4.5/*",
|
|
25
|
+
"dist/types-ts4.5/index.d.ts"
|
|
26
|
+
]
|
|
24
27
|
}
|
|
25
28
|
},
|
|
26
29
|
"sideEffects": false,
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
"dependencies": {
|
|
32
35
|
"@atlaskit/adf-schema": "^36.10.7",
|
|
33
36
|
"@atlaskit/analytics-next": "^9.3.0",
|
|
34
|
-
"@atlaskit/editor-common": "^82.
|
|
37
|
+
"@atlaskit/editor-common": "^82.7.0",
|
|
35
38
|
"@atlaskit/editor-plugin-analytics": "^1.2.0",
|
|
36
39
|
"@atlaskit/editor-plugin-card": "2.0.5",
|
|
37
40
|
"@atlaskit/editor-prosemirror": "4.0.1",
|
|
@@ -43,6 +46,7 @@
|
|
|
43
46
|
},
|
|
44
47
|
"peerDependencies": {
|
|
45
48
|
"react": "^16.8.0",
|
|
49
|
+
"react-dom": "^16.8.0",
|
|
46
50
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
|
@@ -54,23 +58,37 @@
|
|
|
54
58
|
"@atlaskit/visual-regression": "*",
|
|
55
59
|
"@testing-library/react": "^12.1.5",
|
|
56
60
|
"raf-stub": "^2.0.1",
|
|
57
|
-
"react-dom": "^16.8.0",
|
|
58
61
|
"typescript": "~5.4.2",
|
|
59
62
|
"wait-for-expect": "^1.2.0"
|
|
60
63
|
},
|
|
61
64
|
"techstack": {
|
|
62
65
|
"@atlassian/frontend": {
|
|
63
|
-
"import-structure": [
|
|
64
|
-
|
|
66
|
+
"import-structure": [
|
|
67
|
+
"atlassian-conventions"
|
|
68
|
+
],
|
|
69
|
+
"circular-dependencies": [
|
|
70
|
+
"file-and-folder-level"
|
|
71
|
+
]
|
|
65
72
|
},
|
|
66
73
|
"@repo/internal": {
|
|
67
74
|
"dom-events": "use-bind-event-listener",
|
|
68
|
-
"analytics": [
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
75
|
+
"analytics": [
|
|
76
|
+
"analytics-next"
|
|
77
|
+
],
|
|
78
|
+
"design-tokens": [
|
|
79
|
+
"color"
|
|
80
|
+
],
|
|
81
|
+
"theming": [
|
|
82
|
+
"react-context"
|
|
83
|
+
],
|
|
84
|
+
"ui-components": [
|
|
85
|
+
"lite-mode"
|
|
86
|
+
],
|
|
72
87
|
"deprecation": "no-deprecated-imports",
|
|
73
|
-
"styling": [
|
|
88
|
+
"styling": [
|
|
89
|
+
"emotion",
|
|
90
|
+
"emotion"
|
|
91
|
+
]
|
|
74
92
|
}
|
|
75
93
|
},
|
|
76
94
|
"platform-feature-flags": {
|
|
@@ -79,6 +97,9 @@
|
|
|
79
97
|
},
|
|
80
98
|
"platform.editor.card.inject-settings-button": {
|
|
81
99
|
"type": "boolean"
|
|
100
|
+
},
|
|
101
|
+
"platform.linking-platform.smart-links-in-live-pages": {
|
|
102
|
+
"type": "boolean"
|
|
82
103
|
}
|
|
83
104
|
}
|
|
84
105
|
}
|