UNPKG

@atlaskit/editor-plugin-hyperlink

Version:

Hyperlink plugin for @atlaskit/editor-core

122 lines (114 loc) 5.66 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.createInputRulePlugin = createInputRulePlugin; exports.createLinkInputRule = createLinkInputRule; exports.default = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _analytics = require("@atlaskit/editor-common/analytics"); var _card = require("@atlaskit/editor-common/card"); var _safePlugin = require("@atlaskit/editor-common/safe-plugin"); var _utils = require("@atlaskit/editor-common/utils"); var _prosemirrorInputRules = require("@atlaskit/prosemirror-input-rules"); var _toolbarButtons = require("./toolbar-buttons"); /** * Called when space after link, but not on enter */ function createLinkInputRule(regexp, editorAnalyticsApi) { // Plain typed text (eg, typing 'www.google.com') should convert to a hyperlink return (0, _utils.createRule)(regexp, function (state, match, start, end) { var _toolbarKey$getState$, _toolbarKey$getState; var schema = state.schema; if (state.doc.rangeHasMark(start, end, schema.marks.link)) { return null; } var link = match; // Property 'url' does not exist on type 'RegExpExecArray', the type of `match`. // This check is in case the match is not a Linkify match, which has a url property. if (link.url === undefined) { return null; } if (!(0, _utils.shouldAutoLinkifyMatch)(link)) { return null; } var url = (0, _utils.normalizeUrl)(link.url); // Not previously handled; don't create a link if the URL is empty. // This will only happen if the `regexp` matches more links than the normalizeUrl validation; // if they both use the same linkify instance this shouldn't happen. if (url === '') { return null; } var markType = schema.mark('link', { href: url }); // Need access to complete text to check if last URL is part of a filepath before linkifying var nodeBefore = state.selection.$from.nodeBefore; if (!nodeBefore || !nodeBefore.isText || !nodeBefore.text) { return null; } var filepaths = (0, _utils.findFilepaths)(nodeBefore.text, // The position referenced by 'start' is relative to the start of the document, findFilepaths deals with index in a node only. start - (nodeBefore.text.length - link.text.length) // (start of link match) - (whole node text length - link length) gets start of text node, which is used as offset ); if ((0, _utils.isLinkInMatches)(start, filepaths)) { var _tr = state.tr; return _tr; } var from = start; var to = Math.min(start + link.text.length, state.doc.content.size); var tr = state.tr.addMark(from, to, markType); // Keep old behavior that will delete the space after the link if (to === end) { tr.insertText(' '); } (0, _card.addLinkMetadata)(state.selection, tr, { inputMethod: _analytics.INPUT_METHOD.AUTO_DETECT }); var skipAnalytics = (_toolbarKey$getState$ = (_toolbarKey$getState = _toolbarButtons.toolbarKey.getState(state)) === null || _toolbarKey$getState === void 0 ? void 0 : _toolbarKey$getState.skipAnalytics) !== null && _toolbarKey$getState$ !== void 0 ? _toolbarKey$getState$ : false; if (skipAnalytics) { return tr; } editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent((0, _utils.getLinkCreationAnalyticsEvent)(_analytics.INPUT_METHOD.AUTO_DETECT, url))(tr); return tr; }); } function createInputRulePlugin(schema, editorAnalyticsApi) { var autoLinkOnBlur = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (!schema.marks.link) { return; } var urlWithASpaceRule = createLinkInputRule(_utils.LinkMatcher.create(), editorAnalyticsApi); // [something](link) should convert to a hyperlink // eslint-disable-next-line require-unicode-regexp var markdownLinkRule = (0, _utils.createRule)(/(^|[^!])\[(.*?)\]\((\S+)\)$/, function (state, match, start, end) { var _toolbarKey$getState$2, _toolbarKey$getState2; var schema = state.schema; var _match = (0, _slicedToArray2.default)(match, 4), prefix = _match[1], linkText = _match[2], linkUrl = _match[3]; // We don't filter this match here by shouldAutoLinkifyMatch // because the intent of creating a link is clear var url = (0, _utils.normalizeUrl)(linkUrl).trim(); var markType = schema.mark('link', { href: url }); var tr = state.tr.replaceWith(start + prefix.length, end, schema.text((linkText || '').trim(), [markType])); (0, _card.addLinkMetadata)(state.selection, tr, { inputMethod: _analytics.INPUT_METHOD.FORMATTING }); var skipAnalytics = (_toolbarKey$getState$2 = (_toolbarKey$getState2 = _toolbarButtons.toolbarKey.getState(state)) === null || _toolbarKey$getState2 === void 0 ? void 0 : _toolbarKey$getState2.skipAnalytics) !== null && _toolbarKey$getState$2 !== void 0 ? _toolbarKey$getState$2 : false; if (skipAnalytics) { return tr; } editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent((0, _utils.getLinkCreationAnalyticsEvent)(_analytics.INPUT_METHOD.FORMATTING, url))(tr); return tr; }); return new _safePlugin.SafePlugin((0, _prosemirrorInputRules.createPlugin)('hyperlink', [urlWithASpaceRule, markdownLinkRule], autoLinkOnBlur ? { checkOnBlur: true, appendTextOnBlur: ' ' } : undefined)); } var _default = exports.default = createInputRulePlugin;