@atlaskit/editor-plugin-paste 12.1.2 → 12.1.4
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 +16 -0
- package/dist/cjs/pm-plugins/media.js +41 -0
- package/dist/es2019/pm-plugins/media.js +41 -0
- package/dist/esm/pm-plugins/media.js +41 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-paste
|
|
2
2
|
|
|
3
|
+
## 12.1.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 12.1.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`dbe0d03cebcd7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/dbe0d03cebcd7) -
|
|
14
|
+
Fix media copy/paste from rendered comments: only hoist external images from mediaSingle wrappers,
|
|
15
|
+
preserve internal media with valid file references so ProseMirror can reconstruct proper media
|
|
16
|
+
nodes. Remove debug console.log.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
|
|
3
19
|
## 12.1.2
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -146,6 +146,29 @@ function canContainImage(element) {
|
|
|
146
146
|
return VALID_TAGS_CONTAINER.indexOf(element.tagName) !== -1;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Determines whether an `<img>` inside a mediaSingle wrapper should be hoisted
|
|
151
|
+
* out of the wrapper and treated as a standalone external image.
|
|
152
|
+
*
|
|
153
|
+
* This should only happen when:
|
|
154
|
+
* - The image source is external (data-source="external"), and
|
|
155
|
+
* - The media wrapper has no valid file reference (no data-id), meaning
|
|
156
|
+
* ProseMirror cannot reconstruct a proper internal media node from the wrapper.
|
|
157
|
+
*
|
|
158
|
+
* When the wrapper has a valid file reference (e.g. internal media from Jira),
|
|
159
|
+
* we leave the wrapper intact so ProseMirror can reconstruct a proper internal media node with the file reference and fetch fresh auth tokens.
|
|
160
|
+
*/
|
|
161
|
+
function shouldHoistFromMediaSingle(imageTag) {
|
|
162
|
+
var _mediaNode$hasAttribu;
|
|
163
|
+
var isExternalSource = imageTag.getAttribute('data-source') === 'external';
|
|
164
|
+
if (!isExternalSource) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
var mediaNode = imageTag.closest('[data-node-type="media"]');
|
|
168
|
+
var hasFileReference = (_mediaNode$hasAttribu = mediaNode === null || mediaNode === void 0 ? void 0 : mediaNode.hasAttribute('data-id')) !== null && _mediaNode$hasAttribu !== void 0 ? _mediaNode$hasAttribu : false;
|
|
169
|
+
return !hasFileReference;
|
|
170
|
+
}
|
|
171
|
+
|
|
149
172
|
/**
|
|
150
173
|
* Given a html string, we attempt to hoist any nested `<img>` tags,
|
|
151
174
|
* not directly wrapped by a `<div>` as ProseMirror no-op's
|
|
@@ -188,6 +211,24 @@ var unwrapNestedMediaElements = exports.unwrapNestedMediaElements = function unw
|
|
|
188
211
|
return;
|
|
189
212
|
}
|
|
190
213
|
|
|
214
|
+
// when copying a jira comment that contains external image (data-source="external"),
|
|
215
|
+
// the 'media' div is like this:
|
|
216
|
+
// <div data-node-type="media"> has no data-id,
|
|
217
|
+
// But when copying a jira comment that contains image that was uploaded to Jira, the div is like this:
|
|
218
|
+
// <div data-node-type="media" data-type="file" data-id="dce9c14b-b857-41fd-9452-5f4ba3a4f679" data-collection="" data-file-name="Screenshot 2026-05-26 at 4.41.05 pm.png" data-file-size="1354355" data-file-mime-type="image/png">
|
|
219
|
+
// ProseMirror fails to parse the media node because it has no data-id,
|
|
220
|
+
// so we hoist the <img> to replace the entire mediaSingle wrapper
|
|
221
|
+
// so the editor can treat it as a plain external image and render/re-upload it correctly.
|
|
222
|
+
var mediaSingleWrapper = imageTag.closest('[data-node-type="mediaSingle"]');
|
|
223
|
+
if (mediaSingleWrapper && shouldHoistFromMediaSingle(imageTag) && (0, _expValEquals.expValEquals)('fix_copy_paste_external_media_renderer_to_editor', 'isEnabled', true)) {
|
|
224
|
+
// Hoist the <img> to replace the entire mediaSingle wrapper
|
|
225
|
+
if (mediaSingleWrapper.parentElement) {
|
|
226
|
+
mediaSingleWrapper.parentElement.insertBefore(imageTag, mediaSingleWrapper);
|
|
227
|
+
mediaSingleWrapper.remove();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
191
232
|
// If either the parent or the image itself contains styles that would make
|
|
192
233
|
// them invisible on copy, dont paste them.
|
|
193
234
|
if (isElementInvisible(mediaParent) || isElementInvisible(imageTag)) {
|
|
@@ -142,6 +142,29 @@ function canContainImage(element) {
|
|
|
142
142
|
return VALID_TAGS_CONTAINER.indexOf(element.tagName) !== -1;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Determines whether an `<img>` inside a mediaSingle wrapper should be hoisted
|
|
147
|
+
* out of the wrapper and treated as a standalone external image.
|
|
148
|
+
*
|
|
149
|
+
* This should only happen when:
|
|
150
|
+
* - The image source is external (data-source="external"), and
|
|
151
|
+
* - The media wrapper has no valid file reference (no data-id), meaning
|
|
152
|
+
* ProseMirror cannot reconstruct a proper internal media node from the wrapper.
|
|
153
|
+
*
|
|
154
|
+
* When the wrapper has a valid file reference (e.g. internal media from Jira),
|
|
155
|
+
* we leave the wrapper intact so ProseMirror can reconstruct a proper internal media node with the file reference and fetch fresh auth tokens.
|
|
156
|
+
*/
|
|
157
|
+
function shouldHoistFromMediaSingle(imageTag) {
|
|
158
|
+
var _mediaNode$hasAttribu;
|
|
159
|
+
const isExternalSource = imageTag.getAttribute('data-source') === 'external';
|
|
160
|
+
if (!isExternalSource) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
const mediaNode = imageTag.closest('[data-node-type="media"]');
|
|
164
|
+
const hasFileReference = (_mediaNode$hasAttribu = mediaNode === null || mediaNode === void 0 ? void 0 : mediaNode.hasAttribute('data-id')) !== null && _mediaNode$hasAttribu !== void 0 ? _mediaNode$hasAttribu : false;
|
|
165
|
+
return !hasFileReference;
|
|
166
|
+
}
|
|
167
|
+
|
|
145
168
|
/**
|
|
146
169
|
* Given a html string, we attempt to hoist any nested `<img>` tags,
|
|
147
170
|
* not directly wrapped by a `<div>` as ProseMirror no-op's
|
|
@@ -184,6 +207,24 @@ export const unwrapNestedMediaElements = html => {
|
|
|
184
207
|
return;
|
|
185
208
|
}
|
|
186
209
|
|
|
210
|
+
// when copying a jira comment that contains external image (data-source="external"),
|
|
211
|
+
// the 'media' div is like this:
|
|
212
|
+
// <div data-node-type="media"> has no data-id,
|
|
213
|
+
// But when copying a jira comment that contains image that was uploaded to Jira, the div is like this:
|
|
214
|
+
// <div data-node-type="media" data-type="file" data-id="dce9c14b-b857-41fd-9452-5f4ba3a4f679" data-collection="" data-file-name="Screenshot 2026-05-26 at 4.41.05 pm.png" data-file-size="1354355" data-file-mime-type="image/png">
|
|
215
|
+
// ProseMirror fails to parse the media node because it has no data-id,
|
|
216
|
+
// so we hoist the <img> to replace the entire mediaSingle wrapper
|
|
217
|
+
// so the editor can treat it as a plain external image and render/re-upload it correctly.
|
|
218
|
+
const mediaSingleWrapper = imageTag.closest('[data-node-type="mediaSingle"]');
|
|
219
|
+
if (mediaSingleWrapper && shouldHoistFromMediaSingle(imageTag) && expValEquals('fix_copy_paste_external_media_renderer_to_editor', 'isEnabled', true)) {
|
|
220
|
+
// Hoist the <img> to replace the entire mediaSingle wrapper
|
|
221
|
+
if (mediaSingleWrapper.parentElement) {
|
|
222
|
+
mediaSingleWrapper.parentElement.insertBefore(imageTag, mediaSingleWrapper);
|
|
223
|
+
mediaSingleWrapper.remove();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
187
228
|
// If either the parent or the image itself contains styles that would make
|
|
188
229
|
// them invisible on copy, dont paste them.
|
|
189
230
|
if (isElementInvisible(mediaParent) || isElementInvisible(imageTag)) {
|
|
@@ -137,6 +137,29 @@ function canContainImage(element) {
|
|
|
137
137
|
return VALID_TAGS_CONTAINER.indexOf(element.tagName) !== -1;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Determines whether an `<img>` inside a mediaSingle wrapper should be hoisted
|
|
142
|
+
* out of the wrapper and treated as a standalone external image.
|
|
143
|
+
*
|
|
144
|
+
* This should only happen when:
|
|
145
|
+
* - The image source is external (data-source="external"), and
|
|
146
|
+
* - The media wrapper has no valid file reference (no data-id), meaning
|
|
147
|
+
* ProseMirror cannot reconstruct a proper internal media node from the wrapper.
|
|
148
|
+
*
|
|
149
|
+
* When the wrapper has a valid file reference (e.g. internal media from Jira),
|
|
150
|
+
* we leave the wrapper intact so ProseMirror can reconstruct a proper internal media node with the file reference and fetch fresh auth tokens.
|
|
151
|
+
*/
|
|
152
|
+
function shouldHoistFromMediaSingle(imageTag) {
|
|
153
|
+
var _mediaNode$hasAttribu;
|
|
154
|
+
var isExternalSource = imageTag.getAttribute('data-source') === 'external';
|
|
155
|
+
if (!isExternalSource) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
var mediaNode = imageTag.closest('[data-node-type="media"]');
|
|
159
|
+
var hasFileReference = (_mediaNode$hasAttribu = mediaNode === null || mediaNode === void 0 ? void 0 : mediaNode.hasAttribute('data-id')) !== null && _mediaNode$hasAttribu !== void 0 ? _mediaNode$hasAttribu : false;
|
|
160
|
+
return !hasFileReference;
|
|
161
|
+
}
|
|
162
|
+
|
|
140
163
|
/**
|
|
141
164
|
* Given a html string, we attempt to hoist any nested `<img>` tags,
|
|
142
165
|
* not directly wrapped by a `<div>` as ProseMirror no-op's
|
|
@@ -179,6 +202,24 @@ export var unwrapNestedMediaElements = function unwrapNestedMediaElements(html)
|
|
|
179
202
|
return;
|
|
180
203
|
}
|
|
181
204
|
|
|
205
|
+
// when copying a jira comment that contains external image (data-source="external"),
|
|
206
|
+
// the 'media' div is like this:
|
|
207
|
+
// <div data-node-type="media"> has no data-id,
|
|
208
|
+
// But when copying a jira comment that contains image that was uploaded to Jira, the div is like this:
|
|
209
|
+
// <div data-node-type="media" data-type="file" data-id="dce9c14b-b857-41fd-9452-5f4ba3a4f679" data-collection="" data-file-name="Screenshot 2026-05-26 at 4.41.05 pm.png" data-file-size="1354355" data-file-mime-type="image/png">
|
|
210
|
+
// ProseMirror fails to parse the media node because it has no data-id,
|
|
211
|
+
// so we hoist the <img> to replace the entire mediaSingle wrapper
|
|
212
|
+
// so the editor can treat it as a plain external image and render/re-upload it correctly.
|
|
213
|
+
var mediaSingleWrapper = imageTag.closest('[data-node-type="mediaSingle"]');
|
|
214
|
+
if (mediaSingleWrapper && shouldHoistFromMediaSingle(imageTag) && expValEquals('fix_copy_paste_external_media_renderer_to_editor', 'isEnabled', true)) {
|
|
215
|
+
// Hoist the <img> to replace the entire mediaSingle wrapper
|
|
216
|
+
if (mediaSingleWrapper.parentElement) {
|
|
217
|
+
mediaSingleWrapper.parentElement.insertBefore(imageTag, mediaSingleWrapper);
|
|
218
|
+
mediaSingleWrapper.remove();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
182
223
|
// If either the parent or the image itself contains styles that would make
|
|
183
224
|
// them invisible on copy, dont paste them.
|
|
184
225
|
if (isElementInvisible(mediaParent) || isElementInvisible(imageTag)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-paste",
|
|
3
|
-
"version": "12.1.
|
|
3
|
+
"version": "12.1.4",
|
|
4
4
|
"description": "Paste plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
"@atlaskit/editor-plugin-expand": "^12.0.0",
|
|
39
39
|
"@atlaskit/editor-plugin-feature-flags": "^10.0.0",
|
|
40
40
|
"@atlaskit/editor-plugin-list": "^13.0.0",
|
|
41
|
-
"@atlaskit/editor-plugin-media": "^13.
|
|
41
|
+
"@atlaskit/editor-plugin-media": "^13.4.0",
|
|
42
42
|
"@atlaskit/editor-plugin-mentions": "^13.3.0",
|
|
43
43
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
44
44
|
"@atlaskit/editor-tables": "^2.10.0",
|
|
45
|
-
"@atlaskit/flag": "^17.
|
|
45
|
+
"@atlaskit/flag": "^17.13.0",
|
|
46
46
|
"@atlaskit/icon": "^35.4.0",
|
|
47
47
|
"@atlaskit/insm": "^0.4.0",
|
|
48
48
|
"@atlaskit/media-client": "^36.3.0",
|
|
49
49
|
"@atlaskit/media-common": "^13.3.0",
|
|
50
50
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
51
51
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
52
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
52
|
+
"@atlaskit/tmp-editor-statsig": "^92.0.0",
|
|
53
53
|
"@atlaskit/tokens": "^13.3.0",
|
|
54
54
|
"@babel/runtime": "^7.0.0",
|
|
55
55
|
"lodash": "^4.17.21",
|