@jsonresume/schema 1.3.1 → 1.5.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/README.md CHANGED
@@ -18,30 +18,33 @@ npm install --save @jsonresume/schema
18
18
 
19
19
  To use
20
20
 
21
+ `validate(resume, callback)` calls back with `(errors, valid)`:
22
+
21
23
  ```js
22
- import resumeSchema from '@jsonresume/schema';
23
- resumeSchema.validate(
24
- { basics: { name: "Thomas" } },
25
- function (err, report) {
26
- if (err) {
27
- console.error("The resume was invalid:", err);
28
- return;
29
- }
30
- console.log("Resume validated successfully:", report);
31
- },
32
- function (err) {
33
- console.error("The resume was invalid:", err);
24
+ const { validate } = require('@jsonresume/schema');
25
+
26
+ validate({ basics: { name: 'Thomas' } }, (errors, valid) => {
27
+ if (!valid) {
28
+ console.error('The resume was invalid:', errors);
29
+ return;
34
30
  }
35
- );
31
+ console.log('Resume validated successfully');
32
+ });
36
33
  ```
37
34
 
38
35
  Or against a full `resume.json`
39
36
 
40
37
  ```js
41
38
  const fs = require('fs');
42
- const resumeSchema = require('@jsonresume/schema');
43
- const resumeObject = JSON.parse(fs.readFileSync('./resume.json', 'utf8'));
44
- resumeSchema.validate(resumeObject);
39
+ const { validate } = require('@jsonresume/schema');
40
+
41
+ const resume = JSON.parse(fs.readFileSync('./resume.json', 'utf8'));
42
+ validate(resume, (errors, valid) => {
43
+ if (!valid) {
44
+ console.error(errors);
45
+ process.exit(1);
46
+ }
47
+ });
45
48
  ```
46
49
 
47
50
  The JSON Resume schema is available from:
@@ -50,6 +53,28 @@ The JSON Resume schema is available from:
50
53
  require('@jsonresume/schema').schema;
