@atlaskit/adf-schema 19.2.3 → 20.0.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 (94) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/cjs/index.js +24 -6
  3. package/dist/cjs/schema/create-schema.js +10 -3
  4. package/dist/cjs/schema/default-schema.js +7 -13
  5. package/dist/cjs/schema/index.js +12 -6
  6. package/dist/cjs/schema/jira-schema.js +1 -1
  7. package/dist/cjs/schema/marks/fragment.js +77 -0
  8. package/dist/cjs/schema/marks/index.js +15 -1
  9. package/dist/cjs/schema/marks/link.js +1 -54
  10. package/dist/cjs/schema/marks/unsupported-mark.js +1 -0
  11. package/dist/cjs/schema/nodes/bodied-extension.js +1 -1
  12. package/dist/cjs/schema/nodes/caption.js +0 -1
  13. package/dist/cjs/schema/nodes/doc.js +1 -1
  14. package/dist/cjs/schema/nodes/emoji.js +4 -0
  15. package/dist/cjs/schema/nodes/expand.js +1 -1
  16. package/dist/cjs/schema/nodes/index.js +0 -6
  17. package/dist/cjs/schema/nodes/layout-column.js +1 -1
  18. package/dist/cjs/schema/nodes/media-single.js +1 -1
  19. package/dist/cjs/schema/nodes/panel.js +58 -53
  20. package/dist/cjs/schema/nodes/paragraph.js +168 -25
  21. package/dist/cjs/schema/nodes/tableNodes.js +3 -3
  22. package/dist/cjs/utils/index.js +12 -0
  23. package/dist/cjs/utils/url.js +62 -4
  24. package/dist/cjs/version.json +1 -1
  25. package/dist/es2019/index.js +2 -2
  26. package/dist/es2019/schema/create-schema.js +10 -5
  27. package/dist/es2019/schema/default-schema.js +6 -10
  28. package/dist/es2019/schema/index.js +2 -2
  29. package/dist/es2019/schema/jira-schema.js +1 -1
  30. package/dist/es2019/schema/marks/fragment.js +59 -0
  31. package/dist/es2019/schema/marks/index.js +2 -1
  32. package/dist/es2019/schema/marks/link.js +1 -49
  33. package/dist/es2019/schema/marks/unsupported-mark.js +1 -0
  34. package/dist/es2019/schema/nodes/bodied-extension.js +1 -1
  35. package/dist/es2019/schema/nodes/caption.js +0 -1
  36. package/dist/es2019/schema/nodes/doc.js +1 -1
  37. package/dist/es2019/schema/nodes/emoji.js +4 -0
  38. package/dist/es2019/schema/nodes/expand.js +1 -1
  39. package/dist/es2019/schema/nodes/index.js +1 -1
  40. package/dist/es2019/schema/nodes/layout-column.js +1 -1
  41. package/dist/es2019/schema/nodes/media-single.js +1 -1
  42. package/dist/es2019/schema/nodes/panel.js +42 -49
  43. package/dist/es2019/schema/nodes/paragraph.js +163 -25
  44. package/dist/es2019/schema/nodes/tableNodes.js +3 -3
  45. package/dist/es2019/utils/index.js +1 -1
  46. package/dist/es2019/utils/url.js +57 -4
  47. package/dist/es2019/version.json +1 -1
  48. package/dist/esm/index.js +2 -2
  49. package/dist/esm/schema/create-schema.js +10 -5
  50. package/dist/esm/schema/default-schema.js +6 -10
  51. package/dist/esm/schema/index.js +2 -2
  52. package/dist/esm/schema/jira-schema.js +1 -1
  53. package/dist/esm/schema/marks/fragment.js +64 -0
  54. package/dist/esm/schema/marks/index.js +2 -1
  55. package/dist/esm/schema/marks/link.js +1 -53
  56. package/dist/esm/schema/marks/unsupported-mark.js +1 -0
  57. package/dist/esm/schema/nodes/bodied-extension.js +1 -1
  58. package/dist/esm/schema/nodes/caption.js +0 -1
  59. package/dist/esm/schema/nodes/doc.js +1 -1
  60. package/dist/esm/schema/nodes/emoji.js +4 -0
  61. package/dist/esm/schema/nodes/expand.js +1 -1
  62. package/dist/esm/schema/nodes/index.js +1 -1
  63. package/dist/esm/schema/nodes/layout-column.js +1 -1
  64. package/dist/esm/schema/nodes/media-single.js +1 -1
  65. package/dist/esm/schema/nodes/panel.js +53 -51
  66. package/dist/esm/schema/nodes/paragraph.js +167 -25
  67. package/dist/esm/schema/nodes/tableNodes.js +3 -3
  68. package/dist/esm/utils/index.js +1 -1
  69. package/dist/esm/utils/url.js +57 -4
  70. package/dist/esm/version.json +1 -1
  71. package/dist/json-schema/v1/full.json +108 -73
  72. package/dist/json-schema/v1/stage-0.json +63 -26
  73. package/dist/types/index.d.ts +3 -3
  74. package/dist/types/schema/create-schema.d.ts +1 -0
  75. package/dist/types/schema/index.d.ts +3 -3
  76. package/dist/types/schema/marks/fragment.d.ts +30 -0
  77. package/dist/types/schema/marks/index.d.ts +2 -0
  78. package/dist/types/schema/marks/link.d.ts +3 -0
  79. package/dist/types/schema/nodes/block-card.d.ts +3 -0
  80. package/dist/types/schema/nodes/bodied-extension.d.ts +7 -5
  81. package/dist/types/schema/nodes/caption.d.ts +0 -1
  82. package/dist/types/schema/nodes/embed-card.d.ts +3 -0
  83. package/dist/types/schema/nodes/extension.d.ts +7 -5
  84. package/dist/types/schema/nodes/index.d.ts +1 -1
  85. package/dist/types/schema/nodes/inline-card.d.ts +0 -9
  86. package/dist/types/schema/nodes/inline-extension.d.ts +7 -5
  87. package/dist/types/schema/nodes/media-single.d.ts +0 -1
  88. package/dist/types/schema/nodes/panel.d.ts +1 -11
  89. package/dist/types/utils/index.d.ts +1 -1
  90. package/dist/types/utils/url.d.ts +7 -2
  91. package/json-schema/v1/full.json +108 -73
  92. package/json-schema/v1/stage-0.json +63 -26
  93. package/package.json +11 -8
  94. package/test-helpers/schema.ts +1 -0
