@atlaskit/adf-utils 18.0.2 → 18.0.3

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 (143) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cjs/builders/marks/alignment.js +0 -3
  3. package/dist/cjs/builders/marks/annotation.js +0 -3
  4. package/dist/cjs/builders/marks/breakout.js +0 -3
  5. package/dist/cjs/builders/marks/code.js +0 -3
  6. package/dist/cjs/builders/marks/data-consumer.js +0 -3
  7. package/dist/cjs/builders/marks/em.js +0 -3
  8. package/dist/cjs/builders/marks/fragment.js +0 -3
  9. package/dist/cjs/builders/marks/indentation.js +0 -3
  10. package/dist/cjs/builders/marks/link.js +0 -3
  11. package/dist/cjs/builders/marks/strike.js +0 -3
  12. package/dist/cjs/builders/marks/strong.js +0 -3
  13. package/dist/cjs/builders/marks/subsup.js +0 -3
  14. package/dist/cjs/builders/marks/text-color.js +0 -3
  15. package/dist/cjs/builders/marks/underline.js +0 -3
  16. package/dist/cjs/builders/nodes/block-card.js +0 -2
  17. package/dist/cjs/builders/nodes/blockquote.js +0 -3
  18. package/dist/cjs/builders/nodes/bodied-extension.js +0 -3
  19. package/dist/cjs/builders/nodes/bullet-list.js +0 -3
  20. package/dist/cjs/builders/nodes/caption.js +0 -3
  21. package/dist/cjs/builders/nodes/code-block.js +0 -3
  22. package/dist/cjs/builders/nodes/date.js +0 -2
  23. package/dist/cjs/builders/nodes/decision-item.js +0 -3
  24. package/dist/cjs/builders/nodes/decision-list.js +0 -3
  25. package/dist/cjs/builders/nodes/doc.js +0 -3
  26. package/dist/cjs/builders/nodes/embed-card.js +0 -2
  27. package/dist/cjs/builders/nodes/emoji.js +0 -2
  28. package/dist/cjs/builders/nodes/expand.js +0 -3
  29. package/dist/cjs/builders/nodes/extension.js +0 -2
  30. package/dist/cjs/builders/nodes/hard-break.js +0 -2
  31. package/dist/cjs/builders/nodes/heading.js +0 -3
  32. package/dist/cjs/builders/nodes/inline-card.js +0 -2
  33. package/dist/cjs/builders/nodes/inline-extension.js +0 -2
  34. package/dist/cjs/builders/nodes/layout-column.js +0 -2
  35. package/dist/cjs/builders/nodes/layout-section.js +0 -2
  36. package/dist/cjs/builders/nodes/list-item.js +0 -2
  37. package/dist/cjs/builders/nodes/media-group.js +0 -3
  38. package/dist/cjs/builders/nodes/media-inline.js +0 -2
  39. package/dist/cjs/builders/nodes/media-single.js +0 -2
  40. package/dist/cjs/builders/nodes/media.js +0 -2
  41. package/dist/cjs/builders/nodes/mention.js +0 -6
  42. package/dist/cjs/builders/nodes/nested-expand.js +0 -3
  43. package/dist/cjs/builders/nodes/ordered-list.js +0 -3
  44. package/dist/cjs/builders/nodes/panel.js +0 -3
  45. package/dist/cjs/builders/nodes/paragraph.js +0 -4
  46. package/dist/cjs/builders/nodes/placeholder.js +0 -2
  47. package/dist/cjs/builders/nodes/rule.js +0 -2
  48. package/dist/cjs/builders/nodes/status.js +0 -2
  49. package/dist/cjs/builders/nodes/table-cell.js +0 -3
  50. package/dist/cjs/builders/nodes/table-header.js +0 -3
  51. package/dist/cjs/builders/nodes/table-row.js +0 -2
  52. package/dist/cjs/builders/nodes/table.js +0 -3
  53. package/dist/cjs/builders/nodes/task-item.js +0 -3
  54. package/dist/cjs/builders/nodes/task-list.js +0 -3
  55. package/dist/cjs/builders/nodes/text.js +0 -2
  56. package/dist/cjs/builders/utils/apply-mark.js +0 -5
  57. package/dist/cjs/builders/utils/create-text-nodes.js +0 -3
  58. package/dist/cjs/builders/utils/is-duplicate-mark.js +0 -3
  59. package/dist/cjs/builders.js +0 -51
  60. package/dist/cjs/empty-adf.js +0 -2
  61. package/dist/cjs/scrub/default-node-replacements.js +0 -11
  62. package/dist/cjs/scrub/default-value-replacements.js +0 -2
  63. package/dist/cjs/scrub/hash.js +0 -4
  64. package/dist/cjs/scrub/scrub-adf.js +2 -25
  65. package/dist/cjs/scrub/scrub-content.js +7 -37
  66. package/dist/cjs/scrub.js +0 -2
  67. package/dist/cjs/transforms/dedupe-marks-transform.js +2 -23
  68. package/dist/cjs/transforms/helpers.js +0 -3
  69. package/dist/cjs/transforms/indentation-marks-transform.js +6 -14
  70. package/dist/cjs/transforms/invalid-media-content-transform.js +3 -22
  71. package/dist/cjs/transforms/media-link-transform.js +2 -12
  72. package/dist/cjs/transforms/nodes-missing-content-transform.js +0 -44
  73. package/dist/cjs/transforms/text-link-code-transform.js +3 -13
  74. package/dist/cjs/transforms.js +0 -6
  75. package/dist/cjs/traverse/filter.js +0 -2
  76. package/dist/cjs/traverse/map.js +0 -2
  77. package/dist/cjs/traverse/reduce.js +0 -2
  78. package/dist/cjs/traverse/traverse.js +1 -18
  79. package/dist/cjs/traverse.js +0 -4
  80. package/dist/cjs/validator/rules.js +0 -2
  81. package/dist/cjs/validator/specs/index.js +0 -83
  82. package/dist/cjs/validator/utils.js +4 -20
  83. package/dist/cjs/validator/validator.js +67 -218
  84. package/dist/cjs/validator.js +0 -1
  85. package/dist/cjs/version.json +1 -1
  86. package/dist/es2019/builders/utils/apply-mark.js +0 -2
  87. package/dist/es2019/builders/utils/is-duplicate-mark.js +0 -1
  88. package/dist/es2019/builders.js +4 -1
  89. package/dist/es2019/scrub/default-node-replacements.js +2 -7
  90. package/dist/es2019/scrub/hash.js +0 -2
  91. package/dist/es2019/scrub/scrub-adf.js +4 -10
  92. package/dist/es2019/scrub/scrub-content.js +7 -20
  93. package/dist/es2019/transforms/dedupe-marks-transform.js +4 -16
  94. package/dist/es2019/transforms/helpers.js +0 -1
  95. package/dist/es2019/transforms/indentation-marks-transform.js +10 -10
  96. package/dist/es2019/transforms/invalid-media-content-transform.js +5 -15
  97. package/dist/es2019/transforms/media-link-transform.js +2 -9
  98. package/dist/es2019/transforms/nodes-missing-content-transform.js +6 -38
  99. package/dist/es2019/transforms/text-link-code-transform.js +5 -8
  100. package/dist/es2019/traverse/traverse.js +5 -13
  101. package/dist/es2019/validator/utils.js +4 -2
  102. package/dist/es2019/validator/validator.js +60 -174
  103. package/dist/es2019/version.json +1 -1
  104. package/dist/esm/builders/nodes/blockquote.js +0 -1
  105. package/dist/esm/builders/nodes/bodied-extension.js +0 -1
  106. package/dist/esm/builders/nodes/bullet-list.js +0 -1
  107. package/dist/esm/builders/nodes/caption.js +0 -1
  108. package/dist/esm/builders/nodes/code-block.js +0 -1
  109. package/dist/esm/builders/nodes/decision-item.js +0 -1
  110. package/dist/esm/builders/nodes/decision-list.js +0 -1
  111. package/dist/esm/builders/nodes/doc.js +0 -1
  112. package/dist/esm/builders/nodes/expand.js +0 -1
  113. package/dist/esm/builders/nodes/heading.js +0 -1
  114. package/dist/esm/builders/nodes/media-group.js +0 -1
  115. package/dist/esm/builders/nodes/mention.js +0 -3
  116. package/dist/esm/builders/nodes/nested-expand.js +0 -1
  117. package/dist/esm/builders/nodes/ordered-list.js +0 -1
  118. package/dist/esm/builders/nodes/panel.js +0 -1
  119. package/dist/esm/builders/nodes/paragraph.js +0 -1
  120. package/dist/esm/builders/nodes/table-cell.js +0 -1
  121. package/dist/esm/builders/nodes/table-header.js +0 -1
  122. package/dist/esm/builders/nodes/table.js +0 -1
  123. package/dist/esm/builders/nodes/task-item.js +0 -1
  124. package/dist/esm/builders/nodes/task-list.js +0 -1
  125. package/dist/esm/builders/utils/apply-mark.js +0 -2
  126. package/dist/esm/builders/utils/is-duplicate-mark.js +0 -1
  127. package/dist/esm/builders.js +4 -1
  128. package/dist/esm/scrub/default-node-replacements.js +0 -9
  129. package/dist/esm/scrub/hash.js +0 -2
  130. package/dist/esm/scrub/scrub-adf.js +2 -17
  131. package/dist/esm/scrub/scrub-content.js +7 -28
  132. package/dist/esm/transforms/dedupe-marks-transform.js +2 -18
  133. package/dist/esm/transforms/helpers.js +0 -1
  134. package/dist/esm/transforms/indentation-marks-transform.js +6 -11
  135. package/dist/esm/transforms/invalid-media-content-transform.js +3 -18
  136. package/dist/esm/transforms/media-link-transform.js +2 -9
  137. package/dist/esm/transforms/nodes-missing-content-transform.js +0 -38
  138. package/dist/esm/transforms/text-link-code-transform.js +3 -10
  139. package/dist/esm/traverse/traverse.js +1 -15
  140. package/dist/esm/validator/utils.js +4 -2
  141. package/dist/esm/validator/validator.js +67 -209
  142. package/dist/esm/version.json +1 -1
  143. package/package.json +2 -2
