@gsriram24/structured-data-validator 1.6.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 (54) hide show
  1. package/.eslint-header.txt +9 -0
  2. package/.releaserc.json +22 -0
  3. package/CHANGELOG.md +71 -0
  4. package/CODE_OF_CONDUCT.md +79 -0
  5. package/LICENSE +201 -0
  6. package/README.md +109 -0
  7. package/package.json +49 -0
  8. package/renovate.json +4 -0
  9. package/src/index.js +14 -0
  10. package/src/types/3DModel.js +21 -0
  11. package/src/types/AggregateOffer.js +23 -0
  12. package/src/types/AggregateRating.js +35 -0
  13. package/src/types/Answer.js +18 -0
  14. package/src/types/Article.js +26 -0
  15. package/src/types/Brand.js +18 -0
  16. package/src/types/BreadcrumbList.js +148 -0
  17. package/src/types/BroadcastEvent.js +23 -0
  18. package/src/types/Certification.js +26 -0
  19. package/src/types/Clip.js +25 -0
  20. package/src/types/DefinedRegion.js +38 -0
  21. package/src/types/Event.js +51 -0
  22. package/src/types/FAQPage.js +18 -0
  23. package/src/types/HowTo.js +27 -0
  24. package/src/types/HowToDirection.js +19 -0
  25. package/src/types/HowToSection.js +22 -0
  26. package/src/types/HowToStep.js +43 -0
  27. package/src/types/HowToTip.js +19 -0
  28. package/src/types/ImageObject.js +40 -0
  29. package/src/types/JobPosting.js +63 -0
  30. package/src/types/ListItem.js +28 -0
  31. package/src/types/LocalBusiness.js +30 -0
  32. package/src/types/MerchantReturnPolicy.js +96 -0
  33. package/src/types/Offer.js +39 -0
  34. package/src/types/OfferShippingDetails.js +27 -0
  35. package/src/types/Organization.js +18 -0
  36. package/src/types/PeopleAudience.js +37 -0
  37. package/src/types/Person.js +18 -0
  38. package/src/types/PriceSpecification.js +21 -0
  39. package/src/types/Product.js +90 -0
  40. package/src/types/ProductMerchant.js +88 -0
  41. package/src/types/QuantitativeValue.js +36 -0
  42. package/src/types/Question.js +21 -0
  43. package/src/types/Rating.js +56 -0
  44. package/src/types/Recipe.js +75 -0
  45. package/src/types/Review.js +35 -0
  46. package/src/types/SeekToAction.js +22 -0
  47. package/src/types/ShippingDeliveryTime.js +21 -0
  48. package/src/types/SizeSpecification.js +22 -0
  49. package/src/types/VideoObject.js +41 -0
  50. package/src/types/WebSite.js +23 -0
  51. package/src/types/base.js +201 -0
  52. package/src/types/schemaOrg.js +227 -0
  53. package/src/utils.js +15 -0
  54. package/src/validator.js +323 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class AnswerValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [this.required('text')].map((c) => c.bind(this));
