@larsgw/formica 0.10.5 → 0.11.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.
@@ -397,7 +397,7 @@ function makeLinkedDataForScientificName(name) {
397
397
  return node;
398
398
  }
399
399
  function makeLinkedDataForResource(work, files, resourceId) {
400
- var _a, _b, _c, _d, _e, _f, _g, _h;
400
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
401
401
  const resource = new resource_1.WorkResource({});
402
402
  if (!resourceId) {
403
403
  resourceId = `${work.get('id')}:0`;
@@ -479,7 +479,7 @@ function makeLinkedDataForResource(work, files, resourceId) {
479
479
  if (tags.length) {
480
480
  node['ac:tag'] = tags;
481
481
  }
482
- if (files.resources[resourceId].taxa) {
482
+ if ((_j = files.resources[resourceId]) === null || _j === void 0 ? void 0 : _j.taxa) {
483
483
  const leafs = new Set(files.resources[resourceId].taxa.map(taxon => taxon.scientificNameID));
484
484
  const taxa = [];
485
485
  for (const taxon of files.resources[resourceId].taxa) {
@@ -679,9 +679,16 @@ function* makeLinkedDataForWorks(files) {
679
679
  for (const work of works.entities) {
680
680
  const id = work.get('id');
681
681
  const node = makeLinkedDataForWork(work, files);
682
+ const resources = [];
682
683
  let resourceIndex = 1;
683
684
  let resourceId;
684
685
  while ((resourceId = `${id}:${resourceIndex++}`) in files.resources) {
686
+ resources.push(resourceId);
687
+ }
688
+ if (!resources.length) {
689
+ resources.push(undefined);
690
+ }
691
+ for (const resourceId of resources) {
685
692
  const resource = makeLinkedDataForResource(work, files, resourceId);
686
693
  if (!Array.isArray(node['dcterms:hasPart'])) {
687
694
  node['dcterms:hasPart'] = [];
@@ -66,6 +66,13 @@ const FLAGS = [
66
66
  ];
67
67
  const RESOURCE_DELIMITER = '\n\n===\n\n';
68
68
  const INDENT = 2;
69
+ function isStructuralLine(line) {
70
+ return line.startsWith('[indet]') || line.startsWith('[incertae sedis]');
71
+ }
72
+ function isNameLine(line) {
73
+ line = line.trim();
74
+ return !line.startsWith('> ') && !isStructuralLine(line);
75
+ }
69
76
  function makeParseError(message, line, column = 1) {
70
77
  return new SyntaxError(`[${line}:${column}] ${message}`);
71
78
  }
@@ -190,7 +197,7 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
190
197
  const parents = [];
191
198
  const previous = { id: '', indent: 0, group: { isLeaf: false, indent: 0 }, errors: [] };
192
199
  for (const line of content) {
193
- const hasOriginalId = line.type !== diff_resource_1.ResourceDiffType.Added && !/^\s*(\[indet\]|> )/.test((_a = line.original) !== null && _a !== void 0 ? _a : line.text);
200
+ const hasOriginalId = line.type !== diff_resource_1.ResourceDiffType.Added && isNameLine((_a = line.original) !== null && _a !== void 0 ? _a : line.text);
194
201
  if (hasOriginalId) {
195
202
  id++;
196
203
  }
@@ -217,7 +224,7 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
217
224
  // Update parentage
218
225
  if (lineIndent > previous.indent) {
219
226
  // Do not count synonyms as parents (unless this is correcting a typo in the synonym)
220
- if (data[previous.id] && data[previous.id].taxonomicStatus === 'accepted' || name.startsWith('> ')) {
227
+ if (data[previous.id] && (data[previous.id].taxonomicStatus === 'accepted' || name.startsWith('> '))) {
221
228
  parents.push(previous.id);
222
229
  }
223
230
  else {
@@ -235,9 +242,13 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
235
242
  parents.splice(lineIndent / INDENT);
236
243
  }
237
244
  previous.indent = lineIndent;
238
- // Do not process "indet" lines further, as they only serve to indicate
239
- // that subtaxa are explicitely omitted
240
- if (name.startsWith('[indet]')) {
245
+ if (name.startsWith('[incertae sedis]')) {
246
+ previous.id = '';
247
+ previous.group.indent = previous.indent;
248
+ }
249
+ // Do not process "indet" or "incertae sedis" lines further, as they only
250
+ // serve as structural indicators.
251
+ if (isStructuralLine(name)) {
241
252
  errors.push(...previous.errors);
242
253
  previous.errors.length = 0;
243
254
  previous.group.isLeaf = lineIndent / INDENT >= leafTaxonIndex;
@@ -281,10 +292,6 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
281
292
  }
282
293
  // Amend "parent" with corrections, exit
283
294
  if (item.taxonomicStatus === 'incorrect') {
284
- if (parent.taxonomicStatus !== 'accepted') {
285
- // Remove corrected synonym from parentage
286
- parents[parents.length - 1] = null;
287
- }
288
295
  if (parent.incorrect) {
289
296
  errors.push(makeParseError('Cannot apply a correction to a previous correction', lineNumber));
290
297
  continue;
@@ -293,6 +300,14 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
293
300
  errors.push(makeParseError('Cannot apply a correction to nothing', lineNumber));
294
301
  continue;
295
302
  }
303
+ else if (parents.indexOf(parentId) !== parents.length - 1) {
304
+ errors.push(makeParseError('Cannot apply a correction after skipping a rank', lineNumber));
305
+ continue;
306
+ }
307
+ if (parent.taxonomicStatus !== 'accepted') {
308
+ // Remove corrected synonym from parentage
309
+ parents[parents.length - 1] = null;
310
+ }
296
311
  parent.incorrect = Object.assign({}, parent);
297
312
  for (const key in item) {
298
313
  if (key !== 'taxonomicStatus' && key !== 'verbatimIdentification') {
@@ -305,8 +320,17 @@ function parseResourceContent(content, resource, oldIds, offsetLine) {
305
320
  errors.push(...itemErrors);
306
321
  continue;
307
322
  }
308
- // Add more classification info
323
+ // Validate synonyms
309
324
  const isSynonym = item.taxonomicStatus !== 'accepted';
325
+ if (isSynonym) {
326
+ if (parentId === null) {
327
+ errors.push(makeParseError('Cannot define a synonym of nothing', lineNumber));
328
+ }
329
+ else if (parents.indexOf(parentId) !== parents.length - 1) {
330
+ errors.push(makeParseError('Cannot define a synonym after skipping a rank', lineNumber));
331
+ }
332
+ }
333
+ // Add more classification info
310
334
  if (isSynonym) {
311
335
  item.higherClassification = parent.higherClassification;
312
336
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@larsgw/formica",
3
- "version": "0.10.5",
3
+ "version": "0.11.0",
4
4
  "description": "SDK and tools for data from the Library of Identification Resources",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "ietf-language-tag-regex": "^0.0.5",
41
41
  "js-yaml": "^5.2.1",
42
- "jsonld": "^9.0.0",
42
+ "jsonld": "larsgw/jsonld.js#larsgw-patch-1",
43
43
  "n3": "^2.1.1",
44
44
  "shex": "^1.0.0-alpha.30",
45
45
  "spdx-license-list": "^6.6.0"