51
54
  ```
52
55
 
56
+ ### Extending with `custom`
57
+
58
+ Data with no standard field can go in an optional `custom` object, allowed at
59
+ the root, in `basics`, and on every entry of every section. Its contents are
60
+ free-form; namespace keys by tool to avoid collisions:
61
+
62
+ ```json
63
+ {
64
+ "work": [
65
+ {
66
+ "name": "Tech Corp",
67
+ "position": "Senior Developer",
68
+ "custom": { "myAts": { "teamSize": 12, "directReports": 5 } }
69
+ }
70
+ ]
71
+ }
72
+ ```
73
+
74
+ Themes don't render `custom`, and tools that read and write resumes should
75
+ preserve it unchanged. Unknown top-level properties are also still allowed
76
+ (`additionalProperties: true`); `custom` gives that data a predictable home.
77
+
53
78
  ### Contribute
54
79
 
55
80
  We encourage anyone who's interested in participating in the formation of this standard to join the discussions [here on GitHub](https://github.com/jsonresume/jsonresume.org/issues). Also feel free to fork this project and submit new ideas to add to the JSON Resume Schema standard. To make sure all formatting is kept in check, please install the [EditorConfig plugin](http://editorconfig.org/) for your editor of choice.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/schema.json",
3
3
  "basics": {
4
4
  "name": "Daniel Reyes",
5
5
  "label": "Junior Data Analyst (former Restaurant Manager)",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/schema.json",
3
3
  "basics": {
4
4
  "name": "Maya Okonkwo",
5
5
  "label": "Computer Science Graduate",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/schema.json",
3
3
  "basics": {
4
4
  "name": "Dr. Lena Vasquez",
5
5
  "label": "Staff Software Engineer, Distributed Systems",
package/job-schema.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/job-schema.json",
3
4
  "additionalProperties": true,
4
5
  "definitions": {
5
6
  "iso8601": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonresume/schema",
3
- "version": "1.3.1",
3
+ "version": "1.5.0",
4
4
  "description": "JSON Resume Schema",
5
5
  "private": false,
6
6
  "main": "validator.js",
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/schema.json",
3
3
  "basics": {
4
4
  "name": "Richard Hendriks",
5
5
  "label": "Programmer",
@@ -28,6 +28,7 @@
28
28
  }
29
29
  ]
30
30
  },
31
+ "objective": "Lead engineering for a compression-first storage platform.",
31
32
  "work": [
32
33
  {
33
34
  "name": "Pied Piper",
@@ -42,7 +43,8 @@
42
43
  "Build an algorithm for artist to detect if their music was violating copy right infringement laws",
43
44
  "Successfully won Techcrunch Disrupt",
44
45
  "Optimized an algorithm that holds the current world record for Weisman Scores"
45
- ]
46
+ ],
47
+ "keywords": ["Compression", "C++", "Distributed Systems"]
46
48
  }
47
49
  ],
48
50
  "volunteer": [
@@ -65,7 +67,8 @@
65
67
  "startDate": "2011-06-01",
66
68
  "endDate": "2014-01-01",
67
69
  "score": "4.0",
68
- "courses": ["DB1101 - Basic SQL", "CS2011 - Java Introduction"]
70
+ "courses": ["DB1101 - Basic SQL", "CS2011 - Java Introduction"],
71
+ "summary": "Senior project on lossless compression for streaming media."
69
72
  }
70
73
  ],
71
74
  "awards": [
@@ -76,13 +79,25 @@
76
79
  "summary": "There is no spoon."
77
80
  }
78
81
  ],
82
+ "certificates": [
83
+ {
84
+ "name": "AWS Certified Solutions Architect – Associate",
85
+ "date": "2014-06-01",
86
+ "expiryDate": "2017-06-01",
87
+ "issuer": "Amazon Web Services",
88
+ "url": "https://certificates.example.com/aws/rhendriks",
89
+ "credentialId": "AWS-ASA-12345",
90
+ "summary": "Designing distributed systems on AWS."
91
+ }
92
+ ],
79
93
  "publications": [
80
94
  {
81
95
  "name": "Video compression for 3d media",
82
96
  "publisher": "Hooli",
83
97
  "releaseDate": "2014-10-01",
84
98
  "url": "http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)",
85
- "summary": "Innovative middle-out compression algorithm that changes the way we store data."
99
+ "summary": "Innovative middle-out compression algorithm that changes the way we store data.",
100
+ "type": "article"
86
101
  }
87
102
  ],
88
103
  "skills": [
@@ -134,8 +149,8 @@
134
149
  }
135
150
  ],
136
151
  "meta": {
137
- "canonical": "https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/sample.resume.json",
138
- "version": "v1.0.0",
139
- "lastModified": "2017-12-24T15:53:00"
152
+ "canonical": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/sample.resume.json",
153
+ "version": "v1.3.1",
154
+ "lastModified": "2026-10-22T00:00:00"
140
155
  }
141
156
  }
package/schema.json CHANGED
@@ -1,12 +1,43 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "http://example.com/example.json",
3
+ "$id": "https://raw.githubusercontent.com/jsonresume/jsonresume.org/master/packages/schema/schema.json",
4
4
  "additionalProperties": true,
5
5
  "definitions": {
6
6
  "iso8601": {
7
7
  "type": "string",
8
- "description": "Similar to the standard date type, but each section after the year is optional. e.g. 2014-06-29 or 2023-04",
9
- "pattern": "^([1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9]|[1-2][0-9]{3}-[0-1][0-9]|[1-2][0-9]{3})$"
8
+ "description": "Similar to the standard date type, but each section after the year is optional. e.g. 2014-06-29 or 2023-04. Every date is optional; omit endDate for a current position or ongoing entry (#309).",
9
+ "pattern": "^([1-2][0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])|[1-2][0-9]{3}-(0[1-9]|1[0-2])|[1-2][0-9]{3})$"
10
+ },
11
+ "custom": {
12
+ "type": "object",
13
+ "description": "Tool- or author-specific data that has no standard field yet (#316). Keys are free-form; namespace them by tool (e.g. \"myTool\": { ... }) to avoid collisions. Themes are not expected to render it, and tools should preserve it unchanged when reading and writing resumes.",
14
+ "additionalProperties": true
15
+ },
16
+ "location": {
17
+ "type": "object",
18
+ "additionalProperties": true,
19
+ "properties": {
20
+ "address": {
21
+ "type": "string",
22
+ "description": "To add multiple address lines, use \n. For example, 1234 Glücklichkeit Straße\nHinterhaus 5. Etage li."
23
+ },
24
+ "postalCode": {
25
+ "type": "string",
26
+ "description": "e.g. 12345"
27
+ },
28
+ "city": {
29
+ "type": "string",
30
+ "description": "e.g. Teststadt"
31
+ },
32
+ "countryCode": {
33
+ "type": "string",
34
+ "description": "code as per ISO-3166-1 ALPHA-2, e.g. US, AU, IN"
35
+ },
36
+ "region": {
37
+ "type": "string",
38
+ "description": "The general region where you live. Can be a US state, or a province, for instance."
39
+ }
40
+ }
10
41
  }
11
42
  },
12
43
  "properties": {
@@ -26,6 +57,10 @@
26
57
  "type": "string",
27
58
  "description": "e.g. Web Developer"
28
59
  },
60
+ "pronouns": {
61
+ "type": "string",
62
+ "description": "e.g. she/her, they/them (#312)"
63
+ },
29
64
  "image": {
30
65
  "type": "string",
31
66
  "description": "URL (as per RFC 3986) to a image in JPEG or PNG format"
@@ -49,28 +84,7 @@
49
84
  "description": "Write a short 2-3 sentence biography about yourself"
50
85
  },
51
86
  "location": {
52
- "type": "object",
53
- "additionalProperties": true,
54
- "properties": {
55
- "address": {
56
- "type": "string",
57
- "description": "To add multiple address lines, use \n. For example, 1234 Glücklichkeit Straße\nHinterhaus 5. Etage li."
58
- },
59
- "postalCode": {
60
- "type": "string"
61
- },
62
- "city": {
63
- "type": "string"
64
- },
65
- "countryCode": {
66
- "type": "string",
67
- "description": "code as per ISO-3166-1 ALPHA-2, e.g. US, AU, IN"
68
- },
69
- "region": {
70
- "type": "string",
71
- "description": "The general region where you live. Can be a US state, or a province, for instance."
72
- }
73
- }
87
+ "$ref": "#/definitions/location"
74
88
  },
75
89
  "profiles": {
76
90
  "type": "array",
@@ -94,9 +108,16 @@
94
108
  }
95
109
  }
96
110
  }
111
+ },
112
+ "custom": {
113
+ "$ref": "#/definitions/custom"
97
114
  }
98
115
  }
99
116
  },
117
+ "objective": {
118
+ "type": "string",
119
+ "description": "Forward-looking career goal, e.g. 'Seeking a senior backend role in climate tech'. Distinct from basics.summary, which describes background (#317)"
120
+ },
100
121
  "work": {
101
122
  "type": "array",
102
123
  "items": {
@@ -108,8 +129,15 @@
108
129
  "description": "e.g. Facebook"
109
130
  },
110
131
  "location": {
111
- "type": "string",
112
- "description": "e.g. Menlo Park, CA"
132
+ "oneOf": [
133
+ {
134
+ "type": "string",
135
+ "description": "Free text, e.g. Menlo Park, CA"
136
+ },
137
+ {
138
+ "$ref": "#/definitions/location"
139
+ }
140
+ ]
113
141
  },
114
142
  "description": {
115
143
  "type": "string",
@@ -141,6 +169,17 @@
141
169
  "type": "string",
142
170
  "description": "e.g. Increased profits by 20% from 2011-2012 through viral advertising"
143
171
  }
172
+ },
173
+ "keywords": {
174
+ "type": "array",
175
+ "description": "Skills, tools or technologies used in this role (#293)",
176
+ "items": {
177
+ "type": "string",
178
+ "description": "e.g. React"
179
+ }
180
+ },
181
+ "custom": {
182
+ "$ref": "#/definitions/custom"
144
183
  }
145
184
  }
146
185
  }
@@ -155,6 +194,17 @@
155
194
  "type": "string",
156
195
  "description": "e.g. Facebook"
157
196
  },
197
+ "location": {
198
+ "oneOf": [
199
+ {
200
+ "type": "string",
201
+ "description": "Free text, e.g. Berlin, DE"
202
+ },
203
+ {
204
+ "$ref": "#/definitions/location"
205
+ }
206
+ ]
207
+ },
158
208
  "position": {
159
209
  "type": "string",
160
210
  "description": "e.g. Software Engineer"
@@ -181,6 +231,9 @@
181
231
  "type": "string",
182
232
  "description": "e.g. Increased profits by 20% from 2011-2012 through viral advertising"
183
233
  }
234
+ },
235
+ "custom": {
236
+ "$ref": "#/definitions/custom"
184
237
  }
185
238
  }
186
239
  }
@@ -195,6 +248,17 @@
195
248
  "type": "string",
196
249
  "description": "e.g. Massachusetts Institute of Technology"
197
250
  },
251
+ "location": {
252
+ "oneOf": [
253
+ {
254
+ "type": "string",
255
+ "description": "Free text, e.g. Cambridge, MA"
256
+ },
257
+ {
258
+ "$ref": "#/definitions/location"
259
+ }
260
+ ]
261
+ },
198
262
  "url": {
199
263
  "type": "string",
200
264
  "description": "e.g. http://facebook.example.com",
@@ -225,6 +289,13 @@
225
289
  "type": "string",
226
290
  "description": "e.g. H1302 - Introduction to American history"
227
291
  }
292
+ },
293
+ "summary": {
294
+ "type": "string",
295
+ "description": "Thesis topic, honours, notable projects or other context (#292)"
296
+ },
297
+ "custom": {
298
+ "$ref": "#/definitions/custom"
228
299
  }
229
300
  }
230
301
  }
@@ -250,6 +321,9 @@
250
321
  "summary": {
251
322
  "type": "string",
252
323
  "description": "e.g. Received for my work with Quantum Physics"
324
+ },
325
+ "custom": {
326
+ "$ref": "#/definitions/custom"
253
327
  }
254
328
  }
255
329
  }
@@ -273,9 +347,23 @@
273
347
  "description": "e.g. http://example.com",
274
348
  "format": "uri"
275
349
  },
350
+ "credentialId": {
351
+ "type": "string",
352
+ "description": "Credential or licence number used to verify the certificate, e.g. a licence number or a certification ID (#590)"
353
+ },
276
354
  "issuer": {
277
355
  "type": "string",
278
356
  "description": "e.g. CNCF"
357
+ },
358
+ "expiryDate": {
359
+ "$ref": "#/definitions/iso8601"
360
+ },
361
+ "summary": {
362
+ "type": "string",
363
+ "description": "What the certificate covers (#590)"
364
+ },
365
+ "custom": {
366
+ "$ref": "#/definitions/custom"
279
367
  }
280
368
  }
281
369
  }
@@ -306,6 +394,13 @@
306
394
  "summary": {
307
395
  "type": "string",
308
396
  "description": "Short summary of publication. e.g. Discussion of the World Wide Web, HTTP, HTML."
397
+ },
398
+ "type": {
399
+ "type": "string",
400
+ "description": "e.g. 'article', 'book', 'patent', 'thesis', 'talk' (#295)"
401
+ },
402
+ "custom": {
403
+ "$ref": "#/definitions/custom"
309
404
  }
310
405
  }
311
406
  }
@@ -332,6 +427,9 @@
332
427
  "type": "string",
333
428
  "description": "e.g. HTML"
334
429
  }
430
+ },
431
+ "custom": {
432
+ "$ref": "#/definitions/custom"
335
433
  }
336
434
  }
337
435
  }
@@ -350,6 +448,9 @@
350
448
  "fluency": {
351
449
  "type": "string",
352
450
  "description": "e.g. Fluent, Beginner"
451
+ },
452
+ "custom": {
453
+ "$ref": "#/definitions/custom"
353
454
  }
354
455
  }
355
456
  }
@@ -370,6 +471,9 @@
370
471
  "type": "string",
371
472
  "description": "e.g. Friedrich Nietzsche"
372
473
  }
474
+ },
475
+ "custom": {
476
+ "$ref": "#/definitions/custom"
373
477
  }
374
478
  }
375
479
  }
@@ -388,6 +492,9 @@
388
492
  "reference": {
389
493
  "type": "string",
390
494
  "description": "e.g. Joe blogs was a great employee, who turned up to work at least once a week. He exceeded my expectations when it came to doing nothing."
495
+ },
496
+ "custom": {
497
+ "$ref": "#/definitions/custom"
391
498
  }
392
499
  }
393
500
  }
@@ -449,6 +556,9 @@
449
556
  "type": {
450
557
  "type": "string",
451
558
  "description": " e.g. 'volunteering', 'presentation', 'talk', 'application', 'conference'"
559
+ },
560
+ "custom": {
561
+ "$ref": "#/definitions/custom"
452
562
  }
453
563
  }
454
564
  }
@@ -472,6 +582,9 @@
472
582
  "description": "Using ISO 8601 with YYYY-MM-DDThh:mm:ss"
473
583
  }
474
584
  }
585
+ },
586
+ "custom": {
587
+ "$ref": "#/definitions/custom"
475
588
  }
476
589
  },
477
590
  "title": "Resume Schema",
package/validator.js CHANGED
@@ -4,6 +4,19 @@ const jobSchema = require('./job-schema');
4
4
  const Validator = require('jsonschema').Validator;
5
5
 
6
6
  function validate(resumeJson, callback) {
7
+ // jsonschema treats an absent instance as valid, which hides failed reads
8
+ // and parses upstream
9
+ if (
10
+ resumeJson === null ||
11
+ typeof resumeJson !== 'object' ||
12
+ Array.isArray(resumeJson)
13
+ ) {
14
+ return callback(
15
+ [{ property: 'instance', message: 'resume must be a JSON object' }],
16
+ false
17
+ );
18
+ }
19
+
7
20
  const v = new Validator();
8
21
 
9
22
  const validation = v.validate(resumeJson, schema);