@atlaskit/editor-jira-transformer 8.2.3 → 8.2.5

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.
@@ -2,27 +2,27 @@ import { normalizeHexColor } from '@atlaskit/adf-schema';
2
2
  import { isSchemaWithLists, isSchemaWithMentions, isSchemaWithLinks, isSchemaWithAdvancedTextFormattingMarks, isSchemaWithCodeBlock, isSchemaWithBlockQuotes, isSchemaWithMedia, isSchemaWithSubSupMark, isSchemaWithTextColor, isSchemaWithTables } from '@atlaskit/adf-schema/schema-jira';
3
3
  import { Fragment } from 'prosemirror-model';
4
4
  import { mapImageToEmoji } from './emojiHelper';
5
+
5
6
  /**
6
7
  * Ensure that each node in the fragment is a block, wrapping
7
8
  * in a block node if necessary.
8
9
  */
9
-
10
10
  export function ensureBlocks(fragment, schema, nodeType) {
11
11
  // If all the nodes are inline, we want to wrap in a single paragraph.
12
12
  if (schema.nodes.paragraph.validContent(fragment)) {
13
13
  return Fragment.fromArray([schema.nodes.paragraph.createChecked({}, fragment)]);
14
- } // Either all the nodes are blocks, or a mix of inline and blocks.
15
- // We convert each (if any) inline nodes to blocks.
14
+ }
16
15
 
16
+ // Either all the nodes are blocks, or a mix of inline and blocks.
17
+ // We convert each (if any) inline nodes to blocks.
18
+ const blockNodes = [];
17
19
 
18
- const blockNodes = []; // Following if condition has been added as fix for #ED-3431.
20
+ // Following if condition has been added as fix for #ED-3431.
19
21
  // First child of list-item should be paragraph,
20
22
  // if that is not the case paragraph requires to be added.
21
-
22
23
  if (nodeType && nodeType === schema.nodes.listItem && fragment.firstChild && (fragment.firstChild.type === schema.nodes.bulletList || fragment.firstChild.type === schema.nodes.orderedList)) {
23
24
  blockNodes.push(schema.nodes.paragraph.createAndFill());
24
25
  }