@@ -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 => ({
@@ -10,12 +10,8 @@ export let PanelType;
10
10
  PanelType["CUSTOM"] = "custom";
11
11
  })(PanelType || (PanelType = {}));
12
12
 
13
- //TODO: ED-10445 rename to panel and merge with the other panel node spec, after emoji panels moved to full schema
14
- export const customPanel = {
15
- group: 'block',
16
- content: '(paragraph | heading | bulletList | orderedList | blockCard | unsupportedBlock)+',
17
- marks: 'unsupportedMark unsupportedNodeAttribute',
18
- attrs: {
13
+ const getDefaultAttrs = () => {
14
+ let attrs = {
19
15
  panelType: {
20
16
  default: 'info'
21
17
  },
@@ -25,55 +21,52 @@ export const customPanel = {
25
21
  panelColor: {
26
22
  default: null
27
23
  }
28
- },
29
- parseDOM: [{
30
- tag: 'div[data-panel-type]',
31
- getAttrs: dom => ({
32
- panelType: dom.getAttribute('data-panel-type'),
24
+ };
25
+ return attrs;
26
+ };
27
+
28
+ const getDomAttrs = nodeAttrs => {
29
+ let attrs = {
30
+ 'data-panel-type': nodeAttrs.panelType,
31
+ 'data-panel-icon': nodeAttrs.panelIcon,
32
+ 'data-panel-color': nodeAttrs.panelColor
33
+ };
34
+ return attrs;
35
+ };
36
+
37
+ const getParseDOMAttrs = (allowCustomPanel, dom) => {
38
+ let parseDOMAttrs = {
39
+ panelType: dom.getAttribute('data-panel-type')
40
+ };
41
+
42
+ if (allowCustomPanel) {
43
+ parseDOMAttrs = { ...parseDOMAttrs,
33
44
  panelIcon: dom.getAttribute('data-panel-icon'),
34
45
  panelColor: dom.getAttribute('data-panel-color')
35
- })
36
- }],
37
-
38
- toDOM(node) {
39
- const {
40
- panelType,
41
- panelIcon,
42
- panelColor
43
- } = node.attrs;
44
- const attrs = {
45
- 'data-panel-type': panelType,
46
- 'data-panel-icon': panelIcon,
47
- 'data-panel-color': panelColor
48
46
  };
49
- return ['div', attrs, ['div', {}, 0]];
47
+ } else {
48
+ parseDOMAttrs.panelType = parseDOMAttrs.panelType === PanelType.CUSTOM ? PanelType.INFO : parseDOMAttrs.panelType;
50
49
  }
51
50
 
51
+ return parseDOMAttrs;
52
52
  };
53
- export const panel = {
54
- group: 'block',
55
- content: '(paragraph | heading | bulletList | orderedList | blockCard | unsupportedBlock)+',
56
- marks: 'unsupportedMark unsupportedNodeAttribute',
57
- attrs: {
58
- panelType: {
59
- default: 'info'
60
- }
61
- },
62
- parseDOM: [{
63
- tag: 'div[data-panel-type]',
64
- getAttrs: dom => ({
65
- panelType: dom.getAttribute('data-panel-type')
66
- })
67
- }],
68
53
 
69
- toDOM(node) {
70
- const {
71
- panelType
72
- } = node.attrs;
73
- const attrs = {
74
- 'data-panel-type': panelType
75
- };
76
- return ['div', attrs, ['div', {}, 0]];
77
- }
54
+ export const panel = allowCustomPanel => {
55
+ const panelNodeSpec = {
56
+ group: 'block',
57
+ content: '(paragraph | heading | bulletList | orderedList | blockCard | unsupportedBlock)+',
58
+ marks: 'unsupportedMark unsupportedNodeAttribute',
59
+ attrs: getDefaultAttrs(),
60
+ parseDOM: [{
61
+ tag: 'div[data-panel-type]',
62
+ getAttrs: dom => getParseDOMAttrs(allowCustomPanel, dom)
63
+ }],
64
+
65
+ toDOM(node) {
66
+ const attrs = getDomAttrs(node.attrs);
67
+ return ['div', attrs, ['div', {}, 0]];
68
+ }
78
69
 
70
+ };
71
+ return panelNodeSpec;
79
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-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,4 +1,4 @@
1
1
  export { acNameToEmoji, acShortcutToEmoji, emojiIdToAcName, getEmojiAcName } from './confluence/emoji';
2
2
  export { generateUuid, uuid } from './uuid';
3
3
  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, hexToRgb, hexToRgba, isHex, isRgb, normalizeHexColor, rgbToHex } from './colors';
4
- export { getLinkMatch, isSafeUrl, normalizeUrl } from './url';
4
+ export { getLinkMatch, isSafeUrl, normalizeUrl, linkify, linkifyMatch } from './url';
@@ -1,12 +1,65 @@
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
- const linkify = LinkifyIt();
12
+ export const linkify = LinkifyIt();
7
13
  linkify.add('sourcetree:', 'http:');
14
+ const tlds = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
15
+ const tlds2Char = 'a[cdefgilmnoqrtuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrtuvwxyz]|n[acefgilopruz]|om|p[aefghkmnrtw]|qa|r[eosuw]|s[abcdegijklmnrtuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';
16
+ tlds.push(tlds2Char);
17
+ linkify.tlds(tlds, false);
18
+ export const LINK_REGEXP = /(https?|ftp):\/\/[^\s]+/;
19
+ export const linkifyMatch = text => {
20
+ const matches = [];
21
+
22
+ if (!LINK_REGEXP.test(text)) {
23
+ return matches;
24
+ }
25
+
26
+ let startpos = 0;
27
+ let substr;
28
+
29
+ while (substr = text.substr(startpos)) {
30
+ const link = (substr.match(LINK_REGEXP) || [''])[0];
31
+
32
+ if (link) {
33
+ const index = substr.search(LINK_REGEXP);
34
+ const start = index >= 0 ? index + startpos : index;
35
+ const end = start + link.length;
36
+ matches.push({
37
+ index: start,
38
+ lastIndex: end,
39
+ raw: link,
40
+ url: link,
41
+ text: link,
42
+ schema: ''
43
+ });
44
+ startpos += end;
45
+ } else {
46
+ break;
47
+ }
48
+ }
49
+
50
+ return matches;
51
+ };
8
52
  export function getLinkMatch(str) {
9
- const match = str && linkify.match(str);
53
+ if (!str) {
54
+ return null;
55
+ }
56
+
57
+ let match = linkifyMatch(str);
58
+
59
+ if (!match.length) {
60
+ match = linkify.match(str);
61
+ }
62
+
10
63
  return match && match[0];
11
64
  }
12
65
  /**
@@ -15,5 +68,5 @@ export function getLinkMatch(str) {
15
68
 
16
69
  export function normalizeUrl(url) {
17
70
  const match = getLinkMatch(url);
18
- return match && match.url || url;
71
+ return match && match.url || '';
19
72
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-schema",
3
- "version": "19.2.3",
3
+ "version": "20.0.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';
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, normalizeHexColor, normalizeUrl, rgbToHex, uuid } from './utils';
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
+ 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';
@@ -6,8 +6,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
6
6
 
7
7
  import { Schema } from 'prosemirror-model';
8
8
  import { COLOR, FONT_STYLE, SEARCH_QUERY, LINK } from './groups';
9
- import { link, em, strong, textColor, strike, subsup, underline, code, typeAheadQuery, confluenceInlineComment, breakout, alignment, indentation, annotation, unsupportedMark, unsupportedNodeAttribute, dataConsumer } from './marks';
10
- import { confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, doc, paragraph, text, bulletList, orderedList, listItem, heading, blockquote, codeBlock, panel, rule, image, mention, media, mediaInline, mediaGroup, mediaSingle, hardBreak, emoji, table, tableCell, tableHeader, tableRow, decisionList, decisionItem, taskList, taskItem, unknownBlock, extension, inlineExtension, bodiedExtension, date, placeholder, layoutSection, layoutColumn, inlineCard, blockCard, unsupportedBlock, unsupportedInline, status, expand, nestedExpand, embedCard, caption } from './nodes';
9
+ import { link, em, strong, textColor, strike, subsup, underline, code, typeAheadQuery, confluenceInlineComment, breakout, alignment, indentation, annotation, unsupportedMark, unsupportedNodeAttribute, dataConsumer, fragment } from './marks';
10
+ import { confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, doc, paragraph, text, bulletList, orderedList, listItem, heading, blockquote, codeBlock, panel, rule, image, mention, media, mediaInline, mediaGroup, mediaSingleWithCaption, hardBreak, emoji, table, tableCell, tableHeader, tableRow, decisionList, decisionItem, taskList, taskItem, unknownBlock, extension, inlineExtension, bodiedExtension, date, placeholder, layoutSection, layoutColumn, inlineCard, blockCard, unsupportedBlock, unsupportedInline, status, expand, nestedExpand, embedCard, caption } from './nodes';
11
11
 
12
12
  function addItems(builtInItems, config) {
13
13
  var customSpecs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
@@ -93,7 +93,7 @@ var nodesInOrder = [{
93
93
  spec: codeBlock
94
94
  }, {
95
95
  name: 'panel',
96
- spec: panel
96
+ spec: panel(true)
97
97
  }, {
98
98
  name: 'rule',
99
99
  spec: rule
@@ -114,7 +114,7 @@ var nodesInOrder = [{
114
114
  spec: mediaGroup
115
115
  }, {
116
116
  name: 'mediaSingle',
117
- spec: mediaSingle
117
+ spec: mediaSingleWithCaption
118
118
  }, {
119
119
  name: 'mediaInline',
120
120
  spec: mediaInline
@@ -248,6 +248,9 @@ var marksInOrder = [{
248
248
  }, {
249
249
  name: 'dataConsumer',
250
250
  spec: dataConsumer
251
+ }, {
252
+ name: 'fragment',
253
+ spec: fragment
251
254
  }, {
252
255
  name: 'indentation',
253
256
  spec: indentation
@@ -335,4 +338,6 @@ function isContentSupported(nodes, contentKey) {
335
338
  }
336
339
 
337
340
  return false;
338
- }
341
+ }
342
+
343
+ export var allowCustomPanel = true;
@@ -1,12 +1,10 @@
1
- import { customPanel } from './nodes/panel';
2
- import { layoutSectionWithSingleColumn } from './nodes/layout-section';
3
- import { dataConsumer } from './marks/data-consumer';
1
+ import { layoutSectionWithSingleColumn } from './nodes';
2
+ import { dataConsumer, fragment } from './marks';
4
3
  import { createSchema } from './create-schema';
5
- import { mediaSingleWithCaption } from './nodes';
6
4
 
7
5
  var getDefaultSchemaConfig = function getDefaultSchemaConfig() {
8
6
  var 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
  };
@@ -16,18 +14,16 @@ var getDefaultSchemaConfig = function getDefaultSchemaConfig() {
16
14
  export var defaultSchemaConfig = getDefaultSchemaConfig();
17
15
  export var getSchemaBasedOnStage = function getSchemaBasedOnStage() {
18
16
  var stage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'final';
19
- var defaultSchemaConfig = getDefaultSchemaConfig(); // TODO: ED-10445 remove stage0 check after panels with emoji are on full schema AND image captions are on full schema
17
+ var defaultSchemaConfig = getDefaultSchemaConfig();
20
18
 
21
19
  if (stage === 'stage0') {
22
20
  defaultSchemaConfig.customNodeSpecs = {
23
- panel: customPanel,
24
- mediaSingle: mediaSingleWithCaption,
25
21
  layoutSection: layoutSectionWithSingleColumn
26
22
  };
27
23
  defaultSchemaConfig.customMarkSpecs = {
28
- dataConsumer: dataConsumer
24
+ dataConsumer: dataConsumer,
25
+ fragment: fragment
29
26
  };
30
- defaultSchemaConfig.nodes.push('caption');
31
27
  defaultSchemaConfig.nodes.push('mediaInline');
32
28
  }
33
29
 
@@ -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,64 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
+
7
+ import { isDOMElement } from '../../utils/parseDOM';
8
+
9
+ var parseFragment = function parseFragment(maybeValue) {
10
+ var _maybeValue$getAttrib;
11
+
12
+ if (!isDOMElement(maybeValue)) {
13
+ return false;
14
+ }
15
+
16
+ var name = (_maybeValue$getAttrib = maybeValue.getAttribute('data-name')) !== null && _maybeValue$getAttrib !== void 0 ? _maybeValue$getAttrib : undefined;
17
+ var localId = maybeValue.getAttribute('data-localId');
18
+
19
+ if (!localId) {
20
+ return false;
21
+ }
22
+
23
+ return {
24
+ localId: localId,
25
+ name: name
26
+ };
27
+ };
28
+
29
+ export var fragment = {
30
+ inclusive: false,
31
+ excludes: '',
32
+ attrs: {
33
+ localId: {
34
+ default: ''
35
+ },
36
+ name: {
37
+ default: null
38
+ }
39
+ },
40
+ parseDOM: [{
41
+ tag: '[data-mark-type="fragment"]',
42
+ getAttrs: function getAttrs(maybeValue) {
43
+ return parseFragment(maybeValue);
44
+ }
45
+ }],
46
+ toDOM: function toDOM(mark, inline) {
47
+ var wrapperStyle = inline ? 'span' : 'div';
48
+ return [wrapperStyle, {
49
+ 'data-mark-type': 'fragment',
50
+ 'data-name': mark.attrs.name,
51
+ 'data-localId': mark.attrs.localId
52
+ }];
53
+ }
54
+ };
55
+ export var toJSON = function toJSON(mark) {
56
+ return {
57
+ type: mark.type.name,
58
+ attrs: _objectSpread({
59
+ localId: mark.attrs.localId
60
+ }, mark.attrs.name ? {
61
+ name: mark.attrs.name
62
+ } : {})
63
+ };
64
+ };