sslabdata 3.0.0__py3-none-any.whl
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.
- sslabdata/__init__.py +40 -0
- sslabdata/assembler.py +452 -0
- sslabdata/cli.py +274 -0
- sslabdata/config.py +443 -0
- sslabdata/diagnostics.py +159 -0
- sslabdata/exporters.py +86 -0
- sslabdata/loaders.py +298 -0
- sslabdata/models.py +342 -0
- sslabdata/parsers/__init__.py +0 -0
- sslabdata/parsers/bibtex.py +1132 -0
- sslabdata/parsers/latex.py +215 -0
- sslabdata/resolver.py +517 -0
- sslabdata/schema/__init__.py +0 -0
- sslabdata/schema/v5/output.schema.json +458 -0
- sslabdata-3.0.0.dist-info/METADATA +409 -0
- sslabdata-3.0.0.dist-info/RECORD +20 -0
- sslabdata-3.0.0.dist-info/WHEEL +5 -0
- sslabdata-3.0.0.dist-info/entry_points.txt +2 -0
- sslabdata-3.0.0.dist-info/licenses/LICENSE +21 -0
- sslabdata-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/siddhss5/sslabdata/schema-v5/schema/v5/output.schema.json",
|
|
4
|
+
"title": "sslabdata output",
|
|
5
|
+
"description": "The lab.yml / lab.json file written by `sslabdata --output`. YAML and JSON exports hold the same data. Published schemas are immutable: this one is served from the `schema-v5` tag, which is created when this version ships and is never moved.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schema_version", "generator", "lab", "works", "people", "projects",
|
|
9
|
+
"collaborators"
|
|
10
|
+
],
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"properties": {
|
|
13
|
+
"schema_version": {
|
|
14
|
+
"description": "Version of this output format. Bumped when a change could break a consumer.",
|
|
15
|
+
"const": 5
|
|
16
|
+
},
|
|
17
|
+
"generator": {
|
|
18
|
+
"description": "What compiled this document. It carries no timestamp: a build timestamp would make every run differ, and git records when.",
|
|
19
|
+
"type": "object",
|
|
20
|
+
"required": ["name", "version", "schema_version"],
|
|
21
|
+
"additionalProperties": false,
|
|
22
|
+
"properties": {
|
|
23
|
+
"name": { "type": "string", "minLength": 1 },
|
|
24
|
+
"version": {
|
|
25
|
+
"description": "The sslabdata package version. Independent of schema_version; neither can be derived from the other.",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"minLength": 1
|
|
28
|
+
},
|
|
29
|
+
"schema_version": { "const": 5 }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"lab": {
|
|
33
|
+
"description": "The lab section of lab.yaml, copied through unchanged and always emitted, so an empty header is distinguishable from no header. The properties below are declared for documentation only: this object stays open, and a consumer must probe for the keys it wants rather than expect a fixed set.",
|
|
34
|
+
"type": "object",
|
|
35
|
+
"additionalProperties": true,
|
|
36
|
+
"properties": {
|
|
37
|
+
"name": { "type": "string" },
|
|
38
|
+
"description": { "type": "string" },
|
|
39
|
+
"institution": { "type": "string" },
|
|
40
|
+
"department": { "type": "string" },
|
|
41
|
+
"website": { "type": "string" },
|
|
42
|
+
"email": { "type": "string" },
|
|
43
|
+
"address": { "type": "string" },
|
|
44
|
+
"logo": { "type": "string" },
|
|
45
|
+
"links": { "type": "object" }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"works": {
|
|
49
|
+
"description": "Everything the lab produced that carries a citation key. Ordered by year descending, works with no year last; ties keep read order.",
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": { "$ref": "#/$defs/work" }
|
|
52
|
+
},
|
|
53
|
+
"people": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": { "$ref": "#/$defs/person" }
|
|
56
|
+
},
|
|
57
|
+
"projects": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": { "$ref": "#/$defs/project" }
|
|
60
|
+
},
|
|
61
|
+
"collaborators": {
|
|
62
|
+
"description": "A derived grouping over the authorships that resolved to nobody in people.yaml. Not a list of people: see /$defs/collaborator.",
|
|
63
|
+
"type": "array",
|
|
64
|
+
"items": { "$ref": "#/$defs/collaborator" }
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"$defs": {
|
|
68
|
+
"optionalString": { "type": ["string", "null"] },
|
|
69
|
+
"idList": {
|
|
70
|
+
"type": "array",
|
|
71
|
+
"items": { "type": "string", "minLength": 1 }
|
|
72
|
+
},
|
|
73
|
+
"derived": {
|
|
74
|
+
"description": "Reserved for sslabdata. Every key inside it is sslabdata's; consumers tolerate keys they do not know and must not write their own. A key graduating out of it into a named property is still a major change. It is not a general extension mechanism.",
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": true
|
|
77
|
+
},
|
|
78
|
+
"venue": {
|
|
79
|
+
"description": "Where a work appeared. The one place sslabdata normalises across entry types, collapsing `journal`, `booktitle`, `school` and `institution` to one name plus a kind.",
|
|
80
|
+
"type": "object",
|
|
81
|
+
"required": ["kind", "name"],
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"properties": {
|
|
84
|
+
"kind": {
|
|
85
|
+
"description": "An open string, deliberately not an enum so that new work types need no version bump. Documented values: `journal`, `conference`, `book`, `institution`, `repository`, `other`.",
|
|
86
|
+
"type": "string",
|
|
87
|
+
"minLength": 1
|
|
88
|
+
},
|
|
89
|
+
"name": { "type": "string", "minLength": 1 }
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"link": {
|
|
93
|
+
"description": "One URL a work can be reached at. A link that fails verification is kept and labelled, never deleted, so a consumer can tell a broken link from an absent one.",
|
|
94
|
+
"type": "object",
|
|
95
|
+
"required": ["url", "label", "origin", "verification"],
|
|
96
|
+
"additionalProperties": false,
|
|
97
|
+
"properties": {
|
|
98
|
+
"url": { "type": "string", "minLength": 1 },
|
|
99
|
+
"label": { "$ref": "#/$defs/optionalString" },
|
|
100
|
+
"origin": {
|
|
101
|
+
"description": "Where the link came from. An open string; documented values are `input` (the entry's own field), `sidecar`, `enrichment`, `inferred` and `derived` (sslabdata built it). Only `input` means the entry supplied it.",
|
|
102
|
+
"type": "string",
|
|
103
|
+
"minLength": 1
|
|
104
|
+
},
|
|
105
|
+
"verification": {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"required": ["status"],
|
|
108
|
+
"additionalProperties": false,
|
|
109
|
+
"properties": {
|
|
110
|
+
"status": {
|
|
111
|
+
"description": "`unchecked` when nothing has looked, `verified` when a local filesystem check or a committed cache found it, `missing` when one looked and it was not there. A build never fetches.",
|
|
112
|
+
"enum": ["unchecked", "verified", "missing"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"linkMap": {
|
|
119
|
+
"description": "An open map from link kind to a list of links, so that two code repositories or two videos can both be carried. Documented kinds: `pdf`, `doi`, `arxiv`, `url`, `video`. Unordered; consumers filter.",
|
|
120
|
+
"type": "object",
|
|
121
|
+
"additionalProperties": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"items": { "$ref": "#/$defs/link" }
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"identifierMap": {
|
|
127
|
+
"description": "An open map from identifier scheme to a unique list of identifiers, for example {\"doi\": [\"10.5555/...\"], \"arxiv\": [\"2501.01234\"]}. Schemes are documented, not enumerated. A list because ISBN and ISSN genuinely repeat. Unordered; consumers filter.",
|
|
128
|
+
"type": "object",
|
|
129
|
+
"additionalProperties": {
|
|
130
|
+
"type": "array",
|
|
131
|
+
"items": { "type": "string", "minLength": 1 },
|
|
132
|
+
"uniqueItems": true
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"resolution": {
|
|
136
|
+
"description": "Whether this contributor was matched to a person, and how. Both are open strings: #24 adds `ambiguous` to the status and #25 fills the method with an override or an ORCID, and neither is breaking.",
|
|
137
|
+
"type": "object",
|
|
138
|
+
"required": ["status", "method"],
|
|
139
|
+
"additionalProperties": false,
|
|
140
|
+
"properties": {
|
|
141
|
+
"status": {
|
|
142
|
+
"description": "Documented values: `resolved`, `unresolved`.",
|
|
143
|
+
"type": "string",
|
|
144
|
+
"minLength": 1
|
|
145
|
+
},
|
|
146
|
+
"method": {
|
|
147
|
+
"description": "Documented values: `exact`, `fuzzy`, or null when nothing matched.",
|
|
148
|
+
"$ref": "#/$defs/optionalString"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"nameParts": {
|
|
153
|
+
"description": "The name properties every contributor record carries: the readable form, the parts BibTeX split it into, its position in the list, the person it resolved to, and how. Referenced in place, so each record below still declares every key it allows -- `additionalProperties: false` sees only its own `properties`.",
|
|
154
|
+
"type": "object",
|
|
155
|
+
"required": [
|
|
156
|
+
"name", "position", "person_id", "given", "von", "family", "suffix",
|
|
157
|
+
"literal", "resolution", "derived"
|
|
158
|
+
],
|
|
159
|
+
"properties": {
|
|
160
|
+
"name": {
|
|
161
|
+
"description": "The structured parts joined in reading order. A readable form of the input name, not a citation form: it does not abbreviate, expand or normalise.",
|
|
162
|
+
"type": "string",
|
|
163
|
+
"minLength": 1
|
|
164
|
+
},
|
|
165
|
+
"position": {
|
|
166
|
+
"description": "1-based position in this work's list. With the work's bib_id it addresses the record.",
|
|
167
|
+
"type": "integer",
|
|
168
|
+
"minimum": 1
|
|
169
|
+
},
|
|
170
|
+
"person_id": {
|
|
171
|
+
"description": "The id of the matching person in people.yaml, or null. It means nothing else.",
|
|
172
|
+
"type": ["string", "null"]
|
|
173
|
+
},
|
|
174
|
+
"given": {
|
|
175
|
+
"description": "Given and middle names, as the entry supplied them: an entry writing `Brown, B.` yields `B.`, which is correct rather than a gap. Null for a name written as one brace-protected unit.",
|
|
176
|
+
"$ref": "#/$defs/optionalString"
|
|
177
|
+
},
|
|
178
|
+
"von": {
|
|
179
|
+
"description": "Surname particles such as `van den`. Null when the name has none.",
|
|
180
|
+
"$ref": "#/$defs/optionalString"
|
|
181
|
+
},
|
|
182
|
+
"family": {
|
|
183
|
+
"description": "The surname, without particles or suffix. Null for a name written as one brace-protected unit.",
|
|
184
|
+
"$ref": "#/$defs/optionalString"
|
|
185
|
+
},
|
|
186
|
+
"suffix": {
|
|
187
|
+
"description": "A lineage suffix such as `Jr.`. Null when the name has none.",
|
|
188
|
+
"$ref": "#/$defs/optionalString"
|
|
189
|
+
},
|
|
190
|
+
"literal": {
|
|
191
|
+
"description": "A name written as one brace-protected unit, such as `{Example Robotics Consortium}`. Null for a parsed name, where the four parts above apply instead. Brace protection means `do not parse this`, so it does not assert that the name is an organisation.",
|
|
192
|
+
"$ref": "#/$defs/optionalString"
|
|
193
|
+
},
|
|
194
|
+
"resolution": { "$ref": "#/$defs/resolution" },
|
|
195
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"authorship": {
|
|
199
|
+
"description": "One authorship of a work, addressed by (work.bib_id, position). The authorship is the primary contributor record, so two people who write their names identically are never merged at this level. It references exactly one contributor: `person_id` for a person in people.yaml, `collaborator_key` for the grouping an unresolved authorship fell into.",
|
|
200
|
+
"$ref": "#/$defs/nameParts",
|
|
201
|
+
"type": "object",
|
|
202
|
+
"required": ["collaborator_key", "equal_contribution"],
|
|
203
|
+
"additionalProperties": false,
|
|
204
|
+
"properties": {
|
|
205
|
+
"name": { "type": "string" },
|
|
206
|
+
"position": { "type": "integer" },
|
|
207
|
+
"person_id": { "type": ["string", "null"] },
|
|
208
|
+
"given": { "$ref": "#/$defs/optionalString" },
|
|
209
|
+
"von": { "$ref": "#/$defs/optionalString" },
|
|
210
|
+
"family": { "$ref": "#/$defs/optionalString" },
|
|
211
|
+
"suffix": { "$ref": "#/$defs/optionalString" },
|
|
212
|
+
"literal": { "$ref": "#/$defs/optionalString" },
|
|
213
|
+
"resolution": { "$ref": "#/$defs/resolution" },
|
|
214
|
+
"derived": { "$ref": "#/$defs/derived" },
|
|
215
|
+
"collaborator_key": {
|
|
216
|
+
"description": "The key of the collaborator grouping this authorship fell into, or null when it resolved to a person.",
|
|
217
|
+
"$ref": "#/$defs/optionalString"
|
|
218
|
+
},
|
|
219
|
+
"equal_contribution": {
|
|
220
|
+
"description": "True when the BibTeX entry marked this author with a `*`. The marker itself is not part of the name.",
|
|
221
|
+
"type": "boolean"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"oneOf": [
|
|
225
|
+
{
|
|
226
|
+
"properties": {
|
|
227
|
+
"person_id": { "type": "string", "minLength": 1 },
|
|
228
|
+
"collaborator_key": { "type": "null" }
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"properties": {
|
|
233
|
+
"person_id": { "type": "null" },
|
|
234
|
+
"collaborator_key": { "type": "string", "minLength": 1 }
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
"editorship": {
|
|
240
|
+
"description": "One editor of a work. Editing a volume is not an authorship: an editor is excluded from person.work_ids, from a project's people and from collaborators, so one that matched nobody is simply `person_id: null` and references no grouping.",
|
|
241
|
+
"$ref": "#/$defs/nameParts",
|
|
242
|
+
"type": "object",
|
|
243
|
+
"additionalProperties": false,
|
|
244
|
+
"properties": {
|
|
245
|
+
"name": { "type": "string" },
|
|
246
|
+
"position": { "type": "integer" },
|
|
247
|
+
"person_id": { "type": ["string", "null"] },
|
|
248
|
+
"given": { "$ref": "#/$defs/optionalString" },
|
|
249
|
+
"von": { "$ref": "#/$defs/optionalString" },
|
|
250
|
+
"family": { "$ref": "#/$defs/optionalString" },
|
|
251
|
+
"suffix": { "$ref": "#/$defs/optionalString" },
|
|
252
|
+
"literal": { "$ref": "#/$defs/optionalString" },
|
|
253
|
+
"resolution": { "$ref": "#/$defs/resolution" },
|
|
254
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
"work": {
|
|
258
|
+
"type": "object",
|
|
259
|
+
"required": [
|
|
260
|
+
"bib_id", "source", "title", "authors", "editors", "year", "venue",
|
|
261
|
+
"volume", "number", "pages", "series", "edition", "publisher",
|
|
262
|
+
"address", "organization", "chapter", "month", "howpublished", "type",
|
|
263
|
+
"category", "entry_type", "abstract", "note", "identifiers", "links",
|
|
264
|
+
"project_ids", "bibtex", "derived"
|
|
265
|
+
],
|
|
266
|
+
"additionalProperties": false,
|
|
267
|
+
"properties": {
|
|
268
|
+
"bib_id": {
|
|
269
|
+
"description": "The BibTeX citation key, as written.",
|
|
270
|
+
"type": "string",
|
|
271
|
+
"minLength": 1
|
|
272
|
+
},
|
|
273
|
+
"source": {
|
|
274
|
+
"description": "Where this work was read from. Per-field provenance stays out of the document; #30 uses `derived`.",
|
|
275
|
+
"type": "object",
|
|
276
|
+
"required": ["file", "key"],
|
|
277
|
+
"additionalProperties": false,
|
|
278
|
+
"properties": {
|
|
279
|
+
"file": {
|
|
280
|
+
"description": "The configured `bib_files[].name`, never an absolute path.",
|
|
281
|
+
"type": "string"
|
|
282
|
+
},
|
|
283
|
+
"key": {
|
|
284
|
+
"description": "The citation key as written, which is `bib_id` again.",
|
|
285
|
+
"type": "string",
|
|
286
|
+
"minLength": 1
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
"title": { "type": "string" },
|
|
291
|
+
"authors": { "type": "array", "items": { "$ref": "#/$defs/authorship" } },
|
|
292
|
+
"editors": { "type": "array", "items": { "$ref": "#/$defs/editorship" } },
|
|
293
|
+
"year": {
|
|
294
|
+
"description": "Null when the entry supplied none, which is reported as a diagnostic. A work with no year sorts last.",
|
|
295
|
+
"type": ["integer", "null"],
|
|
296
|
+
"minimum": 0
|
|
297
|
+
},
|
|
298
|
+
"venue": {
|
|
299
|
+
"description": "The container this work appeared in, or null when the entry names none.",
|
|
300
|
+
"oneOf": [{ "$ref": "#/$defs/venue" }, { "type": "null" }]
|
|
301
|
+
},
|
|
302
|
+
"volume": { "$ref": "#/$defs/optionalString" },
|
|
303
|
+
"number": {
|
|
304
|
+
"description": "BibTeX's `number`, with BibTeX's meaning: an issue number for an article and a report number for a technical report. Reinterpreting it is not sslabdata's job; `venue.kind` gives a consumer the branch it needs.",
|
|
305
|
+
"$ref": "#/$defs/optionalString"
|
|
306
|
+
},
|
|
307
|
+
"pages": { "$ref": "#/$defs/optionalString" },
|
|
308
|
+
"series": { "$ref": "#/$defs/optionalString" },
|
|
309
|
+
"edition": { "$ref": "#/$defs/optionalString" },
|
|
310
|
+
"publisher": { "$ref": "#/$defs/optionalString" },
|
|
311
|
+
"address": { "$ref": "#/$defs/optionalString" },
|
|
312
|
+
"organization": { "$ref": "#/$defs/optionalString" },
|
|
313
|
+
"chapter": { "$ref": "#/$defs/optionalString" },
|
|
314
|
+
"month": { "$ref": "#/$defs/optionalString" },
|
|
315
|
+
"howpublished": { "$ref": "#/$defs/optionalString" },
|
|
316
|
+
"type": {
|
|
317
|
+
"description": "BibTeX's `type` field: a report's own label, or a section label for a chapter. Not the entry type, which is `entry_type`.",
|
|
318
|
+
"$ref": "#/$defs/optionalString"
|
|
319
|
+
},
|
|
320
|
+
"category": {
|
|
321
|
+
"description": "The category of the bib_files entry the file was listed under, not anything in the .bib file.",
|
|
322
|
+
"type": "string"
|
|
323
|
+
},
|
|
324
|
+
"entry_type": {
|
|
325
|
+
"description": "The BibTeX entry type, lower-cased.",
|
|
326
|
+
"type": "string",
|
|
327
|
+
"minLength": 1
|
|
328
|
+
},
|
|
329
|
+
"abstract": { "$ref": "#/$defs/optionalString" },
|
|
330
|
+
"note": { "$ref": "#/$defs/optionalString" },
|
|
331
|
+
"identifiers": { "$ref": "#/$defs/identifierMap" },
|
|
332
|
+
"links": { "$ref": "#/$defs/linkMap" },
|
|
333
|
+
"project_ids": { "$ref": "#/$defs/idList" },
|
|
334
|
+
"bibtex": {
|
|
335
|
+
"description": "The entry re-serialized as BibTeX, for a reader to copy, and null when it could not be written back out. It is a re-serialization of the entry's data and explicitly not a source of properties.",
|
|
336
|
+
"$ref": "#/$defs/optionalString"
|
|
337
|
+
},
|
|
338
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"person": {
|
|
342
|
+
"type": "object",
|
|
343
|
+
"required": [
|
|
344
|
+
"id", "name", "role", "status", "photo", "email", "website",
|
|
345
|
+
"co_advisor", "start_year", "end_year", "degree", "thesis_title",
|
|
346
|
+
"current_position", "work_ids", "derived"
|
|
347
|
+
],
|
|
348
|
+
"additionalProperties": false,
|
|
349
|
+
"properties": {
|
|
350
|
+
"id": { "type": "string", "minLength": 1 },
|
|
351
|
+
"name": { "type": "string", "minLength": 1 },
|
|
352
|
+
"role": { "$ref": "#/$defs/optionalString" },
|
|
353
|
+
"status": { "type": "string" },
|
|
354
|
+
"photo": { "$ref": "#/$defs/optionalString" },
|
|
355
|
+
"email": { "$ref": "#/$defs/optionalString" },
|
|
356
|
+
"website": { "$ref": "#/$defs/optionalString" },
|
|
357
|
+
"co_advisor": { "$ref": "#/$defs/optionalString" },
|
|
358
|
+
"start_year": { "type": ["integer", "null"] },
|
|
359
|
+
"end_year": { "type": ["integer", "null"] },
|
|
360
|
+
"degree": { "$ref": "#/$defs/optionalString" },
|
|
361
|
+
"thesis_title": { "$ref": "#/$defs/optionalString" },
|
|
362
|
+
"current_position": { "$ref": "#/$defs/optionalString" },
|
|
363
|
+
"work_ids": {
|
|
364
|
+
"description": "The works this person authored. Editors are not authorships and are not listed.",
|
|
365
|
+
"$ref": "#/$defs/idList"
|
|
366
|
+
},
|
|
367
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
"project": {
|
|
371
|
+
"type": "object",
|
|
372
|
+
"required": [
|
|
373
|
+
"id", "title", "description", "website", "image", "status",
|
|
374
|
+
"work_ids", "people_ids", "derived"
|
|
375
|
+
],
|
|
376
|
+
"additionalProperties": false,
|
|
377
|
+
"properties": {
|
|
378
|
+
"id": { "type": "string", "minLength": 1 },
|
|
379
|
+
"title": { "type": "string" },
|
|
380
|
+
"description": { "$ref": "#/$defs/optionalString" },
|
|
381
|
+
"website": { "$ref": "#/$defs/optionalString" },
|
|
382
|
+
"image": {
|
|
383
|
+
"description": "A URL or a site path, the same kind of value as a person's `photo`. Plain text: deciding which URLs are safe to render is the renderer's job.",
|
|
384
|
+
"$ref": "#/$defs/optionalString"
|
|
385
|
+
},
|
|
386
|
+
"status": { "type": "string" },
|
|
387
|
+
"work_ids": { "$ref": "#/$defs/idList" },
|
|
388
|
+
"people_ids": { "$ref": "#/$defs/idList" },
|
|
389
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
"collaborator": {
|
|
393
|
+
"description": "A grouping over unresolved authorships, not an identity. A consumer that distrusts the grouping can ignore it and work from `authorships` instead; that property is what makes the grouping safe to publish.",
|
|
394
|
+
"type": "object",
|
|
395
|
+
"required": [
|
|
396
|
+
"key", "grouped_by", "name_kind", "name", "given", "von", "family",
|
|
397
|
+
"suffix", "literal", "name_variants", "authorships", "work_ids",
|
|
398
|
+
"last_year", "derived"
|
|
399
|
+
],
|
|
400
|
+
"additionalProperties": false,
|
|
401
|
+
"properties": {
|
|
402
|
+
"key": {
|
|
403
|
+
"description": "A lookup key, explicitly not an assertion about a human: a readable slug of the normalised name plus an always-present short digest, so adding an unrelated collaborator can never change an existing key.",
|
|
404
|
+
"type": "string",
|
|
405
|
+
"minLength": 1
|
|
406
|
+
},
|
|
407
|
+
"grouped_by": {
|
|
408
|
+
"description": "The policy that built the key. An open string; `normalized_name`, or `declared` for a grouping the collaborators file declares.",
|
|
409
|
+
"type": "string",
|
|
410
|
+
"minLength": 1
|
|
411
|
+
},
|
|
412
|
+
"name_kind": {
|
|
413
|
+
"description": "`personal` or `literal`. Not `person`/`organization`: brace protection in BibTeX means `do not parse this`, which covers organisations but also mononyms, so the document must not assert corporate-ness.",
|
|
414
|
+
"enum": ["personal", "literal"]
|
|
415
|
+
},
|
|
416
|
+
"name": {
|
|
417
|
+
"description": "The readable form of the first spelling this key grouped, in document order.",
|
|
418
|
+
"type": "string",
|
|
419
|
+
"minLength": 1
|
|
420
|
+
},
|
|
421
|
+
"given": { "$ref": "#/$defs/optionalString" },
|
|
422
|
+
"von": { "$ref": "#/$defs/optionalString" },
|
|
423
|
+
"family": { "$ref": "#/$defs/optionalString" },
|
|
424
|
+
"suffix": { "$ref": "#/$defs/optionalString" },
|
|
425
|
+
"literal": { "$ref": "#/$defs/optionalString" },
|
|
426
|
+
"name_variants": {
|
|
427
|
+
"description": "The distinct source spellings that normalised to this key, ascending.",
|
|
428
|
+
"type": "array",
|
|
429
|
+
"items": { "type": "string", "minLength": 1 },
|
|
430
|
+
"uniqueItems": true
|
|
431
|
+
},
|
|
432
|
+
"authorships": {
|
|
433
|
+
"description": "The occurrences this key grouped, in document order.",
|
|
434
|
+
"type": "array",
|
|
435
|
+
"items": {
|
|
436
|
+
"type": "object",
|
|
437
|
+
"required": ["work_id", "position"],
|
|
438
|
+
"additionalProperties": false,
|
|
439
|
+
"properties": {
|
|
440
|
+
"work_id": { "type": "string", "minLength": 1 },
|
|
441
|
+
"position": { "type": "integer", "minimum": 1 }
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
"minItems": 1
|
|
445
|
+
},
|
|
446
|
+
"work_ids": {
|
|
447
|
+
"description": "The distinct works this key grouped, in document order. One work listing two authorships under this key appears once; `authorships` lists both.",
|
|
448
|
+
"$ref": "#/$defs/idList"
|
|
449
|
+
},
|
|
450
|
+
"last_year": {
|
|
451
|
+
"description": "The greatest year of any work contributing an occurrence, or null when none of them has one.",
|
|
452
|
+
"type": ["integer", "null"]
|
|
453
|
+
},
|
|
454
|
+
"derived": { "$ref": "#/$defs/derived" }
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|