17
+ }
18
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class ArticleValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [
17
+ this.required('headline'),
18
+
19
+ this.recommended('author', 'arrayOrObject'),
20
+ this.recommended('dateModified', 'date'),
21
+ this.recommended('datePublished', 'date'),
22
+ this.recommended('image', 'arrayOrObject'),
23
+ this.recommended('publisher', 'object'),
24
+ ].map((c) => c.bind(this));
25
+ }
26
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class Brand extends BaseValidator {
15
+ getConditions() {
16
+ return [this.required('name')].map((c) => c.bind(this));
17
+ }
18
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+ import { isObject } from '../utils.js';
14
+
15
+ export default class BreadcrumbListValidator extends BaseValidator {
16
+ getConditions() {
17
+ return [
18
+ this.required('itemListElement', 'arrayOrObject'),
19
+ this.atLeastTwoItems,
20
+ this.validateItemUrl,
21
+ ].map((c) => c.bind(this));
22
+ }
23
+
24
+ atLeastTwoItems(data) {
25
+ if (
26
+ (data['itemListElement'] &&
27
+ Array.isArray(data['itemListElement']) &&
28
+ data['itemListElement'].length < 2) ||
29
+ isObject(data['itemListElement'])
30
+ ) {
31
+ return {
32
+ issueMessage: 'At least two ListItems are required',
33
+ severity: 'WARNING',
34
+ path: this.path,
35
+ fieldName: 'itemListElement',
36
+ };
37
+ }
38
+ return null;
39
+ }
40
+
41
+ validateItemUrl(data) {
42
+ if (!data['itemListElement']) {
43
+ return null;
44
+ }
45
+
46
+ // Get all items and sort by position
47
+ const items = [];
48
+ if (Array.isArray(data['itemListElement'])) {
49
+ items.push(...data['itemListElement']);
50
+ } else if (isObject(data['itemListElement'])) {
51
+ items.push(data['itemListElement']);
52
+ }
53
+
54
+ // Check if all positions are numbers
55
+ const allPositionsAreNumbers = items.every((item) =>
56
+ this.checkType(item.position, 'number'),
57
+ );
58
+
59
+ // Find last item by position
60
+ let lastItem = null;
61
+ if (allPositionsAreNumbers) {
62
+ lastItem = items.reduce((acc, item) => {
63
+ if (Number(item.position) > Number(acc.position)) {
64
+ return item;
65
+ }
66
+ return acc;
67
+ }, items[0]);
68
+ }
69
+
70
+ const issues = [];
71
+
72
+ for (const [index, listItem] of items.entries()) {
73
+ const newPath = [
74
+ ...this.path,
75
+ {
76
+ type: listItem['@type'] ? listItem['@type'] : 'ListItem',
77
+ index,
78
+ length: items.length,
79
+ property: 'itemListElement',
80
+ },
81
+ ];
82
+
83
+ // if not all positions are numbers, last item is impossible to determine, so no item is considered last
84
+ const isLast = allPositionsAreNumbers ? listItem === lastItem : false;
85
+
86
+ let urlToCheck;
87
+ let urlPath;
88
+
89
+ if (this.checkType(listItem.item, 'object')) {
90
+ urlToCheck = listItem.item['@id'];
91
+ urlPath = 'item.@id';
92
+ } else if (listItem.item) {
93
+ urlToCheck = listItem.item;
94
+ urlPath = 'item';
95
+ }
96
+
97
+ // Last element does not need a URL, but if it has one, it should be valid
98
+ if (isLast && !urlToCheck) {
99
+ continue;
100
+ }
101
+
102
+ try {
103
+ if (!urlToCheck) {
104
+ throw 'Field "item" with URL is missing';
105
+ }
106
+
107
+ // Handle absolute URLs
108
+ if (
109
+ urlToCheck.startsWith('http://') ||
110
+ urlToCheck.startsWith('https://') ||
111
+ this.dataFormat === 'jsonld'
112
+ ) {
113
+ try {
114
+ new URL(urlToCheck);
115
+ } catch (e) {
116
+ throw `Invalid URL in field "${urlPath}"`;
117
+ }
118
+ continue;
119
+ }
120
+
121
+ // Handle relative URLs
122
+ // Special case for microdata: / is allowed
123
+ if (urlToCheck === '/' && this.dataFormat === 'microdata') {
124
+ continue;
125
+ }
126
+
127
+ if (this.dataFormat === 'rdfa' || this.dataFormat === 'microdata') {
128
+ // Remove any query parameters and hash fragments for validation
129
+ const urlWithoutParams = urlToCheck.split('?')[0].split('#')[0];
130
+
131
+ // Check if valid relative path
132
+ if (!urlWithoutParams.match(/^\/[a-z0-9\-/]+$/)) {
133
+ throw `Invalid URL in field "${urlPath}"`;
134
+ }
135
+ }
136
+ } catch (e) {
137
+ issues.push({
138
+ issueMessage: e,
139
+ severity: 'WARNING',
140
+ path: newPath,
141
+ fieldName: urlPath || 'item',
142
+ });
143
+ }
144
+ }
145
+
146
+ return issues;
147
+ }
148
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class BroadcastEventValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.required('startDate', 'date'),
18
+ this.required('endDate', 'date'),
19
+ this.required('isLiveBroadcast', 'boolean'),
20
+ ];
21
+ return conditions.map((c) => c.bind(this));
22
+ }
23
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class CertificationValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [
17
+ this.required('issuedBy'),
18
+ this.required('name'),
19
+
20
+ this.or(
21
+ this.recommended('certificationIdentification'),
22
+ this.recommended('certificationRating'),
23
+ ),
24
+ ].map((c) => c.bind(this));
25
+ }
26
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class ClipValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.required('name', 'string'),
18
+ this.required('startOffset', 'number'),
19
+ this.required('url', 'url'),
20
+
21
+ this.recommended('endOffset', 'number'),
22
+ ];
23
+ return conditions.map((c) => c.bind(this));
24
+ }
25
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class DefinedRegionValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [
17
+ this.required('addressCountry', 'string'),
18
+
19
+ this.or(
20
+ this.recommended('addressRegion'),
21
+ this.recommended('postalCode'),
22
+ ),
23
+ this.regionOrPostalCode,
24
+ ].map((c) => c.bind(this));
25
+ }
26
+
27
+ regionOrPostalCode(data) {
28
+ if (data['addressRegion'] && data['postalCode']) {
29
+ return {
30
+ issueMessage: 'Only one of addressRegion or postalCode can be used',
31
+ severity: 'WARNING',
32
+ path: this.path,
33
+ fieldName: 'addressRegion',
34
+ fieldNames: ['addressRegion', 'postalCode'],
35
+ };
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class EventValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [
17
+ this.required('name'),
18
+ this.required('startDate', 'date'),
19
+ this.locationOrAttendanceMode,
20
+
21
+ this.recommended('description'),
22
+ this.recommended('endDate', 'date'),
23
+ this.recommended('eventAttendanceMode'),
24
+ this.recommended('eventStatus'),
25
+ this.recommended('image', 'arrayOrObject'),
26
+ this.recommended('offers', 'arrayOrObject'),
27
+ this.recommended('organizer', 'object'),
28
+ this.recommended('performer', 'arrayOrObject'),
29
+ ].map((c) => c.bind(this));
30
+ }
31
+
32
+ locationOrAttendanceMode(data) {
33
+ const hasLocation = data.location !== undefined && data.location !== null;
34
+ const hasOnlineAttendanceMode =
35
+ data.eventAttendanceMode &&
36
+ (data.eventAttendanceMode.includes('OnlineEventAttendanceMode') ||
37
+ data.eventAttendanceMode.includes('MixedEventAttendanceMode'));
38
+
39
+ if (!hasLocation && !hasOnlineAttendanceMode) {
40
+ return {
41
+ issueMessage:
42
+ 'Either "location" or online "eventAttendanceMode" is required',
43
+ severity: 'ERROR',
44
+ path: this.path,
45
+ fieldName: 'location',
46
+ fieldNames: ['location', 'eventAttendanceMode'],
47
+ };
48
+ }
49
+ return null;
50
+ }
51
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class FAQPageValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [this.required('mainEntity', 'arrayOrObject')].map((c) => c.bind(this));
17
+ }
18
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class HowToValidator extends BaseValidator {
15
+ getConditions() {
16
+ return [
17
+ this.required('name'),
18
+ this.required('step', 'arrayOrObject'),
19
+
20
+ this.recommended('estimatedCost', 'object'),
21
+ this.recommended('image', 'arrayOrObject'),
22
+ this.recommended('supply', 'arrayOrObject'),
23
+ this.recommended('tool', 'arrayOrObject'),
24
+ this.recommended('totalTime', 'duration'),
25
+ ].map((c) => c.bind(this));
26
+ }
27
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class HowToDirectionValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [this.required('text', 'string')];
17
+ return conditions.map((c) => c.bind(this));
18
+ }
19
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class HowToSectionValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.required('itemListElement'),
18
+ this.required('name', 'string'),
19
+ ];
20
+ return conditions.map((c) => c.bind(this));
21
+ }
22
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class HowToStepValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.textAndItemList,
18
+
19
+ this.recommended('image'),
20
+ this.recommended('name', 'string'),
21
+ this.recommended('url', 'url'),
22
+ this.recommended('video'),
23
+ ];
24
+ return conditions.map((c) => c.bind(this));
25
+ }
26
+
27
+ textAndItemList(data) {
28
+ const issues = [];
29
+ const hasItemList =
30
+ data.itemListElement !== undefined && data.itemListElement !== null;
31
+ const hasText = data.text !== undefined && data.text !== null;
32
+
33
+ if (hasItemList || hasText) {
34
+ issues.push(this.recommended('text')(data));
35
+ issues.push(this.recommended('itemListElement')(data));
36
+ } else {
37
+ issues.push(
38
+ this.or(this.required('text'), this.required('itemListElement'))(data),
39
+ );
40
+ }
41
+ return issues.filter((issue) => issue !== null);
42
+ }
43
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class HowToTipValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [this.required('text', 'string')];
17
+ return conditions.map((c) => c.bind(this));
18
+ }
19
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class ImageObjectValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.or(this.required('contentUrl', 'url'), this.required('url', 'url')),
18
+ ];
19
+
20
+ // Only require these additional fields for root image objects
21
+ if (this.path.length === 1) {
22
+ conditions.push(
23
+ // Be aware, this rule is not shown as an error in the validator. Instead the entity is completely ignored if not at least one of these fields is present.
24
+ this.or(
25
+ this.required('creator'),
26
+ this.required('creditText'),
27
+ this.required('copyrightNotice'),
28
+ this.required('license'),
29
+ ),
30
+
31
+ this.recommended('acquireLicensePage', 'url'),
32
+ this.recommended('creator'),
33
+ this.recommended('creditText'),
34
+ this.recommended('copyrightNotice'),
35
+ this.recommended('license'),
36
+ );
37
+ }
38
+ return conditions.map((c) => c.bind(this));
39
+ }
40
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class JobPostingValidator extends BaseValidator {
15
+ getConditions() {
16
+ const conditions = [
17
+ this.required('title', 'string'),
18
+ this.required('description', 'string'),
19
+ this.required('datePosted', 'date'),
20
+ this.required('hiringOrganization'),
21
+ this.checkJobLocations,
22
+ this.recommended('applicantLocationRequirements'),
23
+ this.recommended('baseSalary'),
24
+ this.recommended('directApply'),
25
+ this.recommended('employmentType'),
26
+ this.recommended('identifier'),
27
+ this.recommended('jobLocationType', 'string'),
28
+ this.recommended('validThrough', 'date'),
29
+ ];
30
+ return conditions.map((c) => c.bind(this));
31
+ }
32
+
33
+ checkJobLocations(data) {
34
+ const issues = [];
35
+ if (data.jobLocationType === 'TELECOMMUTE') {
36
+ if (!data.applicantLocationRequirements) {
37
+ const applicantLocationIssue = this.required(
38
+ 'applicantLocationRequirements',
39
+ )(data);
40
+ if (applicantLocationIssue) {
41
+ issues.push(applicantLocationIssue);
42
+ }
43
+ }
44
+ } else {
45
+ if (!data.applicantLocationRequirements) {
46
+ const jobLocationIssues = this.required('jobLocation')(data);
47
+ if (jobLocationIssues) {
48
+ issues.push(jobLocationIssues);
49
+ }
50
+ }
51
+ }
52
+
53
+ if (data.jobLocation) {
54
+ const addressCountryIssues = this.required(
55
+ 'jobLocation.address.addressCountry',
56
+ )(data);
57
+ if (addressCountryIssues) {
58
+ issues.push(addressCountryIssues);
59
+ }
60
+ }
61
+ return issues;
62
+ }
63
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ import BaseValidator from './base.js';
13
+
14
+ export default class ListItemValidator extends BaseValidator {
15
+ constructor(config) {
16
+ super(config);
17
+ }
18
+
19
+ getConditions() {
20
+ return [
21
+ this.or(
22
+ this.required('name', 'string'),
23
+ this.required('item.name', 'string'),
24
+ ),
25
+ this.required('position'),
26
+ ].map((c) => c.bind(this));
27
+ }
28
+ }