@atlaskit/adf-utils 18.3.0 → 18.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/adf-utils
2
2
 
3
+ ## 18.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`55d241a3794`](https://bitbucket.org/atlassian/atlassian-frontend/commits/55d241a3794) - Improve ADF validation by making deeper and stricter array checks as well as ability to have deep attribute structures.
8
+
3
9
  ## 18.3.0
4
10
 
5
11
  ### Minor Changes
@@ -43,7 +43,8 @@ function mapMarksItems(spec) {
43
43
  }
44
44
  var partitionObject = function partitionObject(obj, predicate) {
45
45
  return Object.keys(obj).reduce(function (acc, key) {
46
- acc[predicate(key, obj[key], obj) ? 0 : 1].push(key);
46
+ var result = predicate(key, obj[key], obj);
47
+ acc[result ? 0 : 1].push(key);
47
48
  return acc;
48
49
  }, [[], []]);
49
50
  };
@@ -152,12 +153,25 @@ function getOptionsForType(type, list) {
152
153
  }
153
154
  return false;
154
155
  }
156
+ var isValidatorSpecAttrs = function isValidatorSpecAttrs(spec) {
157
+ return !!spec.props;
158
+ };
155
159
  function validateAttrs(spec, value) {
156
- // extension_node parameters has no type
157
- if (!(0, _utils.isDefined)(spec.type)) {
160
+ if (!(0, _utils.isDefined)(value)) {
158
161
  return !!spec.optional;
159
162
  }
160
- if (!(0, _utils.isDefined)(value)) {
163
+ if (isValidatorSpecAttrs(spec)) {
164
+ // If spec has ".props" it is ValidatorSpecAttrs and need to pipe back in recursively
165
+ var _partitionObject = partitionObject(spec.props, function (key, subSpec) {
166
+ return validateAttrs(subSpec, value[key]);
167
+ }),
168
+ _partitionObject2 = (0, _slicedToArray2.default)(_partitionObject, 2),
169
+ _ = _partitionObject2[0],
170
+ invalidKeys = _partitionObject2[1];
171
+ return invalidKeys.length === 0;
172
+ }
173
+ // extension_node parameters has no type
174
+ if (!(0, _utils.isDefined)(spec.type)) {
161
175
  return !!spec.optional;
162
176
  }
163
177
  switch (spec.type) {
@@ -175,14 +189,29 @@ function validateAttrs(spec, value) {
175
189
  case 'object':
176
190
  return (0, _utils.isPlainObject)(value);
177
191
  case 'array':
178
- var types = spec.items;
179
- var lastTypeIndex = types.length - 1;
180
192
  if (Array.isArray(value)) {
181
- // We are doing this to support tuple which can be defined as [number, string]
182
- // NOTE: Not validating tuples strictly
183
- return value.every(function (x, i) {
184
- return validateAttrs(types[Math.min(i, lastTypeIndex)], x);
185
- });
193
+ var isTuple = !!spec.isTupleLike;
194
+ var minItems = spec.minItems,
195
+ maxItems = spec.maxItems;
196
+ if (minItems !== undefined && value.length < minItems || maxItems !== undefined && value.length > maxItems) {
197
+ return false;
198
+ }
199
+ if (isTuple) {
200
+ // If value has fewer items than tuple has specs - we are fine with that.
201
+ var numberOfItemsToCheck = Math.min(spec.items.length, value.length);
202
+ return Array(numberOfItemsToCheck).fill(null).every(function (_, i) {
203
+ return validateAttrs(spec.items[i], value[i]);
204
+ });
205
+ } else {
206
+ return value.every(function (valueItem) {
207
+ return (
208
+ // We check that at least one of the specs in the list (spec.items) matches each value from
209
+ spec.items.some(function (itemSpec) {
210
+ return validateAttrs(itemSpec, valueItem);
211
+ })
212
+ );
213
+ });
214
+ }
186
215
  }
187
216
  return false;
188
217
  case 'enum':
@@ -458,11 +487,12 @@ function validator(nodes, marks, options) {
458
487
  for (var i = 0, length = attrOptions.length; i < length; ++i) {
459
488
  var attrOption = attrOptions[i];
460
489
  if (attrOption && attrOption.props) {
461
- var _partitionObject = partitionObject(attrOption.props, function (k, v) {
462
- return validateAttrs(v, prevEntity.attrs[k]);
490
+ var _partitionObject3 = partitionObject(attrOption.props, function (key, spec) {
491
+ var valueToValidate = prevEntity.attrs[key];
492
+ return validateAttrs(spec, valueToValidate);
463
493
  });
464
- var _partitionObject2 = (0, _slicedToArray2.default)(_partitionObject, 2);
465
- invalidAttrs = _partitionObject2[1];
494
+ var _partitionObject4 = (0, _slicedToArray2.default)(_partitionObject3, 2);
495
+ invalidAttrs = _partitionObject4[1];
466
496
  }
467
497
  validatorAttrs = attrOption;
468
498
  if (!invalidAttrs.length) {
@@ -602,12 +632,12 @@ function validator(nodes, marks, options) {
602
632
  valid: true,
603
633
  entity: prevEntity
604
634
  };
605
- var _partitionObject3 = partitionObject(prevEntity, function (k) {
635
+ var _partitionObject5 = partitionObject(prevEntity, function (k) {
606
636
  return (0, _utils.isDefined)(validatorSpec.props[k]);
607
637
  }),
608
- _partitionObject4 = (0, _slicedToArray2.default)(_partitionObject3, 2),
609
- requiredProps = _partitionObject4[0],
610
- redundantProps = _partitionObject4[1];
638
+ _partitionObject6 = (0, _slicedToArray2.default)(_partitionObject5, 2),
639
+ requiredProps = _partitionObject6[0],
640
+ redundantProps = _partitionObject6[1];
611
641
  if (redundantProps.length) {
612
642
  if (mode === 'loose') {
613
643
  newEntity = {
@@ -677,11 +707,11 @@ function validator(nodes, marks, options) {
677
707
 
678
708
  // Required Props
679
709
  // For object format based on `optional` property
680
- var _partitionObject5 = partitionObject(validatorSpec.props, function (k, v) {
710
+ var _partitionObject7 = partitionObject(validatorSpec.props, function (k, v) {
681
711
  return v.optional || (0, _utils.isDefined)(prevEntity[k]);
682
712
  }),
683
- _partitionObject6 = (0, _slicedToArray2.default)(_partitionObject5, 2),
684
- missingProps = _partitionObject6[1];
713
+ _partitionObject8 = (0, _slicedToArray2.default)(_partitionObject7, 2),
714
+ missingProps = _partitionObject8[1];
685
715
  if (missingProps.length) {
686
716
  return {
687
717
  hasValidated: true,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-utils",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -26,7 +26,8 @@ function mapMarksItems(spec, fn = x => x) {
26
26
  }
27
27
  }
28
28
  const partitionObject = (obj, predicate) => Object.keys(obj).reduce((acc, key) => {
29
- acc[predicate(key, obj[key], obj) ? 0 : 1].push(key);
29
+ const result = predicate(key, obj[key], obj);
30
+ acc[result ? 0 : 1].push(key);
30
31
  return acc;
31
32
  }, [[], []]);
32
33
 
@@ -126,12 +127,20 @@ function getOptionsForType(type, list) {
126
127
  }
127
128
  return false;
128
129
  }
130
+ const isValidatorSpecAttrs = spec => {
131
+ return !!spec.props;
132
+ };
129
133
  export function validateAttrs(spec, value) {
130
- // extension_node parameters has no type
131
- if (!isDefined(spec.type)) {
134
+ if (!isDefined(value)) {
132
135
  return !!spec.optional;
133
136
  }
134
- if (!isDefined(value)) {
137
+ if (isValidatorSpecAttrs(spec)) {
138
+ // If spec has ".props" it is ValidatorSpecAttrs and need to pipe back in recursively
139
+ const [_, invalidKeys] = partitionObject(spec.props, (key, subSpec) => validateAttrs(subSpec, value[key]));
140
+ return invalidKeys.length === 0;
141
+ }
142
+ // extension_node parameters has no type
143
+ if (!isDefined(spec.type)) {
135
144
  return !!spec.optional;
136
145
  }
137
146
  switch (spec.type) {
@@ -147,12 +156,24 @@ export function validateAttrs(spec, value) {
147
156
  case 'object':
148
157
  return isPlainObject(value);
149
158
  case 'array':
150
- const types = spec.items;
151
- const lastTypeIndex = types.length - 1;
152
159
  if (Array.isArray(value)) {
153
- // We are doing this to support tuple which can be defined as [number, string]
154
- // NOTE: Not validating tuples strictly
155
- return value.every((x, i) => validateAttrs(types[Math.min(i, lastTypeIndex)], x));
160
+ const isTuple = !!spec.isTupleLike;
161
+ const {
162
+ minItems,
163
+ maxItems
164
+ } = spec;
165
+ if (minItems !== undefined && value.length < minItems || maxItems !== undefined && value.length > maxItems) {
166
+ return false;
167
+ }
168
+ if (isTuple) {
169
+ // If value has fewer items than tuple has specs - we are fine with that.
170
+ const numberOfItemsToCheck = Math.min(spec.items.length, value.length);
171
+ return Array(numberOfItemsToCheck).fill(null).every((_, i) => validateAttrs(spec.items[i], value[i]));
172
+ } else {
173
+ return value.every(valueItem =>
174
+ // We check that at least one of the specs in the list (spec.items) matches each value from
175
+ spec.items.some(itemSpec => validateAttrs(itemSpec, valueItem)));
176
+ }
156
177
  }
157
178
  return false;
158
179
  case 'enum':
@@ -441,8 +462,9 @@ export function validator(nodes, marks, options) {
441
462
  for (let i = 0, length = attrOptions.length; i < length; ++i) {
442
463
  const attrOption = attrOptions[i];
443
464
  if (attrOption && attrOption.props) {
444
- [, invalidAttrs] = partitionObject(attrOption.props, (k, v) => {
445
- return validateAttrs(v, prevEntity.attrs[k]);
465
+ [, invalidAttrs] = partitionObject(attrOption.props, (key, spec) => {
466
+ const valueToValidate = prevEntity.attrs[key];
467
+ return validateAttrs(spec, valueToValidate);
446
468
  });
447
469
  }
448
470
  validatorAttrs = attrOption;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-utils",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -32,7 +32,8 @@ function mapMarksItems(spec) {
32
32
  }
33
33
  var partitionObject = function partitionObject(obj, predicate) {
34
34
  return Object.keys(obj).reduce(function (acc, key) {
35
- acc[predicate(key, obj[key], obj) ? 0 : 1].push(key);
35
+ var result = predicate(key, obj[key], obj);
36
+ acc[result ? 0 : 1].push(key);
36
37
  return acc;
37
38
  }, [[], []]);
38
39
  };
@@ -141,12 +142,25 @@ function getOptionsForType(type, list) {
141
142
  }
142
143
  return false;
143
144
  }
145
+ var isValidatorSpecAttrs = function isValidatorSpecAttrs(spec) {
146
+ return !!spec.props;
147
+ };
144
148
  export function validateAttrs(spec, value) {
145
- // extension_node parameters has no type
146
- if (!isDefined(spec.type)) {
149
+ if (!isDefined(value)) {
147
150
  return !!spec.optional;
148
151
  }
149
- if (!isDefined(value)) {
152
+ if (isValidatorSpecAttrs(spec)) {
153
+ // If spec has ".props" it is ValidatorSpecAttrs and need to pipe back in recursively
154
+ var _partitionObject = partitionObject(spec.props, function (key, subSpec) {
155
+ return validateAttrs(subSpec, value[key]);
156
+ }),
157
+ _partitionObject2 = _slicedToArray(_partitionObject, 2),
158
+ _ = _partitionObject2[0],
159
+ invalidKeys = _partitionObject2[1];
160
+ return invalidKeys.length === 0;
161
+ }
162
+ // extension_node parameters has no type
163
+ if (!isDefined(spec.type)) {
150
164
  return !!spec.optional;
151
165
  }
152
166
  switch (spec.type) {
@@ -164,14 +178,29 @@ export function validateAttrs(spec, value) {
164
178
  case 'object':
165
179
  return isPlainObject(value);
166
180
  case 'array':
167
- var types = spec.items;
168
- var lastTypeIndex = types.length - 1;
169
181
  if (Array.isArray(value)) {
170
- // We are doing this to support tuple which can be defined as [number, string]
171
- // NOTE: Not validating tuples strictly
172
- return value.every(function (x, i) {
173
- return validateAttrs(types[Math.min(i, lastTypeIndex)], x);
174
- });
182
+ var isTuple = !!spec.isTupleLike;
183
+ var minItems = spec.minItems,
184
+ maxItems = spec.maxItems;
185
+ if (minItems !== undefined && value.length < minItems || maxItems !== undefined && value.length > maxItems) {
186
+ return false;
187
+ }
188
+ if (isTuple) {
189
+ // If value has fewer items than tuple has specs - we are fine with that.
190
+ var numberOfItemsToCheck = Math.min(spec.items.length, value.length);
191
+ return Array(numberOfItemsToCheck).fill(null).every(function (_, i) {
192
+ return validateAttrs(spec.items[i], value[i]);
193
+ });
194
+ } else {
195
+ return value.every(function (valueItem) {
196
+ return (
197
+ // We check that at least one of the specs in the list (spec.items) matches each value from
198
+ spec.items.some(function (itemSpec) {
199
+ return validateAttrs(itemSpec, valueItem);
200
+ })
201
+ );
202
+ });
203
+ }
175
204
  }
176
205
  return false;
177
206
  case 'enum':
@@ -447,11 +476,12 @@ export function validator(nodes, marks, options) {
447
476
  for (var i = 0, length = attrOptions.length; i < length; ++i) {
448
477
  var attrOption = attrOptions[i];
449
478
  if (attrOption && attrOption.props) {
450
- var _partitionObject = partitionObject(attrOption.props, function (k, v) {
451
- return validateAttrs(v, prevEntity.attrs[k]);
479
+ var _partitionObject3 = partitionObject(attrOption.props, function (key, spec) {
480
+ var valueToValidate = prevEntity.attrs[key];
481
+ return validateAttrs(spec, valueToValidate);
452
482
  });
453
- var _partitionObject2 = _slicedToArray(_partitionObject, 2);
454
- invalidAttrs = _partitionObject2[1];
483
+ var _partitionObject4 = _slicedToArray(_partitionObject3, 2);
484
+ invalidAttrs = _partitionObject4[1];
455
485
  }
456
486
  validatorAttrs = attrOption;
457
487
  if (!invalidAttrs.length) {
@@ -591,12 +621,12 @@ export function validator(nodes, marks, options) {
591
621
  valid: true,
592
622
  entity: prevEntity
593
623
  };
594
- var _partitionObject3 = partitionObject(prevEntity, function (k) {
624
+ var _partitionObject5 = partitionObject(prevEntity, function (k) {
595
625
  return isDefined(validatorSpec.props[k]);
596
626
  }),
597
- _partitionObject4 = _slicedToArray(_partitionObject3, 2),
598
- requiredProps = _partitionObject4[0],
599
- redundantProps = _partitionObject4[1];
627
+ _partitionObject6 = _slicedToArray(_partitionObject5, 2),
628
+ requiredProps = _partitionObject6[0],
629
+ redundantProps = _partitionObject6[1];
600
630
  if (redundantProps.length) {
601
631
  if (mode === 'loose') {
602
632
  newEntity = {
@@ -666,11 +696,11 @@ export function validator(nodes, marks, options) {
666
696
 
667
697
  // Required Props
668
698
  // For object format based on `optional` property
669
- var _partitionObject5 = partitionObject(validatorSpec.props, function (k, v) {
699
+ var _partitionObject7 = partitionObject(validatorSpec.props, function (k, v) {
670
700
  return v.optional || isDefined(prevEntity[k]);
671
701
  }),
672
- _partitionObject6 = _slicedToArray(_partitionObject5, 2),
673
- missingProps = _partitionObject6[1];
702
+ _partitionObject8 = _slicedToArray(_partitionObject7, 2),
703
+ missingProps = _partitionObject8[1];
674
704
  if (missingProps.length) {
675
705
  return {
676
706
  hasValidated: true,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-utils",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "sideEffects": false
5
5
  }
@@ -55,15 +55,19 @@ export type AttributesSpec = {
55
55
  type: 'array';
56
56
  items: Array<AttributesSpec>;
57
57
  optional?: boolean;
58
- };
58
+ minItems?: number;
59
+ maxItems?: number;
60
+ isTupleLike?: boolean;
61
+ } | ValidatorSpecAttrs;
62
+ export interface ValidatorSpecAttrs {
63
+ props: {
64
+ [key: string]: AttributesSpec;
65
+ };
66
+ optional?: boolean;
67
+ }
59
68
  export interface ValidatorSpec {
60
69
  props?: {
61
- attrs?: {
62
- props: {
63
- [key: string]: AttributesSpec;
64
- };
65
- optional?: boolean;
66
- };
70
+ attrs?: ValidatorSpecAttrs;
67
71
  content?: ValidatorContent;
68
72
  text?: AttributesSpec;
69
73
  marks?: {
@@ -55,15 +55,19 @@ export type AttributesSpec = {
55
55
  type: 'array';
56
56
  items: Array<AttributesSpec>;
57
57
  optional?: boolean;
58
- };
58
+ minItems?: number;
59
+ maxItems?: number;
60
+ isTupleLike?: boolean;
61
+ } | ValidatorSpecAttrs;
62
+ export interface ValidatorSpecAttrs {
63
+ props: {
64
+ [key: string]: AttributesSpec;
65
+ };
66
+ optional?: boolean;
67
+ }
59
68
  export interface ValidatorSpec {
60
69
  props?: {
61
- attrs?: {
62
- props: {
63
- [key: string]: AttributesSpec;
64
- };
65
- optional?: boolean;
66
- };
70
+ attrs?: ValidatorSpecAttrs;
67
71
  content?: ValidatorContent;
68
72
  text?: AttributesSpec;
69
73
  marks?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/adf-utils",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "description": "Set of utilities to traverse, modify and create ADF documents.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -25,7 +25,7 @@
25
25
  "atlassian": {
26
26
  "team": "Editor",
27
27
  "inPublicMirror": true,
28
- "releaseModel": "scheduled"
28
+ "releaseModel": "continuous"
29
29
  },
30
30
  "af:exports": {
31
31
  "./builders": "./src/builders.ts",
@@ -47,7 +47,6 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@atlaskit/docs": "*",
50
- "@atlaskit/json-schema-generator": "^3.3.0",
51
50
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
52
51
  "jscodeshift": "^0.13.0",
53
52
  "react": "^16.8.0",
@@ -0,0 +1,9 @@
1
+ ## API Report File for "@atlaskit/adf-utils"
2
+
3
+ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4
+
5
+ ```ts
6
+
7
+ // (No @packageDocumentation comment for this package)
8
+
9
+ ```