@atlaskit/adf-schema 19.3.0 → 20.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/cjs/index.js +366 -360
  3. package/dist/cjs/schema/create-schema.js +7 -4
  4. package/dist/cjs/schema/default-schema.js +8 -14
  5. package/dist/cjs/schema/groups.js +1 -1
  6. package/dist/cjs/schema/index.js +244 -238
  7. package/dist/cjs/schema/jira-schema.js +8 -8
  8. package/dist/cjs/schema/marks/alignment.js +1 -1
  9. package/dist/cjs/schema/marks/annotation.js +1 -1
  10. package/dist/cjs/schema/marks/fragment.js +77 -0
  11. package/dist/cjs/schema/marks/index.js +63 -49
  12. package/dist/cjs/schema/marks/link.js +2 -55
  13. package/dist/cjs/schema/marks/text-color.js +18 -3
  14. package/dist/cjs/schema/marks/unsupported-mark.js +1 -0
  15. package/dist/cjs/schema/nodes/bodied-extension.js +1 -1
  16. package/dist/cjs/schema/nodes/bullet-list.js +1 -1
  17. package/dist/cjs/schema/nodes/caption.js +0 -1
  18. package/dist/cjs/schema/nodes/decision-list.js +1 -1
  19. package/dist/cjs/schema/nodes/doc.js +1 -1
  20. package/dist/cjs/schema/nodes/expand.js +1 -1
  21. package/dist/cjs/schema/nodes/index.js +146 -152
  22. package/dist/cjs/schema/nodes/layout-column.js +1 -1
  23. package/dist/cjs/schema/nodes/media-single.js +1 -1
  24. package/dist/cjs/schema/nodes/media.js +1 -1
  25. package/dist/cjs/schema/nodes/ordered-list.js +1 -1
  26. package/dist/cjs/schema/nodes/panel.js +2 -28
  27. package/dist/cjs/schema/nodes/paragraph.js +168 -25
  28. package/dist/cjs/schema/nodes/tableNodes.js +4 -4
  29. package/dist/cjs/schema/nodes/task-list.js +1 -1
  30. package/dist/cjs/steps/analytics.js +1 -1
  31. package/dist/cjs/steps/table/sort-column.js +1 -1
  32. package/dist/cjs/steps/table/utils/cell-step.js +1 -1
  33. package/dist/cjs/steps/table/utils/table-map.js +2 -2
  34. package/dist/cjs/steps/type-ahead.js +1 -1
  35. package/dist/cjs/steps.js +10 -10
  36. package/dist/cjs/utils/colors.js +4 -4
  37. package/dist/cjs/utils/confluence/emoji.js +1 -1
  38. package/dist/cjs/utils/extensions.js +1 -1
  39. package/dist/cjs/utils/index.js +48 -48
  40. package/dist/cjs/utils/url.js +9 -2
  41. package/dist/cjs/version.json +1 -1
  42. package/dist/es2019/index.js +1 -1
  43. package/dist/es2019/schema/create-schema.js +7 -4
  44. package/dist/es2019/schema/default-schema.js +7 -11
  45. package/dist/es2019/schema/index.js +2 -2
  46. package/dist/es2019/schema/jira-schema.js +1 -1
  47. package/dist/es2019/schema/marks/fragment.js +59 -0
  48. package/dist/es2019/schema/marks/index.js +2 -1
  49. package/dist/es2019/schema/marks/link.js +3 -51
  50. package/dist/es2019/schema/marks/text-color.js +15 -1
  51. package/dist/es2019/schema/marks/unsupported-mark.js +1 -0
  52. package/dist/es2019/schema/nodes/bodied-extension.js +1 -1
  53. package/dist/es2019/schema/nodes/caption.js +0 -1
  54. package/dist/es2019/schema/nodes/doc.js +1 -1
  55. package/dist/es2019/schema/nodes/expand.js +1 -1
  56. package/dist/es2019/schema/nodes/index.js +1 -1
  57. package/dist/es2019/schema/nodes/layout-column.js +1 -1
  58. package/dist/es2019/schema/nodes/media-single.js +1 -1
  59. package/dist/es2019/schema/nodes/panel.js +1 -28
  60. package/dist/es2019/schema/nodes/paragraph.js +163 -25
  61. package/dist/es2019/schema/nodes/tableNodes.js +3 -3
  62. package/dist/es2019/utils/url.js +7 -1
  63. package/dist/es2019/version.json +1 -1
  64. package/dist/esm/index.js +1 -1
  65. package/dist/esm/schema/create-schema.js +7 -4
  66. package/dist/esm/schema/default-schema.js +7 -11
  67. package/dist/esm/schema/index.js +2 -2
  68. package/dist/esm/schema/jira-schema.js +1 -1
  69. package/dist/esm/schema/marks/fragment.js +64 -0
  70. package/dist/esm/schema/marks/index.js +2 -1
  71. package/dist/esm/schema/marks/link.js +3 -55
  72. package/dist/esm/schema/marks/text-color.js +17 -3
  73. package/dist/esm/schema/marks/unsupported-mark.js +1 -0
  74. package/dist/esm/schema/nodes/bodied-extension.js +1 -1
  75. package/dist/esm/schema/nodes/caption.js +0 -1
  76. package/dist/esm/schema/nodes/doc.js +1 -1
  77. package/dist/esm/schema/nodes/expand.js +1 -1
  78. package/dist/esm/schema/nodes/index.js +1 -1
  79. package/dist/esm/schema/nodes/layout-column.js +1 -1
  80. package/dist/esm/schema/nodes/media-single.js +1 -1
  81. package/dist/esm/schema/nodes/panel.js +1 -26
  82. package/dist/esm/schema/nodes/paragraph.js +167 -25
  83. package/dist/esm/schema/nodes/tableNodes.js +3 -3
  84. package/dist/esm/utils/url.js +7 -1
  85. package/dist/esm/version.json +1 -1
  86. package/dist/json-schema/v1/full.json +108 -73
  87. package/dist/json-schema/v1/stage-0.json +63 -26
  88. package/dist/types/index.d.ts +2 -2
  89. package/dist/types/schema/index.d.ts +3 -3
  90. package/dist/types/schema/marks/fragment.d.ts +30 -0
  91. package/dist/types/schema/marks/index.d.ts +2 -0
  92. package/dist/types/schema/marks/link.d.ts +3 -0
  93. package/dist/types/schema/nodes/block-card.d.ts +3 -0
  94. package/dist/types/schema/nodes/bodied-extension.d.ts +7 -5
  95. package/dist/types/schema/nodes/caption.d.ts +0 -1
  96. package/dist/types/schema/nodes/embed-card.d.ts +3 -0
  97. package/dist/types/schema/nodes/extension.d.ts +7 -5
  98. package/dist/types/schema/nodes/index.d.ts +1 -1
  99. package/dist/types/schema/nodes/inline-card.d.ts +0 -9
  100. package/dist/types/schema/nodes/inline-extension.d.ts +7 -5
  101. package/dist/types/schema/nodes/media-single.d.ts +0 -1
  102. package/dist/types/schema/nodes/panel.d.ts +1 -11
  103. package/json-schema/v1/full.json +108 -73
  104. package/json-schema/v1/stage-0.json +63 -26
  105. package/package.json +11 -8
  106. package/test-helpers/schema.ts +1 -0
