@atlaskit/editor-plugin-paste 15.0.1 → 15.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 CHANGED
@@ -1,5 +1,29 @@
1
1
  # @atlaskit/editor-plugin-paste
2
2
 
3
+ ## 15.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`a006cb2cc79f9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a006cb2cc79f9) -
8
+ Use the GFM markdown transformer for Cmd+V plain-text paste when
9
+ `platform_editor_paste_as_md_use_gfm` is enabled, matching the existing paste-as-markdown
10
+ (Shift+Cmd+V) path.
11
+
12
+ Consumers can inject a converter via `PastePluginOptions.markdownToPmConverter` and gate usage
13
+ with:
14
+
15
+ `expValEquals('platform_editor_paste_as_md_use_gfm', 'isEnabled', true)`.
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies
20
+
21
+ ## 15.0.2
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies
26
+
3
27
  ## 15.0.1
4
28
 
5
29
  ### Patch Changes
@@ -20,7 +20,8 @@ var pastePlugin = exports.pastePlugin = function pastePlugin(_ref) {
20
20
  cardOptions = _ref2.cardOptions,
21
21
  sanitizePrivateContent = _ref2.sanitizePrivateContent,
22
22
  isFullPage = _ref2.isFullPage,
23
- pasteWarningOptions = _ref2.pasteWarningOptions;
23
+ pasteWarningOptions = _ref2.pasteWarningOptions,
24
+ markdownToPmConverter = _ref2.markdownToPmConverter;
24
25
  var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
25
26
  var editorAnalyticsAPI = api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions;
26
27
  return {
@@ -34,7 +35,7 @@ var pastePlugin = exports.pastePlugin = function pastePlugin(_ref) {
34
35
  dispatchAnalyticsEvent = _ref3.dispatchAnalyticsEvent,
35
36
  dispatch = _ref3.dispatch,
36
37
  getIntl = _ref3.getIntl;
37
- return (0, _main.createPlugin)(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions);
38
+ return (0, _main.createPlugin)(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter);
38
39
  }
39
40
  }, {
40
41
  name: 'moveAnalyticsPlugin',
@@ -40,6 +40,7 @@ var _createClipboardTextSerializer = require("./create-clipboard-text-serializer
40
40
  var _pluginFactory = require("./plugin-factory");
41
41
  var _util = require("./util");
42
42
  var _handleVSCodeBlock = require("./util/edge-cases/handleVSCodeBlock");
43
+ var _getMarkdownSlice = require("./util/get-markdown-slice");
43
44
  var _handlers = require("./util/handlers");
44
45
  var _normalizePastedCodeBlockAttrs = require("./util/normalize-pasted-code-block-attrs");
45
46
  var _syncBlock2 = require("./util/sync-block");
@@ -85,11 +86,14 @@ function isSharePointUrl(url) {
85
86
  return false;
86
87
  }
87
88
  }
88
- function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions) {
89
+ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter) {
89
90
  var _pluginInjectionApi$a;
90
91
  var editorAnalyticsAPI = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions;
91
92
  var atlassianMarkDownParser = new _editorMarkdownTransformer.MarkdownTransformer(schema, _paste.md);
92
93
  function getMarkdownSlice(text, openStart, openEnd) {
94
+ if (markdownToPmConverter && (0, _expValEquals.expValEquals)('platform_editor_paste_as_md_use_gfm', 'isEnabled', true)) {
95
+ return (0, _getMarkdownSlice.getMarkdownSliceViaGfm)(text, schema, openStart, openEnd, markdownToPmConverter);
96
+ }
93
97
  var escapedTextInput = (0, _util.escapeBackslashAndLinksExceptCodeBlock)(text);
94
98
  var doc = atlassianMarkDownParser.parse(escapedTextInput);
95
99
  if (doc && doc.content) {
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getMarkdownSliceViaGfm = getMarkdownSliceViaGfm;
7
+ var _monitoring = require("@atlaskit/editor-common/monitoring");
8
+ var _model = require("@atlaskit/editor-prosemirror/model");
9
+ var _index = require("./index");
10
+ /**
11
+ * Convert plain-text markdown to a ProseMirror Slice using the GFM converter.
12
+ *
13
+ * Only called when `platform_editor_paste_as_md_use_gfm` is enabled AND a
14
+ * `markdownToPmConverter` is provided. Returns `undefined` if the converter
15
+ * throws or produces an empty document — the caller will propagate `undefined`
16
+ * without falling back to the legacy MarkdownTransformer.
17
+ */
18
+ function getMarkdownSliceViaGfm(text, schema, openStart, openEnd, markdownToPmConverter) {
19
+ // GFM parsers (e.g. markdownToAdf) natively recognise raw URLs as autolinks per
20
+ // the CommonMark spec — they do not need the `<url>` angle-bracket wrapping that
21
+ // the legacy MarkdownTransformer requires. Passing skipLinkEscaping: true avoids
22
+ // double-processing URLs and lets the GFM parser handle them correctly.
23
+ var escapedTextInput = (0, _index.escapeBackslashAndLinksExceptCodeBlock)(text, {
24
+ skipLinkEscaping: true
25
+ });
26
+ try {
27
+ var doc = schema.nodes.doc.createAndFill({}, markdownToPmConverter({
28
+ markdown: escapedTextInput,
29
+ schema: schema
30
+ }));
31
+ if (doc && doc.content) {
32
+ return new _model.Slice(doc.content, openStart, openEnd);
33
+ }
34
+ } catch (e) {
35
+ void (0, _monitoring.logException)(e instanceof Error ? e : new Error(String(e)), {
36
+ location: 'editor-plugin-paste/getMarkdownSlice'
37
+ });
38
+ }
39
+ return undefined;
40
+ }
@@ -140,7 +140,8 @@ function escapeLinks(text) {
140
140
  * const input = 'This is a link: https://example.com and a backslash: \\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```';
141
141
  * const output = escapeBackslashAndLinksExceptCodeBlock(input); // 'This is a link: <https://example.com> and a backslash: \\\\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```'
142
142
  */
143
- function escapeBackslashAndLinksExceptCodeBlock(textInput) {
143
+ function escapeBackslashAndLinksExceptCodeBlock(textInput, options) {
144
+ var shouldEscapeLinks = !(options !== null && options !== void 0 && options.skipLinkEscaping);
144
145
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
145
146
  var isInsideCodeBlock = false;
146
147
  var lines = textInput.split('\n');
@@ -162,7 +163,9 @@ function escapeBackslashAndLinksExceptCodeBlock(textInput) {
162
163
  // Ignored via go/ees005
163
164
  // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed)
164
165
  var escaped = line.replace(/\\/g, '\\\\');
165
- escaped = escapeLinks(escaped);
166
+ if (shouldEscapeLinks) {
167
+ escaped = escapeLinks(escaped);
168
+ }
166
169
  return escaped;
167
170
  }
168
171
  }).join('\n');
@@ -14,7 +14,8 @@ export const pastePlugin = ({
14
14
  cardOptions,
15
15
  sanitizePrivateContent,
16
16
  isFullPage,
17
- pasteWarningOptions
17
+ pasteWarningOptions,
18
+ markdownToPmConverter
18
19
  } = config !== null && config !== void 0 ? config : {};
19
20
  const featureFlags = (api === null || api === void 0 ? void 0 : (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
20
21
  const editorAnalyticsAPI = api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions;
@@ -29,7 +30,7 @@ export const pastePlugin = ({
29
30
  dispatchAnalyticsEvent,
30
31
  dispatch,
31
32
  getIntl
32
- }) => createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions)
33
+ }) => createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter)
33
34
  }, {
34
35
  name: 'moveAnalyticsPlugin',
35
36
  plugin: ({
@@ -30,6 +30,7 @@ import { createClipboardTextSerializer } from './create-clipboard-text-serialize
30
30
  import { createPluginState, pluginKey as stateKey } from './plugin-factory';
31
31
  import { escapeBackslashAndLinksExceptCodeBlock, getPasteSource, htmlContainsSingleFile, htmlHasInvalidLinkTags, isPastedFromExcel, isPastedFromWord, removeDuplicateInvalidLinks, transformUnsupportedBlockCardToInline } from './util';
32
32
  import { handleVSCodeBlock } from './util/edge-cases/handleVSCodeBlock';
33
+ import { getMarkdownSliceViaGfm } from './util/get-markdown-slice';
33
34
  import { applyContainerNodeTransformToSlice, splitTablesOutOfPanelHtml, handleMacroAutoConvert, handleMention, handleParagraphBlockMarks, handlePasteExpand, handleTableContentPasteInBodiedExtension } from './util/handlers';
34
35
  import { normalizePastedCodeBlockAttrs } from './util/normalize-pasted-code-block-attrs';
35
36
  import { handleSyncBlocksPaste } from './util/sync-block';
@@ -74,11 +75,14 @@ export function isSharePointUrl(url) {
74
75
  return false;
75
76
  }
76
77
  }
77
- export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions) {
78
+ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter) {
78
79
  var _pluginInjectionApi$a;
79
80
  const editorAnalyticsAPI = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions;
80
81
  const atlassianMarkDownParser = new MarkdownTransformer(schema, md);
81
82
  function getMarkdownSlice(text, openStart, openEnd) {
83
+ if (markdownToPmConverter && expValEquals('platform_editor_paste_as_md_use_gfm', 'isEnabled', true)) {
84
+ return getMarkdownSliceViaGfm(text, schema, openStart, openEnd, markdownToPmConverter);
85
+ }
82
86
  const escapedTextInput = escapeBackslashAndLinksExceptCodeBlock(text);
83
87
  const doc = atlassianMarkDownParser.parse(escapedTextInput);
84
88
  if (doc && doc.content) {
@@ -0,0 +1,35 @@
1
+ import { logException } from '@atlaskit/editor-common/monitoring';
2
+ import { Slice } from '@atlaskit/editor-prosemirror/model';
3
+ import { escapeBackslashAndLinksExceptCodeBlock } from './index';
4
+
5
+ /**
6
+ * Convert plain-text markdown to a ProseMirror Slice using the GFM converter.
7
+ *
8
+ * Only called when `platform_editor_paste_as_md_use_gfm` is enabled AND a
9
+ * `markdownToPmConverter` is provided. Returns `undefined` if the converter
10
+ * throws or produces an empty document — the caller will propagate `undefined`
11
+ * without falling back to the legacy MarkdownTransformer.
12
+ */
13
+ export function getMarkdownSliceViaGfm(text, schema, openStart, openEnd, markdownToPmConverter) {
14
+ // GFM parsers (e.g. markdownToAdf) natively recognise raw URLs as autolinks per
15
+ // the CommonMark spec — they do not need the `<url>` angle-bracket wrapping that
16
+ // the legacy MarkdownTransformer requires. Passing skipLinkEscaping: true avoids
17
+ // double-processing URLs and lets the GFM parser handle them correctly.
18
+ const escapedTextInput = escapeBackslashAndLinksExceptCodeBlock(text, {
19
+ skipLinkEscaping: true
20
+ });
21
+ try {
22
+ const doc = schema.nodes.doc.createAndFill({}, markdownToPmConverter({
23
+ markdown: escapedTextInput,
24
+ schema
25
+ }));
26
+ if (doc && doc.content) {
27
+ return new Slice(doc.content, openStart, openEnd);
28
+ }
29
+ } catch (e) {
30
+ void logException(e instanceof Error ? e : new Error(String(e)), {
31
+ location: 'editor-plugin-paste/getMarkdownSlice'
32
+ });
33
+ }
34
+ return undefined;
35
+ }
@@ -119,7 +119,8 @@ export function escapeLinks(text) {
119
119
  * const input = 'This is a link: https://example.com and a backslash: \\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```';
120
120
  * const output = escapeBackslashAndLinksExceptCodeBlock(input); // 'This is a link: <https://example.com> and a backslash: \\\\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```'
121
121
  */
122
- export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
122
+ export function escapeBackslashAndLinksExceptCodeBlock(textInput, options) {
123
+ const shouldEscapeLinks = !(options !== null && options !== void 0 && options.skipLinkEscaping);
123
124
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
124
125
  let isInsideCodeBlock = false;
125
126
  const lines = textInput.split('\n');
@@ -141,7 +142,9 @@ export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
141
142
  // Ignored via go/ees005
142
143
  // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed)
143
144
  let escaped = line.replace(/\\/g, '\\\\');
144
- escaped = escapeLinks(escaped);
145
+ if (shouldEscapeLinks) {
146
+ escaped = escapeLinks(escaped);
147
+ }
145
148
  return escaped;
146
149
  }
147
150
  }).join('\n');
@@ -13,7 +13,8 @@ export var pastePlugin = function pastePlugin(_ref) {
13
13
  cardOptions = _ref2.cardOptions,
14
14
  sanitizePrivateContent = _ref2.sanitizePrivateContent,
15
15
  isFullPage = _ref2.isFullPage,
16
- pasteWarningOptions = _ref2.pasteWarningOptions;
16
+ pasteWarningOptions = _ref2.pasteWarningOptions,
17
+ markdownToPmConverter = _ref2.markdownToPmConverter;
17
18
  var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
18
19
  var editorAnalyticsAPI = api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions;
19
20
  return {
@@ -27,7 +28,7 @@ export var pastePlugin = function pastePlugin(_ref) {
27
28
  dispatchAnalyticsEvent = _ref3.dispatchAnalyticsEvent,
28
29
  dispatch = _ref3.dispatch,
29
30
  getIntl = _ref3.getIntl;
30
- return createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions);
31
+ return createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, api, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter);
31
32
  }
32
33
  }, {
33
34
  name: 'moveAnalyticsPlugin',
@@ -35,6 +35,7 @@ import { createClipboardTextSerializer } from './create-clipboard-text-serialize
35
35
  import { createPluginState, pluginKey as stateKey } from './plugin-factory';
36
36
  import { escapeBackslashAndLinksExceptCodeBlock, getPasteSource, htmlContainsSingleFile, htmlHasInvalidLinkTags, isPastedFromExcel, isPastedFromWord, removeDuplicateInvalidLinks, transformUnsupportedBlockCardToInline } from './util';
37
37
  import { handleVSCodeBlock } from './util/edge-cases/handleVSCodeBlock';
38
+ import { getMarkdownSliceViaGfm } from './util/get-markdown-slice';
38
39
  import { applyContainerNodeTransformToSlice, splitTablesOutOfPanelHtml, handleMacroAutoConvert, handleMention, handleParagraphBlockMarks, handlePasteExpand, handleTableContentPasteInBodiedExtension } from './util/handlers';
39
40
  import { normalizePastedCodeBlockAttrs } from './util/normalize-pasted-code-block-attrs';
40
41
  import { handleSyncBlocksPaste } from './util/sync-block';
@@ -77,11 +78,14 @@ export function isSharePointUrl(url) {
77
78
  return false;
78
79
  }
79
80
  }
80
- export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions) {
81
+ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pluginInjectionApi, getIntl, cardOptions, sanitizePrivateContent, providerFactory, pasteWarningOptions, markdownToPmConverter) {
81
82
  var _pluginInjectionApi$a;
82
83
  var editorAnalyticsAPI = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions;
83
84
  var atlassianMarkDownParser = new MarkdownTransformer(schema, md);
84
85
  function getMarkdownSlice(text, openStart, openEnd) {
86
+ if (markdownToPmConverter && expValEquals('platform_editor_paste_as_md_use_gfm', 'isEnabled', true)) {
87
+ return getMarkdownSliceViaGfm(text, schema, openStart, openEnd, markdownToPmConverter);
88
+ }
85
89
  var escapedTextInput = escapeBackslashAndLinksExceptCodeBlock(text);
86
90
  var doc = atlassianMarkDownParser.parse(escapedTextInput);
87
91
  if (doc && doc.content) {
@@ -0,0 +1,35 @@
1
+ import { logException } from '@atlaskit/editor-common/monitoring';
2
+ import { Slice } from '@atlaskit/editor-prosemirror/model';
3
+ import { escapeBackslashAndLinksExceptCodeBlock } from './index';
4
+
5
+ /**
6
+ * Convert plain-text markdown to a ProseMirror Slice using the GFM converter.
7
+ *
8
+ * Only called when `platform_editor_paste_as_md_use_gfm` is enabled AND a
9
+ * `markdownToPmConverter` is provided. Returns `undefined` if the converter
10
+ * throws or produces an empty document — the caller will propagate `undefined`
11
+ * without falling back to the legacy MarkdownTransformer.
12
+ */
13
+ export function getMarkdownSliceViaGfm(text, schema, openStart, openEnd, markdownToPmConverter) {
14
+ // GFM parsers (e.g. markdownToAdf) natively recognise raw URLs as autolinks per
15
+ // the CommonMark spec — they do not need the `<url>` angle-bracket wrapping that
16
+ // the legacy MarkdownTransformer requires. Passing skipLinkEscaping: true avoids
17
+ // double-processing URLs and lets the GFM parser handle them correctly.
18
+ var escapedTextInput = escapeBackslashAndLinksExceptCodeBlock(text, {
19
+ skipLinkEscaping: true
20
+ });
21
+ try {
22
+ var doc = schema.nodes.doc.createAndFill({}, markdownToPmConverter({
23
+ markdown: escapedTextInput,
24
+ schema: schema
25
+ }));
26
+ if (doc && doc.content) {
27
+ return new Slice(doc.content, openStart, openEnd);
28
+ }
29
+ } catch (e) {
30
+ void logException(e instanceof Error ? e : new Error(String(e)), {
31
+ location: 'editor-plugin-paste/getMarkdownSlice'
32
+ });
33
+ }
34
+ return undefined;
35
+ }
@@ -120,7 +120,8 @@ export function escapeLinks(text) {
120
120
  * const input = 'This is a link: https://example.com and a backslash: \\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```';
121
121
  * const output = escapeBackslashAndLinksExceptCodeBlock(input); // 'This is a link: <https://example.com> and a backslash: \\\\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```'
122
122
  */
123
- export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
123
+ export function escapeBackslashAndLinksExceptCodeBlock(textInput, options) {
124
+ var shouldEscapeLinks = !(options !== null && options !== void 0 && options.skipLinkEscaping);
124
125
  // ref: https://spec.commonmark.org/0.31.2/#fenced-code-blocks
125
126
  var isInsideCodeBlock = false;
126
127
  var lines = textInput.split('\n');
@@ -142,7 +143,9 @@ export function escapeBackslashAndLinksExceptCodeBlock(textInput) {
142
143
  // Ignored via go/ees005
143
144
  // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed)
144
145
  var escaped = line.replace(/\\/g, '\\\\');
145
- escaped = escapeLinks(escaped);
146
+ if (shouldEscapeLinks) {
147
+ escaped = escapeLinks(escaped);
148
+ }
146
149
  return escaped;
147
150
  }
148
151
  }).join('\n');
@@ -1 +1 @@
1
- export type { PastePlugin, PastePluginOptions, PastePluginState, LastContentPasted, PastePluginDependencies, ActiveFlag, } from '../pastePluginType';
1
+ export type { PastePlugin, PastePluginOptions, PastePluginState, LastContentPasted, PastePluginDependencies, ActiveFlag, MarkdownToPmConverter, } from '../pastePluginType';
@@ -12,7 +12,7 @@ import type { FeatureFlagsPlugin } from '@atlaskit/editor-plugin-feature-flags';
12
12
  import type { ListPlugin } from '@atlaskit/editor-plugin-list';
13
13
  import type { MediaPlugin } from '@atlaskit/editor-plugin-media';
14
14
  import type { MentionsPlugin } from '@atlaskit/editor-plugin-mentions';
15
- import type { Slice } from '@atlaskit/editor-prosemirror/model';
15
+ import type { Fragment, Schema, Slice } from '@atlaskit/editor-prosemirror/model';
16
16
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
17
17
  export declare enum FLAG_TYPE {
18
18
  WARNING = "warning",
@@ -62,9 +62,19 @@ export type LastContentPasted = {
62
62
  sourcePastedSlice?: Slice;
63
63
  text?: string;
64
64
  };
65
+ export type MarkdownToPmConverter = (params: {
66
+ markdown: string;
67
+ schema: Schema;
68
+ }) => Fragment;
65
69
  export type PastePluginOptions = {
66
70
  cardOptions?: CardOptions;
67
71
  isFullPage?: boolean;
72
+ /**
73
+ * Optional markdown → ProseMirror fragment converter used for plain-text
74
+ * Cmd+V paste when `platform_editor_paste_as_md_use_gfm` is enabled.
75
+ * When omitted or the experiment is off, the legacy MarkdownTransformer is used.
76
+ */
77
+ markdownToPmConverter?: MarkdownToPmConverter;
68
78
  pasteWarningOptions?: PasteWarningOptions;
69
79
  sanitizePrivateContent?: boolean;
70
80
  };
@@ -8,7 +8,7 @@ import type { ExtractInjectionAPI, FeatureFlags, PasteWarningOptions } from '@at
8
8
  import type { Schema } from '@atlaskit/editor-prosemirror/model';
9
9
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
10
10
  import type { PastePlugin } from '../index';
11
- import type { PastePluginState } from '../pastePluginType';
11
+ import type { MarkdownToPmConverter, PastePluginState } from '../pastePluginType';
12
12
  export declare const isInsideBlockQuote: (state: EditorState) => boolean;
13
13
  export declare function isSharePointUrl(url: string | undefined): boolean;
14
- export declare function createPlugin(schema: Schema, dispatchAnalyticsEvent: DispatchAnalyticsEvent, dispatch: Dispatch, featureFlags: FeatureFlags, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined, getIntl: () => IntlShape, cardOptions?: CardOptions, sanitizePrivateContent?: boolean, providerFactory?: ProviderFactory, pasteWarningOptions?: PasteWarningOptions): SafePlugin<PastePluginState>;
14
+ export declare function createPlugin(schema: Schema, dispatchAnalyticsEvent: DispatchAnalyticsEvent, dispatch: Dispatch, featureFlags: FeatureFlags, pluginInjectionApi: ExtractInjectionAPI<PastePlugin> | undefined, getIntl: () => IntlShape, cardOptions?: CardOptions, sanitizePrivateContent?: boolean, providerFactory?: ProviderFactory, pasteWarningOptions?: PasteWarningOptions, markdownToPmConverter?: MarkdownToPmConverter): SafePlugin<PastePluginState>;
@@ -0,0 +1,14 @@
1
+ import type { Fragment, Schema } from '@atlaskit/editor-prosemirror/model';
2
+ import { Slice } from '@atlaskit/editor-prosemirror/model';
3
+ /**
4
+ * Convert plain-text markdown to a ProseMirror Slice using the GFM converter.
5
+ *
6
+ * Only called when `platform_editor_paste_as_md_use_gfm` is enabled AND a
7
+ * `markdownToPmConverter` is provided. Returns `undefined` if the converter
8
+ * throws or produces an empty document — the caller will propagate `undefined`
9
+ * without falling back to the legacy MarkdownTransformer.
10
+ */
11
+ export declare function getMarkdownSliceViaGfm(text: string, schema: Schema, openStart: number, openEnd: number, markdownToPmConverter: (params: {
12
+ markdown: string;
13
+ schema: Schema;
14
+ }) => Fragment): Slice | undefined;
@@ -33,7 +33,9 @@ export declare function escapeLinks(text: string): string;
33
33
  * const input = 'This is a link: https://example.com and a backslash: \\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```';
34
34
  * const output = escapeBackslashAndLinksExceptCodeBlock(input); // 'This is a link: <https://example.com> and a backslash: \\\\\n```\ncode block https://example.com not escaped\ncode block \\ not escaped\n```'
35
35
  */
36
- export declare function escapeBackslashAndLinksExceptCodeBlock(textInput: string): string;
36
+ export declare function escapeBackslashAndLinksExceptCodeBlock(textInput: string, options?: {
37
+ skipLinkEscaping?: boolean;
38
+ }): string;
37
39
  export declare function hasOnlyNodesOfType(...nodeTypes: NodeType[]): (slice: Slice) => boolean;
38
40
  export declare function applyTextMarksToSlice(schema: Schema, marks?: readonly Mark[]): (slice: Slice) => Slice;
39
41
  export declare function isEmptyNode(node: PMNode | null | undefined): boolean | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-paste",
3
- "version": "15.0.1",
3
+ "version": "15.1.0",
4
4
  "description": "Paste plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  "@atlaskit/editor-plugin-feature-flags": "^13.0.0",
32
32
  "@atlaskit/editor-plugin-list": "^16.0.0",
33
33
  "@atlaskit/editor-plugin-media": "^16.0.0",
34
- "@atlaskit/editor-plugin-mentions": "^16.0.0",
34
+ "@atlaskit/editor-plugin-mentions": "^16.1.0",
35
35
  "@atlaskit/editor-prosemirror": "^8.0.0",
36
36
  "@atlaskit/editor-tables": "^3.0.0",
37
37
  "@atlaskit/flag": "^18.2.0",
@@ -42,14 +42,14 @@
42
42
  "@atlaskit/platform-feature-experiments": "^0.3.0",
43
43
  "@atlaskit/platform-feature-flags": "^2.1.0",
44
44
  "@atlaskit/prosemirror-history": "^1.1.0",
45
- "@atlaskit/tmp-editor-statsig": "^143.0.0",
46
- "@atlaskit/tokens": "^16.4.0",
45
+ "@atlaskit/tmp-editor-statsig": "^145.0.0",
46
+ "@atlaskit/tokens": "^16.5.0",
47
47
  "@babel/runtime": "^7.0.0",
48
48
  "lodash": "^4.17.21",
49
49
  "uuid": "^3.1.0"
50
50
  },
51
51
  "peerDependencies": {
52
- "@atlaskit/editor-common": "^118.1.0",
52
+ "@atlaskit/editor-common": "^118.2.0",
53
53
  "react": "^18.2.0 || ^19.2.0",
54
54
  "react-dom": "^18.2.0 || ^19.2.0",
55
55
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"