@@ -1,17 +1,18 @@
1
1
  import * as specs from './specs';
2
2
  import { copy, isBoolean, isDefined, isInteger, isNumber, isPlainObject, isString, makeArray } from './utils';
3
3
  import { validatorFnMap } from './rules';
4
-
5
4
  function mapMarksItems(spec, fn = x => x) {
6
5
  if (spec.props && spec.props.marks) {
7
6
  const {
8
7
  items,
9
8
  ...rest
10
9
  } = spec.props.marks;
11
- return { ...spec,
12
- props: { ...spec.props,
13
- marks: { ...rest,
14
-
10
+ return {
11
+ ...spec,
12
+ props: {
13
+ ...spec.props,
14
+ marks: {
15
+ ...rest,
15
16
  /**
16
17
  * `Text & MarksObject<Mark-1>` produces `items: ['mark-1']`
17
18
  * `Text & MarksObject<Mark-1 | Mark-2>` produces `items: [['mark-1', 'mark-2']]`
@@ -24,33 +25,31 @@ function mapMarksItems(spec, fn = x => x) {
24
25
  return spec;
25
26
  }
26
27
  }
27
-
28
28
  const partitionObject = (obj, predicate) => Object.keys(obj).reduce((acc, key) => {
29
29
  acc[predicate(key, obj[key], obj) ? 0 : 1].push(key);
30
30
  return acc;
31
31
  }, [[], []]);
32
+
32
33
  /**
33
34
  * Normalizes the structure of files imported form './specs'.
34
35
  * We denormalised the spec to save bundle size.
35
36
  */
36
-
37
-
38
37
  function createSpec(nodes, marks) {
39
38
  return Object.keys(specs).reduce((newSpecs, k) => {
40
- const spec = { ...specs[k]
39
+ const spec = {
40
+ ...specs[k]
41
41
  };
42
-
43
42
  if (spec.props) {
44
- spec.props = { ...spec.props
43
+ spec.props = {
44
+ ...spec.props
45
45
  };
46
-
47
46
  if (spec.props.content) {
48
47
  // 'tableCell_content' => { type: 'array', items: [ ... ] }
49
48
  if (isString(spec.props.content)) {
50
49
  spec.props.content = specs[spec.props.content];
51
- } // ['inline', 'emoji']
52
-
50
+ }
53
51
 
52
+ // ['inline', 'emoji']
54
53
  if (Array.isArray(spec.props.content)) {
55
54
  /**
56
55
  * Flatten
@@ -66,15 +65,20 @@ function createSpec(nodes, marks) {
66
65
  items: (spec.props.content || []).map(arr => arr.items)
67
66
  };
68
67
  } else {
69
- spec.props.content = { ...spec.props.content
68
+ spec.props.content = {
69
+ ...spec.props.content
70
70
  };
71
71
  }
72
+ spec.props.content.items = spec.props.content.items
72
73
 
73
- spec.props.content.items = spec.props.content.items // ['inline'] => [['emoji', 'hr', ...]]
74
+ // ['inline'] => [['emoji', 'hr', ...]]
74
75
  // ['media'] => [['media']]
75
- .map(item => isString(item) ? Array.isArray(specs[item]) ? specs[item] : [item] : item) // [['emoji', 'hr', 'inline_code']] => [['emoji', 'hr', ['text', { marks: {} }]]]
76
- .map(item => item.map(subItem => Array.isArray(specs[subItem]) ? specs[subItem] : isString(subItem) ? subItem : // Now `NoMark` produces `items: []`, should be fixed in generator
77
- ['text', subItem]) // Remove unsupported nodes & marks
76
+ .map(item => isString(item) ? Array.isArray(specs[item]) ? specs[item] : [item] : item)
77
+ // [['emoji', 'hr', 'inline_code']] => [['emoji', 'hr', ['text', { marks: {} }]]]
78
+ .map(item => item.map(subItem => Array.isArray(specs[subItem]) ? specs[subItem] : isString(subItem) ? subItem :
79
+ // Now `NoMark` produces `items: []`, should be fixed in generator
80
+ ['text', subItem])
81
+ // Remove unsupported nodes & marks
78
82
  // Filter nodes
79
83
  .filter(subItem => {
80
84
  if (nodes) {
@@ -82,21 +86,17 @@ function createSpec(nodes, marks) {
82
86
  // ['mediaSingle', { props: { content: { items: [ 'media', 'caption' ] } }}]
83
87
  if (Array.isArray(subItem)) {
84
88
  var _subItem$, _subItem$$props, _subItem$$props$conte;
85
-
86
89
  const isMainNodeSupported = nodes.indexOf(subItem[0]) > -1;
87
-
88
90
  if (isMainNodeSupported && (_subItem$ = subItem[1]) !== null && _subItem$ !== void 0 && (_subItem$$props = _subItem$.props) !== null && _subItem$$props !== void 0 && (_subItem$$props$conte = _subItem$$props.content) !== null && _subItem$$props$conte !== void 0 && _subItem$$props$conte.items) {
89
91
  return subItem[1].props.content.items.every(item => nodes.indexOf(item) > -1);
90
92
  }
91
-
92
93
  return isMainNodeSupported;
93
94
  }
94
-
95
95
  return nodes.indexOf(subItem) > -1;
96
96
  }
97
-
98
97
  return true;
99
- }) // Filter marks
98
+ })
99
+ // Filter marks
100
100
  .map(subItem => Array.isArray(subItem) && marks ?
101
101
  /**
102
102
  * TODO: Probably try something like immer, but it's 3.3kb gzipped.
@@ -105,83 +105,62 @@ function createSpec(nodes, marks) {
105
105
  [subItem[0], mapMarksItems(subItem[1])] : subItem));
106
106
  }
107
107
  }
108
-
109
108
  newSpecs[k] = spec;
110
109
  return newSpecs;
111
110
  }, {});
112
111
  }
113
-
114
112
  function getOptionsForType(type, list) {
115
113
  if (!list) {
116
114
  return {};
117
115
  }
118
-
119
116
  for (let i = 0, len = list.length; i < len; i++) {
120
117
  const spec = list[i];
121
118
  let name = spec;
122
119
  let options = {};
123
-
124
120
  if (Array.isArray(spec)) {
125
121
  [name, options] = spec;
126
122
  }
127
-
128
123
  if (name === type) {
129
124
  return options;
130
125
  }
131
126
  }
132
-
133
127
  return false;
134
128
  }
135
-
136
129
  export function validateAttrs(spec, value) {
137
130
  // extension_node parameters has no type
138
131
  if (!isDefined(spec.type)) {
139
132
  return !!spec.optional;
140
133
  }
141
-
142
134
  if (!isDefined(value)) {
143
135
  return !!spec.optional;
144
136
  }
145
-
146
137
  switch (spec.type) {
147
138
  case 'boolean':
148
139
  return isBoolean(value);
149
-
150
140
  case 'number':
151
141
  return isNumber(value) && (isDefined(spec.minimum) ? spec.minimum <= value : true) && (isDefined(spec.maximum) ? spec.maximum >= value : true);
152
-
153
142
  case 'integer':
154
143
  return isInteger(value) && (isDefined(spec.minimum) ? spec.minimum <= value : true) && (isDefined(spec.maximum) ? spec.maximum >= value : true);
155
-
156
144
  case 'string':
157
145
  const validatorFnPassed = rule => typeof value === 'string' && isDefined(validatorFnMap[rule]) && validatorFnMap[rule](value);
158
-
159
146
  return isString(value) && (isDefined(spec.minLength) ? spec.minLength <= value.length : true) && (isDefined(spec.validatorFn) ? validatorFnPassed(spec.validatorFn) : true) && (spec.pattern ? new RegExp(spec.pattern).test(value) : true);
160
-
161
147
  case 'object':
162
148
  return isPlainObject(value);
163
-
164
149
  case 'array':
165
150
  const types = spec.items;
166
151
  const lastTypeIndex = types.length - 1;
167
-
168
152
  if (Array.isArray(value)) {
169
153
  // We are doing this to support tuple which can be defined as [number, string]
170
154
  // NOTE: Not validating tuples strictly
171
155
  return value.every((x, i) => validateAttrs(types[Math.min(i, lastTypeIndex)], x));
172
156
  }
173
-
174
157
  return false;
175
-
176
158
  case 'enum':
177
159
  return isString(value) && spec.values.indexOf(value) > -1;
178
160
  }
179
-
180
161
  return false;
181
162
  }
182
-
183
163
  const errorMessageFor = (type, message) => `${type}: ${message}.`;
184
-
185
164
  const getUnsupportedOptions = spec => {
186
165
  if (spec && spec.props && spec.props.content) {
187
166
  const {
@@ -193,31 +172,28 @@ const getUnsupportedOptions = spec => {
193
172
  allowUnsupportedInline
194
173
  };
195
174
  }
196
-
197
175
  return {};
198
176
  };
199
-
200
177
  const invalidChildContent = (child, errorCallback, parentSpec) => {
201
178
  const message = errorMessageFor(child.type, 'invalid content');
202
-
203
179
  if (!errorCallback) {
204
180
  throw new Error(message);
205
181
  } else {
206
- return errorCallback({ ...child
182
+ return errorCallback({
183
+ ...child
207
184
  }, {
208
185
  code: 'INVALID_CONTENT',
209
186
  message
210
187
  }, getUnsupportedOptions(parentSpec));
211
188
  }
212
189
  };
213
-
214
190
  const unsupportedMarkContent = (errorCode, mark, errorCallback, errorMessage) => {
215
191
  const message = errorMessage || errorMessageFor(mark.type, 'unsupported mark');
216
-
217
192
  if (!errorCallback) {
218
193
  throw new Error(message);
219
194
  } else {
220
- return errorCallback({ ...mark
195
+ return errorCallback({
196
+ ...mark
221
197
  }, {
222
198
  code: errorCode,
223
199
  message,
@@ -229,7 +205,6 @@ const unsupportedMarkContent = (errorCode, mark, errorCallback, errorMessage) =>
229
205
  });
230
206
  }
231
207
  };
232
-
233
208
  const unsupportedNodeAttributesContent = (entity, errorCode, invalidAttributes, message, errorCallback) => {
234
209
  if (!errorCallback) {
235
210
  throw new Error(message);
@@ -248,14 +223,12 @@ const unsupportedNodeAttributesContent = (entity, errorCode, invalidAttributes,
248
223
  });
249
224
  }
250
225
  };
251
-
252
226
  export function validator(nodes, marks, options) {
253
227
  const validatorSpecs = createSpec(nodes, marks);
254
228
  const {
255
229
  mode = 'strict',
256
230
  allowPrivateAttributes = false
257
231
  } = options || {};
258
-
259
232
  const validate = (entity, errorCallback, allowed, parentSpec) => {
260
233
  const validationResult = validateNode(entity, errorCallback, allowed, parentSpec);
261
234
  return {
@@ -263,17 +236,15 @@ export function validator(nodes, marks, options) {
263
236
  valid: validationResult.valid
264
237
  };
265
238
  };
266
-
267
239
  const validateNode = (entity, errorCallback, allowed, parentSpec, isMark = false) => {
268
240
  const {
269
241
  type
270
242
  } = entity;
271
- let newEntity = { ...entity
243
+ let newEntity = {
244
+ ...entity
272
245
  };
273
-
274
246
  const err = (code, msg, meta) => {
275
247
  const message = errorMessageFor(type, msg);
276
-
277
248
  if (errorCallback) {
278
249
  return {
279
250
  valid: false,
@@ -287,42 +258,32 @@ export function validator(nodes, marks, options) {
287
258
  throw new Error(message);
288
259
  }
289
260
  };
290
-
291
261
  if (type) {
292
262
  const typeOptions = getOptionsForType(type, allowed);
293
-
294
263
  if (typeOptions === false) {
295
264
  return isMark ? {
296
265
  valid: false
297
266
  } : err('INVALID_TYPE', 'type not allowed here');
298
267
  }
299
-
300
268
  const spec = validatorSpecs[type];
301
-
302
269
  if (!spec) {
303
270
  return err('INVALID_TYPE', `${type}: No validation spec found for type!`);
304
271
  }
305
-
306
272
  const specBasedValidationResult = specBasedValidationFor(spec, typeOptions, entity, err, newEntity, type, errorCallback, isMark);
307
-
308
273
  if (specBasedValidationResult.hasValidated && specBasedValidationResult.result) {
309
274
  return specBasedValidationResult.result;
310
275
  }
311
276
  } else {
312
277
  return err('INVALID_TYPE', 'ProseMirror Node/Mark should contain a `type`');
313
278
  }
314
-
315
279
  return {
316
280
  valid: true,
317
281
  entity: newEntity
318
282
  };
319
283
  };
320
-
321
284
  return validate;
322
-
323
285
  function marksValidationFor(validator, entity, errorCallback, newEntity, err) {
324
286
  let validationResult;
325
-
326
287
  if (validator.props && validator.props.marks) {
327
288
  const marksSet = allowedMarksFor(validator);
328
289
  const marksValidationResult = marksAfterValidation(entity, errorCallback, marksSet, validator);
@@ -334,37 +295,35 @@ export function validator(nodes, marks, options) {
334
295
  } else {
335
296
  validationResult = marksForEntitySpecNotSupportingMarks(entity, newEntity, errorCallback, err);
336
297
  }
337
-
338
298
  return validationResult;
339
299
  }
340
-
341
300
  function validatorFor(spec, typeOptions) {
342
- return { ...spec,
301
+ return {
302
+ ...spec,
343
303
  ...typeOptions,
344
304
  // options with props can override props of spec
345
305
  ...(spec.props ? {
346
- props: { ...spec.props,
306
+ props: {
307
+ ...spec.props,
347
308
  ...(typeOptions['props'] || {})
348
309
  }
349
310
  } : {})
350
311
  };
351
312
  }
352
-
353
313
  function marksAfterValidation(entity, errorCallback, marksSet, validator) {
354
314
  return entity.marks ? entity.marks.map(mark => {
355
315
  const isAKnownMark = marks ? marks.indexOf(mark.type) > -1 : true;
356
-
357
316
  if (mode === 'strict' && isAKnownMark) {
358
317
  const finalResult = validateNode(mark, errorCallback, marksSet, validator, true);
359
318
  const finalMark = finalResult.entity;
360
-
361
319
  if (finalMark) {
362
320
  return {
363
321
  valid: true,
364
322
  originalMark: mark,
365
323
  newMark: finalMark
366
324
  };
367
- } // this checks for mark level attribute errors
325
+ }
326
+ // this checks for mark level attribute errors
368
327
  // and propagates error code and message
369
328
  else if (finalResult.marksValidationOutput && finalResult.marksValidationOutput.length) {
370
329
  return {
@@ -389,7 +348,6 @@ export function validator(nodes, marks, options) {
389
348
  }
390
349
  }) : [];
391
350
  }
392
-
393
351
  function allowedMarksFor(validator) {
394
352
  const {
395
353
  items
@@ -397,20 +355,16 @@ export function validator(nodes, marks, options) {
397
355
  const marksSet = items.length ? Array.isArray(items[0]) ? items[0] : items : [];
398
356
  return marksSet;
399
357
  }
400
-
401
358
  function marksForEntitySpecNotSupportingMarks(prevEntity, newEntity, errorCallback, err) {
402
359
  const errorCode = 'REDUNDANT_MARKS';
403
360
  const currentMarks = prevEntity.marks || [];
404
361
  const newMarks = currentMarks.map(mark => {
405
362
  const isUnsupportedNodeAttributeMark = mark.type === 'unsupportedNodeAttribute';
406
-
407
363
  if (isUnsupportedNodeAttributeMark) {
408
364
  return mark;
409
365
  }
410
-
411
366
  return unsupportedMarkContent(errorCode, mark, errorCallback);
412
367
  });
413
-
414
368
  if (newMarks.length) {
415
369
  newEntity.marks = newMarks;
416
370
  return {
@@ -423,50 +377,41 @@ export function validator(nodes, marks, options) {
423
377
  });
424
378
  }
425
379
  }
426
-
427
380
  function requiredPropertyValidationFor(validatorSpec, prevEntity, err) {
428
381
  let result = {
429
382
  valid: true,
430
383
  entity: prevEntity
431
384
  };
432
-
433
385
  if (validatorSpec.required) {
434
386
  if (!validatorSpec.required.every(prop => isDefined(prevEntity[prop]))) {
435
387
  result = err('MISSING_PROPERTIES', 'required prop missing');
436
388
  }
437
389
  }
438
-
439
390
  return result;
440
391
  }
441
-
442
392
  function textPropertyValidationFor(validatorSpec, prevEntity, err) {
443
393
  let result = {
444
394
  valid: true,
445
395
  entity: prevEntity
446
396
  };
447
-
448
397
  if (validatorSpec.props.text) {
449
398
  if (isDefined(prevEntity.text) && !validateAttrs(validatorSpec.props.text, prevEntity.text)) {
450
399
  result = err('INVALID_TEXT', `'text' validation failed`);
451
400
  }
452
401
  }
453
-
454
402
  return result;
455
403
  }
456
-
457
404
  function contentLengthValidationFor(validatorSpec, prevEntity, err) {
458
405
  let result = {
459
406
  valid: true,
460
407
  entity: prevEntity
461
408
  };
462
-
463
409
  if (validatorSpec.props.content && prevEntity.content) {
464
410
  const {
465
411
  minItems,
466
412
  maxItems
467
413
  } = validatorSpec.props.content;
468
414
  const length = prevEntity.content.length;
469
-
470
415
  if (isDefined(minItems) && minItems > length) {
471
416
  result = err('INVALID_CONTENT_LENGTH', `'content' should have more than ${minItems} child`, {
472
417
  length,
@@ -481,14 +426,11 @@ export function validator(nodes, marks, options) {
481
426
  });
482
427
  }
483
428
  }
484
-
485
429
  return result;
486
430
  }
487
-
488
431
  function invalidAttributesFor(validatorSpec, prevEntity) {
489
432
  let invalidAttrs = [];
490
433
  let validatorAttrs = {};
491
-
492
434
  if (validatorSpec.props && validatorSpec.props.attrs) {
493
435
  const attrOptions = makeArray(validatorSpec.props.attrs);
494
436
  /**
@@ -496,64 +438,51 @@ export function validator(nodes, marks, options) {
496
438
  * attrs: [{ props: { url: { type: 'string' } } }, { props: { data: {} } }],
497
439
  * Gotcha: It will always report the last failure.
498
440
  */
499
-
500
441
  for (let i = 0, length = attrOptions.length; i < length; ++i) {
501
442
  const attrOption = attrOptions[i];
502
-
503
443
  if (attrOption && attrOption.props) {
504
444
  [, invalidAttrs] = partitionObject(attrOption.props, (k, v) => {
505
445
  return validateAttrs(v, prevEntity.attrs[k]);
506
446
  });
507
447
  }
508
-
509
448
  validatorAttrs = attrOption;
510
-
511
449
  if (!invalidAttrs.length) {
512
450
  break;
513
451
  }
514
452
  }
515
453
  }
516
-
517
454
  return {
518
455
  invalidAttrs,
519
456
  validatorAttrs
520
457
  };
521
458
  }
522
-
523
459
  function attributesValidationFor(validatorSpec, prevEntity, newEntity, isMark, errorCallback) {
524
460
  const validatorSpecAllowsAttributes = validatorSpec.props && validatorSpec.props.attrs;
525
-
526
461
  if (prevEntity.attrs) {
527
462
  if (!validatorSpecAllowsAttributes) {
528
463
  if (isMark) {
529
464
  return handleNoAttibutesAllowedInSpecForMark(prevEntity, prevEntity.attrs);
530
465
  }
531
-
532
466
  const attrs = Object.keys(prevEntity.attrs);
533
467
  return handleUnsupportedNodeAttributes(prevEntity, newEntity, [], attrs, errorCallback);
534
468
  }
535
-
536
469
  const {
537
470
  hasUnsupportedAttrs,
538
471
  redundantAttrs,
539
472
  invalidAttrs
540
473
  } = validateAttributes(validatorSpec, prevEntity, prevEntity.attrs);
541
-
542
474
  if (hasUnsupportedAttrs) {
543
475
  if (isMark) {
544
476
  return handleUnsupportedMarkAttributes(prevEntity, invalidAttrs, redundantAttrs);
545
477
  }
546
-
547
478
  return handleUnsupportedNodeAttributes(prevEntity, newEntity, invalidAttrs, redundantAttrs, errorCallback);
548
479
  }
549
480
  }
550
-
551
481
  return {
552
482
  valid: true,
553
483
  entity: prevEntity
554
484
  };
555
485
  }
556
-
557
486
  function validateAttributes(validatorSpec, prevEntity, attributes) {
558
487
  const invalidAttributesResult = invalidAttributesFor(validatorSpec, prevEntity);
559
488
  const {
@@ -570,7 +499,6 @@ export function validator(nodes, marks, options) {
570
499
  redundantAttrs
571
500
  };
572
501
  }
573
-
574
502
  function handleUnsupportedNodeAttributes(prevEntity, newEntity, invalidAttrs, redundantAttrs, errorCallback) {
575
503
  const attr = invalidAttrs.concat(redundantAttrs);
576
504
  let result = {
@@ -586,18 +514,15 @@ export function validator(nodes, marks, options) {
586
514
  };
587
515
  return result;
588
516
  }
589
-
590
517
  function handleUnsupportedMarkAttributes(prevEntity, invalidAttrs, redundantAttrs) {
591
518
  let errorCode = 'INVALID_ATTRIBUTES';
592
519
  let message = errorMessageFor(prevEntity.type, `'attrs' validation failed`);
593
520
  const hasRedundantAttrs = redundantAttrs.length;
594
521
  const hasBothInvalidAndRedundantAttrs = hasRedundantAttrs && invalidAttrs.length;
595
-
596
522
  if (!hasBothInvalidAndRedundantAttrs && hasRedundantAttrs) {
597
523
  errorCode = 'REDUNDANT_ATTRIBUTES';
598
524
  message = errorMessageFor('redundant attributes found', redundantAttrs.join(', '));
599
525
  }
600
-
601
526
  const markValidationResult = {
602
527
  valid: true,
603
528
  originalMark: prevEntity,
@@ -609,7 +534,6 @@ export function validator(nodes, marks, options) {
609
534
  marksValidationOutput: [markValidationResult]
610
535
  };
611
536
  }
612
-
613
537
  function handleNoAttibutesAllowedInSpecForMark(prevEntity, attributes) {
614
538
  const message = errorMessageFor('redundant attributes found', Object.keys(attributes).join(', '));
615
539
  const errorCode = 'REDUNDANT_ATTRIBUTES';
@@ -624,22 +548,18 @@ export function validator(nodes, marks, options) {
624
548
  marksValidationOutput: [markValidationResult]
625
549
  };
626
550
  }
627
-
628
551
  function wrapUnSupportedNodeAttributes(prevEntity, newEntity, invalidAttrs, errorCode, message, errorCallback) {
629
552
  let invalidValues = {};
630
-
631
553
  for (let invalidAttr in invalidAttrs) {
632
554
  invalidValues[invalidAttrs[invalidAttr]] = prevEntity.attrs && prevEntity.attrs[invalidAttrs[invalidAttr]];
633
-
634
555
  if (newEntity.attrs) {
635
556
  delete newEntity.attrs[invalidAttrs[invalidAttr]];
636
557
  }
637
558
  }
638
-
639
559
  const unsupportedNodeAttributeValues = unsupportedNodeAttributesContent(prevEntity, errorCode, invalidValues, message, errorCallback);
640
- const finalEntity = { ...newEntity
560
+ const finalEntity = {
561
+ ...newEntity
641
562
  };
642
-
643
563
  if (finalEntity.marks) {
644
564
  unsupportedNodeAttributeValues && finalEntity.marks.push(unsupportedNodeAttributeValues);
645
565
  return finalEntity.marks;
@@ -647,14 +567,12 @@ export function validator(nodes, marks, options) {
647
567
  return [unsupportedNodeAttributeValues];
648
568
  }
649
569
  }
650
-
651
570
  function extraPropsValidationFor(validatorSpec, prevEntity, err, newEntity, type) {
652
571
  let result = {
653
572
  valid: true,
654
573
  entity: prevEntity
655
574
  };
656
575
  const [requiredProps, redundantProps] = partitionObject(prevEntity, k => isDefined(validatorSpec.props[k]));
657
-
658
576
  if (redundantProps.length) {
659
577
  if (mode === 'loose') {
660
578
  newEntity = {
@@ -669,34 +587,29 @@ export function validator(nodes, marks, options) {
669
587
  }
670
588
  }
671
589
  }
672
-
673
590
  return result;
674
591
  }
675
-
676
592
  function specBasedValidationFor(spec, typeOptions, prevEntity, err, newEntity, type, errorCallback, isMark) {
677
593
  let specBasedValidationResult = {
678
594
  hasValidated: false
679
595
  };
680
596
  const validatorSpec = validatorFor(spec, typeOptions);
681
-
682
597
  if (!validatorSpec) {
683
598
  return specBasedValidationResult;
684
- } // Required Props
685
- // For array format where `required` is an array
686
-
599
+ }
687
600
 
601
+ // Required Props
602
+ // For array format where `required` is an array
688
603
  const requiredPropertyValidatonResult = requiredPropertyValidationFor(validatorSpec, prevEntity, err);
689
-
690
604
  if (!requiredPropertyValidatonResult.valid) {
691
605
  return {
692
606
  hasValidated: true,
693
607
  result: requiredPropertyValidatonResult
694
608
  };
695
609
  }
696
-
697
610
  if (!validatorSpec.props) {
698
- const props = Object.keys(prevEntity); // If there's no validator.props then there shouldn't be any key except `type`
699
-
611
+ const props = Object.keys(prevEntity);
612
+ // If there's no validator.props then there shouldn't be any key except `type`
700
613
  if (props.length > 1) {
701
614
  return {
702
615
  hasValidated: true,
@@ -705,34 +618,29 @@ export function validator(nodes, marks, options) {
705
618
  })
706
619
  };
707
620
  }
708
-
709
621
  return specBasedValidationResult;
710
- } // Check text
711
-
622
+ }
712
623
 
624
+ // Check text
713
625
  const textPropertyValidationResult = textPropertyValidationFor(validatorSpec, prevEntity, err);
714
-
715
626
  if (!textPropertyValidationResult.valid) {
716
627
  return {
717
628
  hasValidated: true,
718
629
  result: textPropertyValidationResult
719
630
  };
720
- } // Content Length
721
-
722
-
631
+ }
632
+ // Content Length
723
633
  const contentLengthValidationResult = contentLengthValidationFor(validatorSpec, prevEntity, err);
724
-
725
634
  if (!contentLengthValidationResult.valid) {
726
635
  return {
727
636
  hasValidated: true,
728
637
  result: contentLengthValidationResult
729
638
  };
730
- } // Required Props
731
- // For object format based on `optional` property
732
-
639
+ }
733
640
 
641
+ // Required Props
642
+ // For object format based on `optional` property
734
643
  const [, missingProps] = partitionObject(validatorSpec.props, (k, v) => v.optional || isDefined(prevEntity[k]));
735
-
736
644
  if (missingProps.length) {
737
645
  return {
738
646
  hasValidated: true,
@@ -741,45 +649,37 @@ export function validator(nodes, marks, options) {
741
649
  })
742
650
  };
743
651
  }
744
-
745
652
  const attributesValidationResult = attributesValidationFor(validatorSpec, prevEntity, newEntity, isMark, errorCallback);
746
-
747
653
  if (!attributesValidationResult.valid) {
748
654
  return {
749
655
  hasValidated: true,
750
656
  result: attributesValidationResult
751
657
  };
752
658
  }
753
-
754
659
  if (isMark && attributesValidationResult.valid) {
755
660
  return {
756
661
  hasValidated: true,
757
662
  result: attributesValidationResult
758
663
  };
759
664
  }
760
-
761
665
  const extraPropsValidationResult = extraPropsValidationFor(validatorSpec, prevEntity, err, newEntity, type);
762
-
763
666
  if (!extraPropsValidationResult.valid) {
764
667
  return {
765
668
  hasValidated: true,
766
669
  result: extraPropsValidationResult
767
670
  };
768
- } // Children
769
-
671
+ }
770
672
 
673
+ // Children
771
674
  if (validatorSpec.props.content) {
772
675
  const contentValidatorSpec = validatorSpec.props.content;
773
-
774
676
  if (prevEntity.content) {
775
677
  const validateChildNode = (child, index) => {
776
678
  if (child === undefined) {
777
679
  return child;
778
680
  }
779
-
780
681
  const validateChildMarks = (childEntity, marksValidationOutput, errorCallback, isLastValidationSpec, isParentTupleLike = false) => {
781
682
  let marksAreValid = true;
782
-
783
683
  if (childEntity && childEntity.marks && marksValidationOutput) {
784
684
  const validMarks = marksValidationOutput.filter(mark => mark.valid);
785
685
  const finalMarks = marksValidationOutput.map(mr => {
@@ -789,11 +689,9 @@ export function validator(nodes, marks, options) {
789
689
  if (validMarks.length || isLastValidationSpec || isParentTupleLike || mr.errorCode === 'INVALID_TYPE' || mr.errorCode === 'INVALID_CONTENT' || mr.errorCode === 'REDUNDANT_ATTRIBUTES' || mr.errorCode === 'INVALID_ATTRIBUTES') {
790
690
  return unsupportedMarkContent(mr.errorCode, mr.originalMark, errorCallback, mr.message);
791
691
  }
792
-
793
692
  return;
794
693
  }
795
694
  }).filter(Boolean);
796
-
797
695
  if (finalMarks.length) {
798
696
  childEntity.marks = finalMarks;
799
697
  } else {
@@ -801,15 +699,12 @@ export function validator(nodes, marks, options) {
801
699
  marksAreValid = false;
802
700
  }
803
701
  }
804
-
805
702
  return {
806
703
  valid: marksAreValid,
807
704
  entity: childEntity
808
705
  };
809
706
  };
810
-
811
707
  const hasMultipleCombinationOfContentAllowed = !!contentValidatorSpec.isTupleLike;
812
-
813
708
  if (hasMultipleCombinationOfContentAllowed) {
814
709
  const {
815
710
  entity: newChildEntity,
@@ -819,33 +714,29 @@ export function validator(nodes, marks, options) {
819
714
  entity
820
715
  } = validateChildMarks(newChildEntity, marksValidationOutput, errorCallback, false, true);
821
716
  return entity;
822
- } // Only go inside valid branch
823
-
717
+ }
824
718
 
825
- const allowedSpecsForEntity = contentValidatorSpec.items.filter(item => Array.isArray(item) ? item.some( // [p, hr, ...] or [p, [text, {}], ...]
719
+ // Only go inside valid branch
720
+ const allowedSpecsForEntity = contentValidatorSpec.items.filter(item => Array.isArray(item) ? item.some(
721
+ // [p, hr, ...] or [p, [text, {}], ...]
826
722
  spec => (Array.isArray(spec) ? spec[0] : spec) === child.type) : true);
827
-
828
723
  if (allowedSpecsForEntity.length) {
829
724
  if (allowedSpecsForEntity.length > 1) {
830
725
  throw new Error('Consider using Tuple instead!');
831
726
  }
832
-
833
727
  const maybeArray = makeArray(allowedSpecsForEntity[0]);
834
728
  const allowedSpecsForChild = maybeArray.filter(item => (Array.isArray(item) ? item[0] : item) === child.type);
835
-
836
729
  if (allowedSpecsForChild.length === 0) {
837
730
  return invalidChildContent(child, errorCallback, validatorSpec);
838
731
  }
732
+
839
733
  /**
840
734
  * When there's multiple possible branches try all of them.
841
735
  * If all of them fails, throw the first one.
842
736
  * e.g.- [['text', { marks: ['a'] }], ['text', { marks: ['b'] }]]
843
737
  */
844
-
845
-
846
738
  let firstError;
847
739
  let firstChild;
848
-
849
740
  for (let i = 0, len = allowedSpecsForChild.length; i < len; i++) {
850
741
  try {
851
742
  const allowedValueForCurrentSpec = [allowedSpecsForChild[i]];
@@ -854,7 +745,6 @@ export function validator(nodes, marks, options) {
854
745
  entity: newChildEntity,
855
746
  marksValidationOutput
856
747
  } = validateNode(child, errorCallback, allowedValueForCurrentSpec, validatorSpec);
857
-
858
748
  if (valid) {
859
749
  const isLastValidationSpec = i === allowedSpecsForChild.length - 1;
860
750
  const {
@@ -862,7 +752,6 @@ export function validator(nodes, marks, options) {
862
752
  entity
863
753
  } = validateChildMarks(newChildEntity, marksValidationOutput, errorCallback, isLastValidationSpec);
864
754
  const unsupportedMarks = entity && entity.marks && entity.marks.filter(mark => mark.type === 'unsupportedMark') || [];
865
-
866
755
  if (marksAreValid && !unsupportedMarks.length) {
867
756
  return entity;
868
757
  } else {
@@ -875,7 +764,6 @@ export function validator(nodes, marks, options) {
875
764
  firstError = firstError || error;
876
765
  }
877
766
  }
878
-
879
767
  if (!errorCallback) {
880
768
  throw firstError;
881
769
  } else {
@@ -885,7 +773,6 @@ export function validator(nodes, marks, options) {
885
773
  return invalidChildContent(child, errorCallback, validatorSpec);
886
774
  }
887
775
  };
888
-
889
776
  newEntity.content = prevEntity.content.map(validateChildNode).filter(Boolean);
890
777
  } else if (!contentValidatorSpec.optional) {
891
778
  return {
@@ -893,16 +780,15 @@ export function validator(nodes, marks, options) {
893
780
  result: err('MISSING_PROPERTIES', 'missing `content` prop')
894
781
  };
895
782
  }
896
- } // Marks
897
-
783
+ }
898
784
 
785
+ // Marks
899
786
  if (prevEntity.marks) {
900
787
  return {
901
788
  hasValidated: true,
902
789
  result: marksValidationFor(validatorSpec, prevEntity, errorCallback, newEntity, err)
903
790
  };
904
791
  }
905
-
906
792
  return specBasedValidationResult;
907
793
  }
908
794
  }