@@ -1,12 +1,10 @@
1
- import { customPanel } from './nodes/panel';
2
- import { layoutSectionWithSingleColumn } from './nodes/layout-section';
3
- import { dataConsumer } from './marks/data-consumer';
4
- import { allowCustomPanel, createSchema } from './create-schema';
5
- import { mediaSingleWithCaption } from './nodes';
1
+ import { layoutSectionWithSingleColumn } from './nodes';
2
+ import { dataConsumer, fragment } from './marks';
3
+ import { createSchema } from './create-schema';
6
4
 
7
5
  const getDefaultSchemaConfig = () => {
8
6
  let defaultSchemaConfig = {
9
- nodes: ['doc', 'paragraph', 'text', 'bulletList', 'orderedList', 'listItem', 'heading', 'blockquote', 'codeBlock', 'panel', 'rule', 'image', 'mention', 'media', 'mediaGroup', 'mediaSingle', 'mediaInline', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'confluenceJiraIssue', 'expand', 'nestedExpand', 'extension', 'inlineExtension', 'bodiedExtension', 'hardBreak', 'emoji', 'table', 'tableCell', 'tableHeader', 'tableRow', 'decisionList', 'decisionItem', 'taskList', 'taskItem', 'unknownBlock', 'date', 'status', 'placeholder', 'layoutSection', 'layoutColumn', 'inlineCard', 'blockCard', 'embedCard', 'unsupportedBlock', 'unsupportedInline'],
7
+ nodes: ['doc', 'paragraph', 'text', 'bulletList', 'orderedList', 'listItem', 'heading', 'blockquote', 'codeBlock', 'panel', 'rule', 'image', 'caption', 'mention', 'media', 'mediaGroup', 'mediaSingle', 'mediaInline', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'confluenceJiraIssue', 'expand', 'nestedExpand', 'extension', 'inlineExtension', 'bodiedExtension', 'hardBreak', 'emoji', 'table', 'tableCell', 'tableHeader', 'tableRow', 'decisionList', 'decisionItem', 'taskList', 'taskItem', 'unknownBlock', 'date', 'status', 'placeholder', 'layoutSection', 'layoutColumn', 'inlineCard', 'blockCard', 'embedCard', 'unsupportedBlock', 'unsupportedInline'],
10
8
  marks: ['link', 'em', 'strong', 'strike', 'subsup', 'underline', 'code', 'textColor', 'confluenceInlineComment', 'breakout', 'alignment', 'indentation', 'annotation', 'unsupportedMark', 'unsupportedNodeAttribute', 'typeAheadQuery' // https://product-fabric.atlassian.net/browse/ED-10214,
11
9
  ]
12
10
  };
@@ -15,18 +13,16 @@ const getDefaultSchemaConfig = () => {
15
13
 
16
14
  export const defaultSchemaConfig = getDefaultSchemaConfig();
17
15
  export const getSchemaBasedOnStage = (stage = 'final') => {
18
- const defaultSchemaConfig = getDefaultSchemaConfig(); // TODO: ED-10445 remove stage0 check after panels with emoji are on full schema AND image captions are on full schema
16
+ const defaultSchemaConfig = getDefaultSchemaConfig();
19
17
 
20
18
  if (stage === 'stage0') {
21
19
  defaultSchemaConfig.customNodeSpecs = {
22
- panel: customPanel(allowCustomPanel),
23
- mediaSingle: mediaSingleWithCaption,
24
20
  layoutSection: layoutSectionWithSingleColumn
25
21
  };
26
22
  defaultSchemaConfig.customMarkSpecs = {
27
- dataConsumer: dataConsumer
23
+ dataConsumer: dataConsumer,
24
+ fragment
28
25
  };
29
- defaultSchemaConfig.nodes.push('caption');
30
26
  defaultSchemaConfig.nodes.push('mediaInline');
31
27
  }
32
28
 
@@ -1,5 +1,5 @@
1
- export { PanelType, blockCard, blockquote, bodiedExtension, bulletList, bulletListSelector, caption, codeBlock, codeBlockToJSON, confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, copyPrivateMediaAttributes, date, decisionItem, decisionList, decisionListSelector, doc, embedCard, emoji, expand, expandToJSON, extension, hardBreak, heading, image, inlineCard, inlineExtension, layoutColumn, layoutSection, layoutSectionWithSingleColumn, listItem, media, mediaGroup, mediaSingle, mediaInline, mediaSingleWithCaption, mediaSingleToJSON, mediaToJSON, mention, mentionToJSON, nestedExpand, orderedList, orderedListSelector, panel, customPanel, paragraph, placeholder, rule, getCellAttrs, getCellDomAttrs, status, table, tableBackgroundBorderColor, tableBackgroundColorNames, tableBackgroundColorPalette, tableCell, tableCellContentDomSelector, tableCellContentWrapperSelector, tableCellSelector, tableHeader, tableHeaderSelector, tablePrefixSelector, tableRow, tableToJSON, taskItem, taskList, taskListSelector, text, toJSONTableCell, toJSONTableHeader, unknownBlock, unsupportedBlock, unsupportedInline } from './nodes';
2
- export { AnnotationTypes, alignment, alignmentPositionMap, annotation, breakout, code, colorPalette, colorPaletteExtended, confluenceInlineComment, dataConsumer, dataConsumerToJSON, em, indentation, link, linkToJSON, strike, strong, subsup, textColor, typeAheadQuery, underline, buildAnnotationMarkDataAttributes, AnnotationMarkStates, unsupportedMark, unsupportedNodeAttribute } from './marks';
1
+ export { PanelType, blockCard, blockquote, bodiedExtension, bulletList, bulletListSelector, caption, codeBlock, codeBlockToJSON, confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, copyPrivateMediaAttributes, date, decisionItem, decisionList, decisionListSelector, doc, embedCard, emoji, expand, expandToJSON, extension, hardBreak, heading, image, inlineCard, inlineExtension, layoutColumn, layoutSection, layoutSectionWithSingleColumn, listItem, media, mediaGroup, mediaSingle, mediaInline, mediaSingleWithCaption, mediaSingleToJSON, mediaToJSON, mention, mentionToJSON, nestedExpand, orderedList, orderedListSelector, panel, paragraph, placeholder, rule, getCellAttrs, getCellDomAttrs, status, table, tableBackgroundBorderColor, tableBackgroundColorNames, tableBackgroundColorPalette, tableCell, tableCellContentDomSelector, tableCellContentWrapperSelector, tableCellSelector, tableHeader, tableHeaderSelector, tablePrefixSelector, tableRow, tableToJSON, taskItem, taskList, taskListSelector, text, toJSONTableCell, toJSONTableHeader, unknownBlock, unsupportedBlock, unsupportedInline } from './nodes';
2
+ export { AnnotationTypes, alignment, alignmentPositionMap, annotation, breakout, code, colorPalette, colorPaletteExtended, confluenceInlineComment, dataConsumer, dataConsumerToJSON, em, fragment, fragmentToJSON, indentation, link, linkToJSON, strike, strong, subsup, textColor, typeAheadQuery, underline, buildAnnotationMarkDataAttributes, AnnotationMarkStates, unsupportedMark, unsupportedNodeAttribute } from './marks';
3
3
  export { unsupportedNodeTypesForMediaCards } from './unsupported';
4
4
  export { inlineNodes } from './inline-nodes';
5
5
  export { sanitizeNodes, createSchema } from './create-schema';
@@ -37,7 +37,7 @@ export default function makeSchema(config) {
37
37
  }
38
38
 
39
39
  if (config.allowMedia) {
40
- nodes.push('mediaGroup', 'mediaSingle', 'media');
40
+ nodes.push('mediaGroup', 'mediaSingle', 'media', 'caption');
41
41
  }
42
42
 
43
43
  if (config.allowTextColor) {
@@ -0,0 +1,59 @@
1
+ import { isDOMElement } from '../../utils/parseDOM';
2
+
3
+ const parseFragment = maybeValue => {
4
+ var _maybeValue$getAttrib;
5
+
6
+ if (!isDOMElement(maybeValue)) {
7
+ return false;
8
+ }
9
+
10
+ const name = (_maybeValue$getAttrib = maybeValue.getAttribute('data-name')) !== null && _maybeValue$getAttrib !== void 0 ? _maybeValue$getAttrib : undefined;
11
+ const localId = maybeValue.getAttribute('data-localId');
12
+
13
+ if (!localId) {
14
+ return false;
15
+ }
16
+
17
+ return {
18
+ localId,
19
+ name
20
+ };
21
+ };
22
+
23
+ export const fragment = {
24
+ inclusive: false,
25
+ excludes: '',
26
+ attrs: {
27
+ localId: {
28
+ default: ''
29
+ },
30
+ name: {
31
+ default: null
32
+ }
33
+ },
34
+ parseDOM: [{
35
+ tag: '[data-mark-type="fragment"]',
36
+ getAttrs: maybeValue => parseFragment(maybeValue)
37
+ }],
38
+
39
+ toDOM(mark, inline) {
40
+ const wrapperStyle = inline ? 'span' : 'div';
41
+ return [wrapperStyle, {
42
+ 'data-mark-type': 'fragment',
43
+ 'data-name': mark.attrs.name,
44
+ 'data-localId': mark.attrs.localId
45
+ }];
46
+ }
47
+
48
+ };
49
+ export const toJSON = mark => {
50
+ return {
51
+ type: mark.type.name,
52
+ attrs: {
53
+ localId: mark.attrs.localId,
54
+ ...(mark.attrs.name ? {
55
+ name: mark.attrs.name
56
+ } : {})
57
+ }
58
+ };
59
+ };
@@ -14,4 +14,5 @@ export { indentation } from './indentation';
14
14
  export { annotation, AnnotationMarkStates, buildDataAttributes as buildAnnotationMarkDataAttributes, AnnotationTypes } from './annotation';
15
15
  export { unsupportedMark } from './unsupported-mark';
16
16
  export { unsupportedNodeAttribute } from './unsupported-node-attributes';
17
- export { dataConsumer, toJSON as dataConsumerToJSON } from './data-consumer';
17
+ export { dataConsumer, toJSON as dataConsumerToJSON } from './data-consumer';
18
+ export { fragment, toJSON as fragmentToJSON } from './fragment';
@@ -1,5 +1,4 @@
1
- import { Fragment } from 'prosemirror-model';
2
- import { LINK, COLOR } from '../groups';
1
+ import { LINK } from '../groups';
3
2
  import { isSafeUrl, normalizeUrl } from '../../utils/url';
4
3
 
5
4
  const getLinkAttrs = attribute => domNode => {
@@ -18,30 +17,8 @@ const getLinkAttrs = attribute => domNode => {
18
17
  return attrs;
19
18
  };
20
19
 
21
- const getLinkAttrsWithCheck = attribute => domNode => {
22
- const dom = domNode;
23
- const hasTextOnlyChildren = Array.from(dom.childNodes).every(node => node.nodeType === Node.TEXT_NODE || node.nodeName === 'SPAN');
24
-
25
- if (hasTextOnlyChildren) {
26
- const href = dom.getAttribute(attribute) || '';
27
- const attrs = {
28
- __confluenceMetadata: dom.hasAttribute('__confluenceMetadata') ? JSON.parse(dom.getAttribute('__confluenceMetadata') || '') : undefined
29
- };
30
-
31
- if (isSafeUrl(href)) {
32
- attrs.href = normalizeUrl(href);
33
- } else {
34
- return false;
35
- }
36
-
37
- return attrs;
38
- }
39
-
40
- return false;
41
- };
42
-
43
20
  export const link = {
44
- excludes: `${LINK} ${COLOR}`,
21
+ excludes: `${LINK}`,
45
22
  // ED-5844 No multiple links in media node
46
23
  group: LINK,
47
24
  attrs: {
@@ -57,39 +34,14 @@ export const link = {
57
34
  contentElement: node => {
58
35
  const clone = node.cloneNode(true);
59
36
  clone.removeAttribute('data-block-link');
37
+ clone.setAttribute('data-skip-paste', 'true');
60
38
  const wrapper = document.createElement('div');
61
39
  wrapper.appendChild(clone);
62
40
  return wrapper;
63
41
  }
64
42
  }, {
65
43
  tag: 'a[href]',
66
- context: 'mediaSingle/|taskItem/|decisionItem/',
67
44
  getAttrs: getLinkAttrs('href')
68
- }, {
69
- tag: 'a[href]',
70
- getAttrs: getLinkAttrsWithCheck('href')
71
- }, {
72
- /**
73
- * When links aren't wrapped in a paragraph and due to
74
- * the odd nature of how our schema is set up, prosemirror will
75
- * add the link to the paragraph node itself where it should be on
76
- * the text node, this satisfies our schema because link is allowed
77
- * in many places (e.g. listitem)
78
- * This change comes through via prosemirror-model@1.9.1
79
- */
80
- tag: 'a[href]',
81
- getAttrs: getLinkAttrsWithCheck('href'),
82
- getContent: (node, schema) => {
83
- if (node instanceof HTMLAnchorElement) {
84
- const href = node.getAttribute('href');
85
- const text = node.innerText;
86
- return Fragment.from(schema.nodes.paragraph.createChecked(undefined, schema.text(text, [schema.marks.link.create({
87
- href
88
- })])));
89
- }
90
-
91
- return Fragment.empty;
92
- }
93
45
  }],
94
46
 
95
47
  toDOM(node, isInline) {
@@ -52,6 +52,18 @@ export const textColor = {
52
52
  } // else handle other colour formats
53
53
 
54
54
 
55
+ return hexColor && (colorPalette.has(hexColor) || colorPaletteExtended.has(hexColor)) ? {
56
+ color: hexColor
57
+ } : false;
58
+ }
59
+ }, {
60
+ tag: '.fabric-text-color-mark',
61
+ getAttrs: maybeElement => {
62
+ if (!(maybeElement instanceof HTMLElement)) {
63
+ return false;
64
+ }
65
+
66
+ const hexColor = maybeElement.dataset.textCustomColor;
55
67
  return hexColor && (colorPalette.has(hexColor) || colorPaletteExtended.has(hexColor)) ? {
56
68
  color: hexColor
57
69
  } : false;
@@ -60,7 +72,9 @@ export const textColor = {
60
72
 
61
73
  toDOM(mark) {
62
74
  return ['span', {
63
- style: `color: ${mark.attrs.color}`
75
+ class: 'fabric-text-color-mark',
76
+ style: `--custom-text-color: ${mark.attrs.color}`,
77
+ ['data-text-custom-color']: mark.attrs.color
64
78
  }];
65
79
  }
66
80
 
@@ -3,6 +3,7 @@ export const unsupportedMark = {
3
3
  return ['span'];
4
4
  },
5
5
 
6
+ excludes: '',
6
7
  attrs: {
7
8
  originalValue: {}
8
9
  }
@@ -4,7 +4,7 @@ const createBodiedExtensionNodeSpec = () => {
4
4
  const nodeSpec = {
5
5
  inline: false,
6
6
  group: 'block',
7
- marks: 'link dataConsumer',
7
+ marks: 'link dataConsumer fragment',
8
8
  content: '(paragraph | panel | blockquote | orderedList | bulletList | rule | heading | codeBlock | mediaGroup | mediaSingle | decisionList | taskList | table | blockCard | extension | unsupportedBlock | embedCard)+',
9
9
  defining: true,
10
10
  selectable: true,
@@ -1,5 +1,4 @@
1
1
  /**
2
- * @stage 0
3
2
  * @name caption_node
4
3
  */
5
4
  export const caption = {
@@ -3,5 +3,5 @@
3
3
  */
4
4
  export const doc = {
5
5
  content: '(block|layoutSection)+',
6
- marks: 'alignment breakout dataConsumer indentation link unsupportedMark unsupportedNodeAttribute'
6
+ marks: 'alignment breakout dataConsumer fragment indentation link unsupportedMark unsupportedNodeAttribute'
7
7
  };
@@ -20,7 +20,7 @@ function getExpandAttrs(domNode) {
20
20
  export const expand = {
21
21
  inline: false,
22
22
  group: 'block',
23
- marks: 'link dataConsumer unsupportedMark unsupportedNodeAttribute',
23
+ marks: 'link dataConsumer fragment unsupportedMark unsupportedNodeAttribute',
24
24
  content: '(paragraph | panel | blockquote | orderedList | bulletList | rule | heading | codeBlock | mediaGroup | mediaSingle | decisionList | taskList | table | blockCard | embedCard | extension | unsupportedBlock)+',
25
25
  isolating: true,
26
26
  selectable: true,
@@ -15,7 +15,7 @@ export { emoji } from './emoji';
15
15
  export { image } from './image';
16
16
  export { mention, toJSON as mentionToJSON } from './mention';
17
17
  export { listItem } from './list-item';
18
- export { panel, customPanel, PanelType } from './panel';
18
+ export { panel, PanelType } from './panel';
19
19
  export { text } from './text';
20
20
  export { default as unknownBlock } from './unknown-block';
21
21
  export { caption } from './caption';
@@ -4,7 +4,7 @@
4
4
  export const layoutColumn = {
5
5
  content: '(block|unsupportedBlock)+',
6
6
  isolating: true,
7
- marks: 'link alignment indentation dataConsumer unsupportedMark unsupportedNodeAttribute',
7
+ marks: 'link alignment indentation dataConsumer fragment unsupportedMark unsupportedNodeAttribute',
8
8
  selectable: false,
9
9
  attrs: {
10
10
  width: {
@@ -17,7 +17,6 @@
17
17
 
18
18
  /**
19
19
  * @name mediaSingle_caption_node
20
- * @stage 0
21
20
  */
22
21
  export const defaultAttrs = {
23
22
  width: {
@@ -64,6 +63,7 @@ export const mediaSingle = {
64
63
 
65
64
  };
66
65
  export const mediaSingleWithCaption = { ...mediaSingle,
66
+ atom: false,
67
67
  content: 'media|unsupportedBlock+|media (caption|unsupportedBlock) unsupportedBlock*'
68
68
  };
69
69
  export const toJSON = node => ({
@@ -51,7 +51,7 @@ const getParseDOMAttrs = (allowCustomPanel, dom) => {
51
51
  return parseDOMAttrs;
52
52
  };
53
53
 
54
- export const customPanel = allowCustomPanel => {
54
+ export const panel = allowCustomPanel => {
55
55
  const panelNodeSpec = {
56
56
  group: 'block',
57
57
  content: '(paragraph | heading | bulletList | orderedList | blockCard | unsupportedBlock)+',
@@ -69,31 +69,4 @@ export const customPanel = allowCustomPanel => {
69
69
 
70
70
  };
71
71
  return panelNodeSpec;
72
- };
73
- export const panel = {
74
- group: 'block',
75
- content: '(paragraph | heading | bulletList | orderedList | blockCard | unsupportedBlock)+',
76
- marks: 'unsupportedMark unsupportedNodeAttribute',
77
- attrs: {
78
- panelType: {
79
- default: 'info'
80
- }
81
- },
82
- parseDOM: [{
83
- tag: 'div[data-panel-type]',
84
- getAttrs: dom => ({
85
- panelType: dom.getAttribute('data-panel-type')
86
- })
87
- }],
88
-
89
- toDOM(node) {
90
- const {
91
- panelType
92
- } = node.attrs;
93
- const attrs = {
94
- 'data-panel-type': panelType
95
- };
96
- return ['div', attrs, ['div', {}, 0]];
97
- }
98
-
99
72
  };
@@ -1,35 +1,173 @@
1
- /**
2
- * @name paragraph_node
3
- */
4
-
5
- /**
6
- * @name paragraph_with_no_marks_node
7
- */
8
-
9
- /**
10
- * NOTE: Need this because TS is too smart and inline everything.
11
- * So we need to give them separate identity.
12
- * Probably there's a way to solve it but that will need time and exploration.
13
- * // http://bit.ly/2raXFX5
14
- * type T1 = X | Y
15
- * type T2 = A | T1 | B // T2 = A | X | Y | B
16
- */
17
-
18
- /**
19
- * @name paragraph_with_alignment_node
20
- */
21
-
22
- /**
23
- * @name paragraph_with_indentation_node
24
- */
1
+ import { Fragment } from 'prosemirror-model';
2
+ import { isSafeUrl } from '../../utils/url';
3
+
4
+ const getLinkContent = (node, schema) => {
5
+ if (!(node instanceof HTMLAnchorElement)) {
6
+ return Fragment.empty;
7
+ }
8
+
9
+ const href = node.getAttribute('href') || '';
10
+ const text = node.innerText;
11
+
12
+ if (!text || text.length === 0) {
13
+ return Fragment.empty;
14
+ }
15
+
16
+ const marks = isSafeUrl(href) ? [schema.marks.link.create({
17
+ href
18
+ })] : [];
19
+ const textNode = schema.text(text, marks);
20
+ return Fragment.from(textNode);
21
+ };
22
+
23
+ const blockTags = {
24
+ address: true,
25
+ article: true,
26
+ aside: true,
27
+ blockquote: true,
28
+ canvas: true,
29
+ dd: true,
30
+ div: true,
31
+ dl: true,
32
+ fieldset: true,
33
+ figcaption: true,
34
+ figure: true,
35
+ footer: true,
36
+ form: true,
37
+ h1: true,
38
+ h2: true,
39
+ h3: true,
40
+ h4: true,
41
+ h5: true,
42
+ h6: true,
43
+ header: true,
44
+ hgroup: true,
45
+ hr: true,
46
+ li: true,
47
+ noscript: true,
48
+ ol: true,
49
+ output: true,
50
+ p: true,
51
+ pre: true,
52
+ section: true,
53
+ table: true,
54
+ tfoot: true,
55
+ ul: true
56
+ };
57
+
58
+ const isListItemNode = node => {
59
+ return Boolean(node && node.nodeName.toLowerCase() === 'li');
60
+ };
61
+
62
+ const isTextNode = node => {
63
+ return Boolean(node && node.nodeType === Node.TEXT_NODE);
64
+ };
65
+
66
+ const isImageNode = node => {
67
+ return Boolean(node && node.nodeName.toLowerCase() === 'img');
68
+ };
69
+
70
+ const hasInlineImage = node => {
71
+ if (!node) {
72
+ return false;
73
+ }
74
+
75
+ return Array.from(node.childNodes).some(child => {
76
+ const isImage = isImageNode(child);
77
+
78
+ if (!isImage && child.childNodes) {
79
+ return Array.from(node.childNodes).some(node => hasInlineImage(node));
80
+ }
81
+
82
+ return isImage;
83
+ });
84
+ };
85
+
86
+ const hasWhiteSpacePre = node => {
87
+ return Boolean(node instanceof HTMLElement && node.style.whiteSpace === 'pre');
88
+ };
89
+
90
+ const hasFontFamilyMonospace = node => {
91
+ return Boolean(node instanceof HTMLElement && node.style.fontFamily.includes('monospace'));
92
+ };
93
+
94
+ const isBlockLevelNode = node => {
95
+ return Boolean(node && blockTags.hasOwnProperty(node.nodeName.toLowerCase()));
96
+ };
97
+
98
+ const NOT_INTERNAL_LINKS = [':not([data-inline-card])', ':not([data-block-card])', ':not([data-block-link])', ':not([data-skip-paste])'].join('');
99
+ const ANCHOR_LINK = `a[href]${NOT_INTERNAL_LINKS}`;
100
+ const NOT_INTERNAL_ELEMENTS = [':not(.code-block)', ':not([data-node-type])', ':not([data-embed-card])', ':not([data-layout-section])', ':not([data-task-local-id])', ':not([data-task-state])', ':not([data-pm-slice])', ':not([data-mark-type])'].join('');
25
101
  const pDOM = ['p', 0];
26
102
  export const paragraph = {
27
103
  selectable: false,
28
104
  content: 'inline*',
29
105
  group: 'block',
30
- marks: 'strong code em link strike subsup textColor typeAheadQuery underline confluenceInlineComment action annotation unsupportedMark unsupportedNodeAttribute dataConsumer',
106
+ marks: 'strong code em link strike subsup textColor typeAheadQuery underline confluenceInlineComment action annotation unsupportedMark unsupportedNodeAttribute dataConsumer fragment',
31
107
  parseDOM: [{
32
108
  tag: 'p'
109
+ }, {
110
+ tag: `div${NOT_INTERNAL_ELEMENTS}, li:not([data-pm-slice])`,
111
+ priority: 100,
112
+ getAttrs: node => {
113
+ if (!(node instanceof Node)) {
114
+ return false;
115
+ }
116
+
117
+ const isCodeBlock = hasWhiteSpacePre(node) || hasFontFamilyMonospace(node);
118
+
119
+ if (isCodeBlock || !node.hasChildNodes()) {
120
+ return false;
121
+ }
122
+
123
+ const hasInlineChildren = Array.from(node.childNodes).every(child => !isBlockLevelNode(child) && // IMG is considered block for mediaSingle
124
+ !isImageNode(child));
125
+
126
+ if (!hasInlineChildren) {
127
+ return false;
128
+ }
129
+
130
+ if ( // We can skip this rule for pure list items
131
+ isListItemNode(node) && Array.from(node.childNodes).every(isTextNode)) {
132
+ return false;
133
+ }
134
+
135
+ return null;
136
+ }
137
+ }, {
138
+ tag: `:not(span) + ${ANCHOR_LINK}`,
139
+ priority: 100,
140
+ getContent: getLinkContent
141
+ }, {
142
+ tag: `:not(span) > ${ANCHOR_LINK}:first-child`,
143
+ getAttrs: node => {
144
+ if (!(node instanceof Node)) {
145
+ return false;
146
+ }
147
+
148
+ if (isBlockLevelNode(node.firstChild)) {
149
+ return null;
150
+ }
151
+
152
+ if (hasInlineImage(node)) {
153
+ return false;
154
+ }
155
+
156
+ const isNextSiblingValid = node.nextSibling === null || node.nextSibling instanceof Text && (node.nextSibling.textContent || '').trim().length === 0;
157
+
158
+ if (isNextSiblingValid) {
159
+ return null;
160
+ } // This rule should not match when there is any sibling after the anchor
161
+
162
+
163
+ if (!isBlockLevelNode(node.nextSibling)) {
164
+ return false;
165
+ }
166
+
167
+ return null;
168
+ },
169
+ priority: 100,
170
+ getContent: getLinkContent
33
171
  }],
34
172
 
35
173
  toDOM() {
@@ -103,7 +103,7 @@ const createTableSpec = () => {
103
103
  const tableNodeSpec = {
104
104
  content: 'tableRow+',
105
105
  attrs: attrs,
106
- marks: 'unsupportedMark unsupportedNodeAttribute',
106
+ marks: 'fragment unsupportedMark unsupportedNodeAttribute',
107
107
  tableRole: 'table',
108
108
  isolating: true,
109
109
  selectable: false,
@@ -183,7 +183,7 @@ export const tableCell = {
183
183
  content: '(paragraph | panel | blockquote | orderedList | bulletList | rule | heading | codeBlock | mediaSingle | mediaGroup | decisionList | taskList | blockCard | embedCard | extension | nestedExpand | unsupportedBlock)+',
184
184
  attrs: cellAttrs,
185
185
  tableRole: 'cell',
186
- marks: 'link alignment dataConsumer unsupportedMark unsupportedNodeAttribute',
186
+ marks: 'link alignment dataConsumer fragment unsupportedMark unsupportedNodeAttribute',
187
187
  isolating: true,
188
188
  parseDOM: [// Ignore number cell copied from renderer
189
189
  {
@@ -210,7 +210,7 @@ export const tableHeader = {
210
210
  attrs: cellAttrs,
211
211
  tableRole: 'header_cell',
212
212
  isolating: true,
213
- marks: 'link alignment dataConsumer unsupportedMark unsupportedNodeAttribute',
213
+ marks: 'link alignment dataConsumer fragment unsupportedMark unsupportedNodeAttribute',
214
214
  parseDOM: [{
215
215
  tag: 'th',
216
216
  getAttrs: dom => getCellAttrs(dom, {
@@ -1,7 +1,13 @@
1
1
  import LinkifyIt from 'linkify-it';
2
2
  const whitelistedURLPatterns = [/^https?:\/\//im, /^ftps?:\/\//im, /^\//im, /^mailto:/im, /^skype:/im, /^callto:/im, /^facetime:/im, /^git:/im, /^irc6?:/im, /^news:/im, /^nntp:/im, /^feed:/im, /^cvs:/im, /^svn:/im, /^mvn:/im, /^ssh:/im, /^scp:\/\//im, /^sftp:\/\//im, /^itms:/im, /^notes:/im, /^hipchat:\/\//im, /^sourcetree:/im, /^urn:/im, /^tel:/im, /^xmpp:/im, /^telnet:/im, /^vnc:/im, /^rdp:/im, /^whatsapp:/im, /^slack:/im, /^sips?:/im, /^magnet:/im, /^#/im];
3
3
  export const isSafeUrl = url => {
4
- return whitelistedURLPatterns.some(p => p.test(url.trim()) === true);
4
+ const urlTrimmed = url.trim();
5
+
6
+ if (urlTrimmed.length === 0) {
7
+ return true;
8
+ }
9
+
10
+ return whitelistedURLPatterns.some(p => p.test(urlTrimmed));
5
11
  };
6
12
  export const linkify = LinkifyIt();
7
13
  linkify.add('sourcetree:', 'http:');
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-schema",
3
- "version": "19.3.0",
3
+ "version": "20.1.0",
4
4
  "sideEffects": false
5
5
  }
package/dist/esm/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { AnnotationTypes, PanelType, alignment, alignmentPositionMap, annotation, bitbucketSchema, blockCard, blockquote, bodiedExtension, breakout, bulletList, bulletListSelector, caption, code, codeBlock, codeBlockToJSON, colorPalette, colorPaletteExtended, confluenceInlineComment, confluenceJiraIssue, confluenceSchema, confluenceSchemaWithMediaSingle, confluenceUnsupportedBlock, confluenceUnsupportedInline, copyPrivateMediaAttributes, createJIRASchema, createSchema, dataConsumer, dataConsumerToJSON, date, decisionItem, decisionList, decisionListSelector, defaultSchema, defaultSchemaConfig, doc, em, embedCard, emoji, expand, expandToJSON, extension, getSchemaBasedOnStage, hardBreak, heading, image, indentation, inlineCard, inlineExtension, inlineNodes, isSchemaWithAdvancedTextFormattingMarks, isSchemaWithBlockQuotes, isSchemaWithCodeBlock, isSchemaWithEmojis, isSchemaWithLinks, isSchemaWithLists, isSchemaWithMedia, isSchemaWithMentions, isSchemaWithSubSupMark, isSchemaWithTables, isSchemaWithTextColor, layoutColumn, layoutSection, link, linkToJSON, listItem, media, mediaGroup, mediaSingle, mediaSingleWithCaption, mediaInline, mediaSingleToJSON, mediaToJSON, mention, mentionToJSON, nestedExpand, orderedList, orderedListSelector, panel, customPanel, paragraph, placeholder, rule, sanitizeNodes, getCellAttrs, getCellDomAttrs, status, strike, strong, subsup, table, tableBackgroundBorderColor, tableBackgroundColorNames, tableBackgroundColorPalette, tableCell, tableCellContentDomSelector, tableCellContentWrapperSelector, tableCellSelector, tableHeader, tableHeaderSelector, tablePrefixSelector, tableRow, tableToJSON, taskItem, taskList, taskListSelector, text, textColor, toJSONTableCell, toJSONTableHeader, typeAheadQuery, underline, unknownBlock, unsupportedBlock, unsupportedInline, unsupportedNodeTypesForMediaCards, buildAnnotationMarkDataAttributes, AnnotationMarkStates, unsupportedMark, unsupportedNodeAttribute } from './schema';
1
+ export { AnnotationTypes, PanelType, alignment, alignmentPositionMap, annotation, bitbucketSchema, blockCard, blockquote, bodiedExtension, breakout, bulletList, bulletListSelector, caption, code, codeBlock, codeBlockToJSON, colorPalette, colorPaletteExtended, confluenceInlineComment, confluenceJiraIssue, confluenceSchema, confluenceSchemaWithMediaSingle, confluenceUnsupportedBlock, confluenceUnsupportedInline, copyPrivateMediaAttributes, createJIRASchema, createSchema, dataConsumer, dataConsumerToJSON, date, decisionItem, decisionList, decisionListSelector, defaultSchema, defaultSchemaConfig, doc, em, embedCard, emoji, expand, expandToJSON, extension, fragment, fragmentToJSON, getSchemaBasedOnStage, hardBreak, heading, image, indentation, inlineCard, inlineExtension, inlineNodes, isSchemaWithAdvancedTextFormattingMarks, isSchemaWithBlockQuotes, isSchemaWithCodeBlock, isSchemaWithEmojis, isSchemaWithLinks, isSchemaWithLists, isSchemaWithMedia, isSchemaWithMentions, isSchemaWithSubSupMark, isSchemaWithTables, isSchemaWithTextColor, layoutColumn, layoutSection, link, linkToJSON, listItem, media, mediaGroup, mediaSingle, mediaSingleWithCaption, mediaInline, mediaSingleToJSON, mediaToJSON, mention, mentionToJSON, nestedExpand, orderedList, orderedListSelector, panel, paragraph, placeholder, rule, sanitizeNodes, getCellAttrs, getCellDomAttrs, status, strike, strong, subsup, table, tableBackgroundBorderColor, tableBackgroundColorNames, tableBackgroundColorPalette, tableCell, tableCellContentDomSelector, tableCellContentWrapperSelector, tableCellSelector, tableHeader, tableHeaderSelector, tablePrefixSelector, tableRow, tableToJSON, taskItem, taskList, taskListSelector, text, textColor, toJSONTableCell, toJSONTableHeader, typeAheadQuery, underline, unknownBlock, unsupportedBlock, unsupportedInline, unsupportedNodeTypesForMediaCards, buildAnnotationMarkDataAttributes, AnnotationMarkStates, unsupportedMark, unsupportedNodeAttribute } from './schema';
2
2
  export { B100, B400, B50, B500, B75, G200, G300, G400, G50, G500, G75, N0, N20, N200, N30, N300, N40, N50, N500, N60, N80, N800, N90, P100, P300, P400, P50, P500, P75, R100, R300, R400, R50, R500, R75, T100, T300, T50, T500, T75, Y200, Y400, Y50, Y500, Y75, acNameToEmoji, acShortcutToEmoji, emojiIdToAcName, generateUuid, getEmojiAcName, getLinkMatch, hexToRgb, hexToRgba, isHex, isRgb, isSafeUrl, linkify, linkifyMatch, normalizeHexColor, normalizeUrl, rgbToHex, uuid } from './utils';