25
-
26
26
  fragment.forEach(child => {
27
27
  if (child.isBlock) {
28
28
  blockNodes.push(child);
@@ -32,10 +32,10 @@ export function ensureBlocks(fragment, schema, nodeType) {
32
32
  });
33
33
  return Fragment.fromArray(blockNodes);
34
34
  }
35
+
35
36
  /**
36
37
  * This function will convert all content to inline nodes
37
38
  */
38
-
39
39
  export const ensureInline = (schema, content, supportedMarks) => {
40
40
  const result = [];
41
41
  content.forEach(node => {
@@ -43,9 +43,8 @@ export const ensureInline = (schema, content, supportedMarks) => {
43
43
  const filteredMarks = node.marks.filter(mark => mark.isInSet(supportedMarks));
44
44
  result.push(node.mark(filteredMarks));
45
45
  return;
46
- } // We replace an non-inline node with UnsupportedInline node
47
-
48
-
46
+ }
47
+ // We replace an non-inline node with UnsupportedInline node
49
48
  result.push(schema.text(node.textContent));
50
49
  });
51
50
  return Fragment.fromArray(result);
@@ -55,59 +54,47 @@ export function convert(content, node, schema) {
55
54
  if (node.nodeType === Node.TEXT_NODE) {
56
55
  const text = node.textContent;
57
56
  return text ? schema.text(text) : null;
58
- } // marks and nodes
59
-
57
+ }
60
58
 
59
+ // marks and nodes
61
60
  if (node instanceof HTMLElement) {
62
61
  const tag = node.tagName.toUpperCase();
63
-
64
62
  switch (tag) {
65
63
  // Marks
66
64
  case 'DEL':
67
65
  if (!isSchemaWithAdvancedTextFormattingMarks(schema)) {
68
66
  return null;
69
67
  }
70
-
71
68
  return addMarks(content, [schema.marks.strike.create()]);
72
-
73
69
  case 'B':
74
70
  return addMarks(content, [schema.marks.strong.create()]);
75
-
76
71
  case 'EM':
77
72
  return addMarks(content, [schema.marks.em.create()]);
78
-
79
73
  case 'TT':
80
74
  if (!isSchemaWithAdvancedTextFormattingMarks(schema)) {
81
75
  return null;
82
76
  }
83
-
84
77
  return addMarks(content, [schema.marks.code.create()]);
85
-
86
78
  case 'SUB':
87
79
  case 'SUP':
88
80
  if (!isSchemaWithSubSupMark(schema)) {
89
81
  return null;
90
82
  }
91
-
92
83
  const type = tag === 'SUB' ? 'sub' : 'sup';
93
84
  return addMarks(content, [schema.marks.subsup.create({
94
85
  type
95
86
  })]);
96
-
97
87
  case 'INS':
98
88
  return addMarks(content, [schema.marks.underline.create()]);
99
-
100
89
  case 'FONT':
101
90
  if (!isSchemaWithTextColor(schema)) {
102
91
  return null;
103
92
  }
104
-
105
93
  const color = normalizeHexColor(node.getAttribute('color'), '#333333');
106
94
  return color ? addMarks(content, [schema.marks.textColor.create({
107
95
  color
108
96
  })]) : content;
109
97
  // Nodes
110
-
111
98
  case 'A':
112
99
  if (node.className === 'user-hover' && isSchemaWithMentions(schema)) {
113
100
  return schema.nodes.mention.createChecked({
@@ -115,18 +102,15 @@ export function convert(content, node, schema) {
115
102
  text: node.textContent
116
103
  });
117
104
  }
118
-
119
105
  if (node.className.match('jira-issue-macro-key') || !content || !isSchemaWithLinks(schema)) {
120
106
  return null;
121
107
  }
122
-
123
108
  const href = node.getAttribute('href');
124
109
  const title = node.getAttribute('title');
125
110
  return href ? addMarks(content, [schema.marks.link.create({
126
111
  href,
127
112
  title
128
113
  })]) : content;
129
-
130
114
  case 'SPAN':
131
115
  /**
132
116
  * JIRA ISSUE MACROS
@@ -144,14 +128,12 @@ export function convert(content, node, schema) {
144
128
  if (node.className.split(' ').indexOf('jira-issue-macro') > -1) {
145
129
  const jiraKey = node.getAttribute('data-jira-key');
146
130
  const link = node.getElementsByTagName('a')[0];
147
-
148
131
  if (jiraKey && link) {
149
132
  return addMarks(Fragment.from(schema.text(jiraKey)), [schema.marks.link.create({
150
133
  href: link.getAttribute('href'),
151
134
  title: link.getAttribute('title')
152
135
  })]);
153
136
  }
154
-
155
137
  return null;
156
138
  } else if (node.className.match('jira-macro-single-issue-export-pdf')) {
157
139
  return null;
@@ -160,7 +142,6 @@ export function convert(content, node, schema) {
160
142
  return null;
161
143
  } else if (isMedia(node) && isSchemaWithMedia(schema)) {
162
144
  const dataNode = node.querySelector('[data-media-services-id]');
163
-
164
145
  if (dataNode && dataNode instanceof HTMLElement) {
165
146
  const id = dataNode.getAttribute('data-media-services-id');
166
147
  const type = dataNode.getAttribute('data-media-services-type');
@@ -182,22 +163,17 @@ export function convert(content, node, schema) {
182
163
  });
183
164
  }
184
165
  }
185
-
186
166
  break;
187
-
188
167
  case 'IMG':
189
168
  if (node.parentElement && node.parentElement.className.match('jira-issue-macro-key')) {
190
169
  return null;
191
170
  } else if (node.className === 'emoticon') {
192
171
  let emojiResult = mapImageToEmoji(node);
193
-
194
172
  if (emojiResult) {
195
173
  return schema.text(emojiResult);
196
174
  }
197
175
  }
198
-
199
176
  break;
200
-
201
177
  case 'H1':
202
178
  case 'H2':
203
179
  case 'H3':
@@ -206,20 +182,19 @@ export function convert(content, node, schema) {
206
182
  case 'H6':
207
183
  const level = Number(tag.charAt(1));
208
184
  const supportedMarks = [schema.marks.link].filter(mark => !!mark);
209
- return schema.nodes.heading.createChecked( // @see ED-4708
185
+ return schema.nodes.heading.createChecked(
186
+ // @see ED-4708
210
187
  {
211
188
  level: level === 6 ? 5 : level
212
189
  }, schema.nodes.heading.validContent(content) ? content : ensureInline(schema, content, supportedMarks));
213
-
214
190
  case 'BR':
215
191
  return schema.nodes.hardBreak.createChecked();
216
-
217
192
  case 'HR':
218
193
  return schema.nodes.rule.createChecked();
219
-
220
194
  case 'P':
221
195
  if (node.firstElementChild && isMedia(node.firstElementChild)) {
222
196
  // Filter out whitespace text nodes
197
+
223
198
  const {
224
199
  mediaSingle,
225
200
  mediaGroup,
@@ -236,45 +211,37 @@ export function convert(content, node, schema) {
236
211
  } else if (!(child.isText && /^\s*$/.test(child.text || ''))) {
237
212
  hasNonMediaChildren = true;
238
213
  }
239
-
240
214
  contentArray.push(child);
241
215
  });
242
-
243
216
  if (hasNonMediaChildren && contentArray.length) {
244
217
  fragmentArray.push(paragraph.createChecked({}, contentArray));
245
218
  }
246
-
247
219
  if (isSchemaWithMedia(schema) && mediaArray.length) {
248
220
  const mediaNodeType = isMediaSingle(node.firstElementChild) ? mediaSingle : mediaGroup;
249
221
  fragmentArray.push(mediaNodeType.createChecked({}, mediaArray));
250
222
  }
251
-
252
223
  if (fragmentArray.length) {
253
224
  return Fragment.fromArray(fragmentArray);
254
225
  }
255
-
256
226
  return null;
257
227
  }
258
-
259
228
  return schema.nodes.paragraph.createChecked({}, content);
260
- } // lists
261
-
229
+ }
262
230
 
231
+ // lists
263
232
  if (isSchemaWithLists(schema)) {
264
233
  switch (tag) {
265
234
  case 'UL':
266
235
  return schema.nodes.bulletList.createChecked({}, content);
267
-
268
236
  case 'OL':
269
237
  return schema.nodes.orderedList.createChecked({}, content);
270
-
271
238
  case 'LI':
272
239
  const compatibleContent = schema.nodes.listItem.validContent(content) ? content : ensureBlocks(content, schema, schema.nodes.listItem);
273
240
  return schema.nodes.listItem.createChecked({}, compatibleContent);
274
241
  }
275
- } // code block
276
-
242
+ }
277
243
 
244
+ // code block
278
245
  if (isSchemaWithCodeBlock(schema)) {
279
246
  switch (tag) {
280
247
  case 'DIV':
@@ -282,109 +249,89 @@ export function convert(content, node, schema) {
282
249
  return null;
283
250
  } else if (node.className === 'code panel' || node.className === 'preformatted panel') {
284
251
  const pre = node.querySelector('pre');
285
-
286
252
  if (!pre) {
287
253
  return null;
288
254
  }
289
-
290
255
  const language = node.className === 'preformatted panel' ? 'plain' : pre.className.split('-')[1];
291
256
  const textContent = (pre.textContent || '').replace(/\r\n/g, '\n');
292
257
  return schema.nodes.codeBlock.createChecked({
293
258
  language
294
259
  }, textContent ? schema.text(textContent) : undefined);
295
260
  }
296
-
297
261
  break;
298
-
299
262
  case 'PRE':
300
263
  return null;
301
264
  }
302
265
  }
303
-
304
266
  if (isSchemaWithBlockQuotes(schema) && tag === 'BLOCKQUOTE') {
305
267
  let blockquoteContent = content && content.content.length ? content : schema.nodes.paragraph.createChecked();
306
268
  return schema.nodes.blockquote.createChecked({}, blockquoteContent);
307
- } // table
308
-
269
+ }
309
270
 
271
+ // table
310
272
  if (isSchemaWithTables(schema)) {
311
273
  switch (tag) {
312
274
  case 'TABLE':
313
275
  return schema.nodes.table.createChecked({}, content);
314
-
315
276
  case 'TR':
316
277
  return schema.nodes.tableRow.createChecked({}, content);
317
-
318
278
  case 'TD':
319
279
  const tdContent = schema.nodes.tableCell.validContent(content) ? content : ensureBlocks(content, schema);
320
280
  return schema.nodes.tableCell.createChecked({}, tdContent);
321
-
322
281
  case 'TH':
323
282
  const thContent = schema.nodes.tableHeader.validContent(content) ? content : ensureBlocks(content, schema);
324
283
  return schema.nodes.tableHeader.createChecked({}, thContent);
325
284
  }
326
285
  }
327
286
  }
328
-
329
287
  return;
330
288
  }
289
+
331
290
  /*
332
291
  * Flattens DOM tree into single array
333
292
  */
334
-
335
293
  export function bfsOrder(root) {
336
294
  const inqueue = [root];
337
295
  const outqueue = [];
338
296
  let elem;
339
-
340
297
  while (elem = inqueue.shift()) {
341
298
  outqueue.push(elem);
342
299
  let childIndex;
343
-
344
300
  for (childIndex = 0; childIndex < elem.childNodes.length; childIndex++) {
345
301
  const child = elem.childNodes[childIndex];
346
-
347
302
  switch (child.nodeType) {
348
303
  case Node.ELEMENT_NODE:
349
304
  case Node.TEXT_NODE:
350
305
  inqueue.push(child);
351
306
  break;
352
-
353
307
  default:
354
308
  // eslint-disable-next-line no-console
355
309
  console.error(`Not pushing: ${child.nodeType} ${child.nodeName}`);
356
310
  }
357
311
  }
358
312
  }
359
-
360
313
  outqueue.shift();
361
314
  return outqueue;
362
315
  }
316
+
363
317
  /**
364
318
  * Create a fragment by adding a set of marks to each node.
365
319
  */
366
-
367
320
  function addMarks(fragment, marks) {
368
321
  let result = fragment;
369
-
370
322
  for (let i = 0; i < fragment.childCount; i++) {
371
323
  const child = result.child(i);
372
324
  let newChild = child;
373
-
374
325
  for (const mark of marks) {
375
326
  newChild = newChild.mark(mark.addToSet(newChild.marks));
376
327
  }
377
-
378
328
  result = result.replaceChild(i, newChild);
379
329
  }
380
-
381
330
  return result;
382
331
  }
383
-
384
332
  function getNodeName(node) {
385
333
  return node.nodeName.toUpperCase();
386
334
  }
387
-
388
335
  function isMedia(node) {
389
336
  if (node && node instanceof HTMLElement) {
390
337
  if (node.parentNode && getNodeName(node.parentNode) === 'P') {
@@ -393,23 +340,18 @@ function isMedia(node) {
393
340
  }
394
341
  }
395
342
  }
396
-
397
343
  return false;
398
344
  }
399
-
400
345
  function isMediaSingle(node) {
401
346
  if (isMedia(node)) {
402
347
  const dataNode = node.querySelector('[data-media-services-id]');
403
-
404
348
  if (dataNode instanceof HTMLElement) {
405
349
  const width = parseInt(dataNode.getAttribute('data-width') || '', 10);
406
350
  const height = parseInt(dataNode.getAttribute('data-height') || '', 10);
407
-
408
351
  if (node.parentNode.classList.contains('mediaSingle') && width && height) {
409
352
  return true;
410
353
  }
411
354
  }
412
355
  }
413
-
414
356
  return false;
415
357
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-jira-transformer",
3
- "version": "8.2.3",
3
+ "version": "8.2.5",
4
4
  "sideEffects": false
5
5
  }
@@ -1,54 +1,44 @@
1
1
  function getNodeName(node) {
2
2
  return node && node.nodeName.toUpperCase();
3
3
  }
4
-
5
4
  function isMedia(node) {
6
5
  if (!node) {
7
6
  return false;
8
7
  }
9
-
10
8
  if (getNodeName(node) === 'SPAN' && node instanceof HTMLElement) {
11
9
  return !!node.querySelector('a > jira-attachment-thumbnail > img[data-attachment-type="thumbnail"], ' + 'a[data-attachment-type="file"]');
12
10
  }
13
-
14
11
  return false;
15
12
  }
16
-
17
13
  function repairParagraph(p) {
18
14
  var paragraphs = [];
19
15
  var buffer = [];
20
16
  var mediaGroupFound = false;
21
17
  var skipBuffer = false;
22
-
23
18
  var processMedia = function processMedia() {
24
19
  if (buffer.length) {
25
20
  var head = buffer[0];
26
-
27
21
  if (getNodeName(head) === 'BR') {
28
22
  buffer.shift();
29
23
  }
30
-
31
24
  paragraphs.push(buffer);
32
25
  buffer = [];
33
26
  }
34
27
  };
35
-
36
28
  for (var i = 0, length = p.childNodes.length; i < length; i++) {
37
29
  var node = p.childNodes[i];
38
- skipBuffer = false; // [..., M, BR, ...]
39
-
30
+ skipBuffer = false;
31
+ // [..., M, BR, ...]
40
32
  if (getNodeName(node) === 'BR') {
41
33
  // [mmm, M, BR, ...]
42
34
  if (mediaGroupFound) {
43
35
  processMedia();
44
36
  mediaGroupFound = false;
45
37
  skipBuffer = true;
46
- } // [..., BR, M, ...]
47
-
48
-
38
+ }
39
+ // [..., BR, M, ...]
49
40
  if (isMedia(node.nextSibling)) {
50
41
  mediaGroupFound = true;
51
-
52
42
  if (buffer.length) {
53
43
  paragraphs.push(buffer);
54
44
  buffer = [];
@@ -65,23 +55,19 @@ function repairParagraph(p) {
65
55
  if (getNodeName(node) === '#TEXT' && (node.textContent || '').trim() === '') {
66
56
  continue;
67
57
  }
68
-
69
58
  buffer = (paragraphs.pop() || []).concat(buffer);
70
59
  mediaGroupFound = false;
71
60
  }
72
61
  }
73
-
74
62
  if (!skipBuffer) {
75
63
  buffer.push(node);
76
64
  }
77
65
  }
78
-
79
66
  if (mediaGroupFound) {
80
67
  processMedia();
81
68
  } else {
82
69
  paragraphs.push(buffer);
83
70
  }
84
-
85
71
  if (paragraphs.length > 1) {
86
72
  var fragment = document.createDocumentFragment();
87
73
  paragraphs.forEach(function (childP) {
@@ -90,21 +76,19 @@ function repairParagraph(p) {
90
76
  return innerP.appendChild(child);
91
77
  });
92
78
  fragment.appendChild(innerP);
93
- }); // Replace old P
79
+ });
94
80
 
81
+ // Replace old P
95
82
  var parent = p.parentNode;
96
- parent.insertBefore(fragment, p.nextSibling); // IE11 doesn't support remove
97
-
83
+ parent.insertBefore(fragment, p.nextSibling);
84
+ // IE11 doesn't support remove
98
85
  parent.removeChild(p);
99
86
  }
100
87
  }
101
-
102
88
  export default function (doc) {
103
89
  var paragraphs = doc.querySelectorAll('p');
104
-
105
90
  for (var i = 0, length = paragraphs.length; i < length; i++) {
106
91
  repairParagraph(paragraphs[i]);
107
92
  }
108
-
109
93
  return doc;
110
94
  }