@natlibfi/marc-record-validators-melinda 12.0.7 → 12.0.8
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/dist/addMissingField041.js +6 -3
- package/dist/addMissingField041.js.map +2 -2
- package/dist/addMissingField336.js +7 -4
- package/dist/addMissingField336.js.map +2 -2
- package/dist/addMissingField337.js +6 -3
- package/dist/addMissingField337.js.map +2 -2
- package/dist/addMissingField338.js +8 -5
- package/dist/addMissingField338.js.map +2 -2
- package/dist/cyrillux-usemarcon-replacement.js +5 -2
- package/dist/cyrillux-usemarcon-replacement.js.map +2 -2
- package/dist/cyrillux.js +10 -7
- package/dist/cyrillux.js.map +2 -2
- package/dist/disambiguateSeriesStatements.js +2 -1
- package/dist/disambiguateSeriesStatements.js.map +2 -2
- package/dist/drop-terms.js +5 -4
- package/dist/drop-terms.js.map +2 -2
- package/dist/fix-33X.js +7 -4
- package/dist/fix-33X.js.map +2 -2
- package/dist/fix-country-codes.js +5 -0
- package/dist/fix-country-codes.js.map +2 -2
- package/dist/fix-language-codes.js +5 -1
- package/dist/fix-language-codes.js.map +2 -2
- package/dist/fix-sami-041.js +11 -10
- package/dist/fix-sami-041.js.map +2 -2
- package/dist/indicator-fixes.js +5 -1
- package/dist/indicator-fixes.js.map +2 -2
- package/dist/merge-fields/counterpartField.js +6 -6
- package/dist/merge-fields/counterpartField.js.map +2 -2
- package/dist/merge-fields/mergableIndicator.js +0 -3
- package/dist/merge-fields/mergableIndicator.js.map +2 -2
- package/dist/merge-fields/worldKnowledge.js.map +2 -2
- package/dist/mergeRelatorTermFields.js +9 -6
- package/dist/mergeRelatorTermFields.js.map +2 -2
- package/dist/normalize-dashes.js +7 -4
- package/dist/normalize-dashes.js.map +2 -2
- package/dist/normalize-identifiers.js.map +2 -2
- package/dist/normalize-utf8-diacritics.js.map +2 -2
- package/dist/normalizeFieldForComparison.js.map +1 -1
- package/dist/normalizeSubfieldValueForComparison.js.map +1 -1
- package/dist/punctuation2.js +5 -2
- package/dist/punctuation2.js.map +2 -2
- package/dist/reindexSubfield6OccurenceNumbers.js +11 -10
- package/dist/reindexSubfield6OccurenceNumbers.js.map +2 -2
- package/dist/removeDuplicateDataFields.js +3 -2
- package/dist/removeDuplicateDataFields.js.map +2 -2
- package/dist/removeInferiorDataFields.js.map +2 -2
- package/dist/resolveOrphanedSubfield6s.js +3 -2
- package/dist/resolveOrphanedSubfield6s.js.map +2 -2
- package/dist/sortSubfields.js +1 -1
- package/dist/sortSubfields.js.map +2 -2
- package/dist/stripPunctuation.js +4 -3
- package/dist/stripPunctuation.js.map +2 -2
- package/dist/subfield6Utils.js +4 -1
- package/dist/subfield6Utils.js.map +2 -2
- package/dist/subfield8Utils.js.map +2 -2
- package/dist/translate-terms.js +4 -3
- package/dist/translate-terms.js.map +2 -2
- package/dist/typeOfDate-008.js +3 -1
- package/dist/typeOfDate-008.js.map +2 -2
- package/dist/update-field-540.js.map +2 -2
- package/dist/urn.js +13 -12
- package/dist/urn.js.map +2 -2
- package/package.json +7 -7
- package/src/addMissingField041.js +8 -4
- package/src/addMissingField336.js +10 -5
- package/src/addMissingField337.js +9 -5
- package/src/addMissingField338.js +11 -6
- package/src/cyrillux-usemarcon-replacement.js +9 -5
- package/src/cyrillux.js +18 -12
- package/src/disambiguateSeriesStatements.js +4 -1
- package/src/drop-terms.js +8 -6
- package/src/fix-33X.js +10 -6
- package/src/fix-country-codes.js +7 -3
- package/src/fix-language-codes.js +8 -4
- package/src/fix-sami-041.js +13 -11
- package/src/indicator-fixes.js +10 -7
- package/src/merge-fields/counterpartField.js +10 -10
- package/src/merge-fields/mergableIndicator.js +3 -3
- package/src/merge-fields/worldKnowledge.js +11 -6
- package/src/mergeRelatorTermFields.js +12 -11
- package/src/normalize-dashes.js +11 -5
- package/src/normalize-identifiers.js +12 -19
- package/src/normalize-utf8-diacritics.js +6 -3
- package/src/normalizeFieldForComparison.js +2 -2
- package/src/normalizeSubfieldValueForComparison.js +2 -2
- package/src/punctuation2.js +34 -30
- package/src/reindexSubfield6OccurenceNumbers.js +13 -11
- package/src/removeDuplicateDataFields.js +29 -27
- package/src/removeInferiorDataFields.js +28 -24
- package/src/resolveOrphanedSubfield6s.js +6 -4
- package/src/sortSubfields.js +5 -5
- package/src/stripPunctuation.js +5 -3
- package/src/subfield6Utils.js +33 -35
- package/src/subfield8Utils.js +10 -7
- package/src/translate-terms.js +13 -9
- package/src/typeOfDate-008.js +4 -1
- package/src/update-field-540.js +7 -5
- package/src/urn.js +17 -13
- package/test-fixtures/drop-terms/02/metadata.json +1 -1
- package/test-fixtures/drop-terms/03/metadata.json +1 -1
- package/test-fixtures/drop-terms/04/metadata.json +1 -1
package/src/subfield6Utils.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');
|
|
3
|
-
|
|
1
|
+
import createDebugLogger from 'debug';
|
|
4
2
|
import {add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils.js';
|
|
5
3
|
import {fieldHasSubfield, fieldToString, /* fieldsToString, */ nvdebug, subfieldToString} from './utils.js';
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils');
|
|
8
6
|
//const debugData = debug.extend('data');
|
|
9
|
-
|
|
7
|
+
const debugDev = debug.extend('dev');
|
|
10
8
|
|
|
11
9
|
// NB! Subfield 6 is non-repeatable and it should always comes first!
|
|
12
10
|
// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.
|
|
@@ -41,7 +39,7 @@ export function subfield6GetOccurrenceNumberAsInteger(subfield) {
|
|
|
41
39
|
return 0;
|
|
42
40
|
}
|
|
43
41
|
const result = parseInt(index, 10);
|
|
44
|
-
//nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`,
|
|
42
|
+
//nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debugDev, debugDev);
|
|
45
43
|
return result;
|
|
46
44
|
}
|
|
47
45
|
|
|
@@ -52,7 +50,7 @@ export function subfield6ResetOccurrenceNumber(subfield, occurrenceNumber) {
|
|
|
52
50
|
const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;
|
|
53
51
|
|
|
54
52
|
const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield);
|
|
55
|
-
//nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}
|
|
53
|
+
//nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);
|
|
56
54
|
subfield.value = newValue;
|
|
57
55
|
}
|
|
58
56
|
|
|
@@ -71,7 +69,7 @@ export function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurre
|
|
|
71
69
|
}
|
|
72
70
|
// We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...
|
|
73
71
|
const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1');
|
|
74
|
-
//nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'
|
|
72
|
+
//nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`, debugDev);
|
|
75
73
|
return key === tagAndOccurrenceNumber;
|
|
76
74
|
}
|
|
77
75
|
|
|
@@ -94,7 +92,7 @@ export function fieldGetUnambiguousOccurrenceNumber(field) {
|
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
export function fieldHasOccurrenceNumber(field, occurrenceNumber) {
|
|
97
|
-
//nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}
|
|
95
|
+
//nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`, debugDev);
|
|
98
96
|
return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);
|
|
99
97
|
}
|
|
100
98
|
|
|
@@ -119,13 +117,13 @@ export function intToOccurrenceNumberString(i) {
|
|
|
119
117
|
|
|
120
118
|
export function fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {
|
|
121
119
|
// used by reducer!
|
|
122
|
-
//nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}
|
|
120
|
+
//nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`, debugDev);
|
|
123
121
|
const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];
|
|
124
122
|
if (sf6s.length === 0) {
|
|
125
123
|
return 0;
|
|
126
124
|
}
|
|
127
125
|
// There should always be one, but here we check every subfield.
|
|
128
|
-
//nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`,
|
|
126
|
+
//nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debugDev);
|
|
129
127
|
const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));
|
|
130
128
|
return Math.max(...vals);
|
|
131
129
|
}
|
|
@@ -155,20 +153,20 @@ export function fieldHasValidSubfield6(field) {
|
|
|
155
153
|
|
|
156
154
|
export function isSubfield6Pair(field, otherField) {
|
|
157
155
|
// No need to log this:
|
|
158
|
-
//nvdebug(`LOOK for $6-pair:\n ${fieldToString(field)}\n ${fieldToString(otherField)}
|
|
156
|
+
//nvdebug(`LOOK for $6-pair:\n ${fieldToString(field)}\n ${fieldToString(otherField)}`, debugDev);
|
|
159
157
|
if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {
|
|
160
158
|
return false;
|
|
161
159
|
}
|
|
162
160
|
|
|
163
161
|
if (!tagsArePairable6(field.tag, otherField.tag)) {
|
|
164
|
-
//nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE
|
|
162
|
+
//nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`, debugDev);
|
|
165
163
|
return false;
|
|
166
164
|
}
|
|
167
165
|
|
|
168
166
|
|
|
169
167
|
const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);
|
|
170
168
|
if (fieldIndex === undefined || fieldIndex === '00') {
|
|
171
|
-
//nvdebug(` FAILED. REASON: NO INDEX FOUND
|
|
169
|
+
//nvdebug(` FAILED. REASON: NO INDEX FOUND`, debugDev);
|
|
172
170
|
return false;
|
|
173
171
|
}
|
|
174
172
|
|
|
@@ -176,12 +174,12 @@ export function isSubfield6Pair(field, otherField) {
|
|
|
176
174
|
|
|
177
175
|
|
|
178
176
|
if (fieldIndex !== otherFieldIndex) {
|
|
179
|
-
//nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}
|
|
177
|
+
//nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`, debugDev);
|
|
180
178
|
return false;
|
|
181
179
|
}
|
|
182
180
|
|
|
183
181
|
if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {
|
|
184
|
-
//nvdebug(` FAILURE: TAG vs $6 TAG
|
|
182
|
+
//nvdebug(` FAILURE: TAG vs $6 TAG`, debugDev);
|
|
185
183
|
return false;
|
|
186
184
|
}
|
|
187
185
|
return true;
|
|
@@ -219,11 +217,11 @@ export function fieldGetOccurrenceNumberPairs(field, candFields) {
|
|
|
219
217
|
//nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);
|
|
220
218
|
const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));
|
|
221
219
|
if (pairs.length === 0) {
|
|
222
|
-
//nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'
|
|
220
|
+
//nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`, debugDev);
|
|
223
221
|
return pairs;
|
|
224
222
|
}
|
|
225
|
-
//nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'
|
|
226
|
-
pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'
|
|
223
|
+
//nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`, debugDev);
|
|
224
|
+
pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`, debugDev));
|
|
227
225
|
return pairs;
|
|
228
226
|
}
|
|
229
227
|
|
|
@@ -268,7 +266,7 @@ export function fieldGetSubfield6Pair(field, record) {
|
|
|
268
266
|
return undefined;
|
|
269
267
|
}
|
|
270
268
|
// NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)
|
|
271
|
-
nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}
|
|
269
|
+
nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`, debugDev);
|
|
272
270
|
return pairedFields[0];
|
|
273
271
|
}
|
|
274
272
|
*/
|
|
@@ -357,7 +355,7 @@ function guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {
|
|
|
357
355
|
export function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag = false) {
|
|
358
356
|
const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);
|
|
359
357
|
|
|
360
|
-
//nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}
|
|
358
|
+
//nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`, debugDev);
|
|
361
359
|
const strings = fields.map(field => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag));
|
|
362
360
|
strings.sort();
|
|
363
361
|
return strings.join('\t__SEPARATOR__\t');
|
|
@@ -369,32 +367,32 @@ export function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0,
|
|
|
369
367
|
export function removeField6IfNeeded(field, record, fieldsAsString) {
|
|
370
368
|
const pairField = fieldGetSubfield6Pair(field, record);
|
|
371
369
|
const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);
|
|
372
|
-
nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}
|
|
370
|
+
nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`, debugDev);
|
|
373
371
|
const tmp = pairField ? fieldToString(pairField) : 'HUTI';
|
|
374
|
-
nvdebug(`PAIR: ${tmp}
|
|
375
|
-
nvdebug(`BASE:\n ${fieldsAsString.join('\n ')}
|
|
372
|
+
nvdebug(`PAIR: ${tmp}`, debugDev);
|
|
373
|
+
nvdebug(`BASE:\n ${fieldsAsString.join('\n ')}`, debugDev);
|
|
376
374
|
if (!fieldsAsString.includes(asString)) {
|
|
377
375
|
return;
|
|
378
376
|
}
|
|
379
|
-
nvdebug(`Duplicate $6 removal: ${fieldToString(field)}
|
|
377
|
+
nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`, debugDev);
|
|
380
378
|
record.removeField(field);
|
|
381
379
|
|
|
382
380
|
if (pairField === undefined) {
|
|
383
381
|
return;
|
|
384
382
|
}
|
|
385
|
-
nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}
|
|
383
|
+
nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`, debugDev);
|
|
386
384
|
record.removeField(pairField);
|
|
387
385
|
}
|
|
388
386
|
*/
|
|
389
387
|
|
|
390
388
|
function getFirstField(record, fields) {
|
|
391
389
|
const fieldsAsStrings = fields.map(field => fieldToString(field));
|
|
392
|
-
//record.fields.forEach((field, i) => nvdebug(`${i}:\t${fieldToString(field)}
|
|
393
|
-
//nvdebug(`getFirstField: ${fieldsAsStrings.join('\t')}
|
|
390
|
+
//record.fields.forEach((field, i) => nvdebug(`${i}:\t${fieldToString(field)}`, debugDev));
|
|
391
|
+
//nvdebug(`getFirstField: ${fieldsAsStrings.join('\t')}`, debugDev);
|
|
394
392
|
const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));
|
|
395
393
|
if (i > -1) {
|
|
396
394
|
const field = record.fields[i];
|
|
397
|
-
//nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}
|
|
395
|
+
//nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`, debugDev);
|
|
398
396
|
return field;
|
|
399
397
|
}
|
|
400
398
|
return undefined;
|
|
@@ -445,7 +443,7 @@ export function isFirstLinkedSubfield6Field(field, record) {
|
|
|
445
443
|
}
|
|
446
444
|
const chain = getAllLinkedSubfield6Fields(field, record);
|
|
447
445
|
if (!isRelevantSubfield6Chain(chain)) {
|
|
448
|
-
//nvdebug(`Rejected 6: ${fieldsToString(chain)}
|
|
446
|
+
//nvdebug(`Rejected 6: ${fieldsToString(chain)}`, debugDev);
|
|
449
447
|
return false;
|
|
450
448
|
}
|
|
451
449
|
|
|
@@ -472,13 +470,13 @@ export function get6s(field, candidateFields) { // NB! Convert field to fields!!
|
|
|
472
470
|
if (sixes.length === 0) {
|
|
473
471
|
return [field];
|
|
474
472
|
}
|
|
475
|
-
//nvdebug(`SIXES: ${sixes.length}
|
|
473
|
+
//nvdebug(`SIXES: ${sixes.length}`, debugDev);
|
|
476
474
|
const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');
|
|
477
|
-
//nvdebug(occurrenceNumbers.join(' -- '));
|
|
475
|
+
//nvdebug(occurrenceNumbers.join(' -- '), debugDev);
|
|
478
476
|
|
|
479
477
|
const relevantFields = candidateFields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));
|
|
480
|
-
//nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}
|
|
481
|
-
//relevantFields.forEach(f => nvdebug(fieldToString(f)));
|
|
478
|
+
//nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`, debugDev);
|
|
479
|
+
//relevantFields.forEach(f => nvdebug(fieldToString(f), debugDev));
|
|
482
480
|
return relevantFields;
|
|
483
481
|
}
|
|
484
482
|
|
|
@@ -488,6 +486,6 @@ export function resetSubfield6Tag(subfield, tag) {
|
|
|
488
486
|
}
|
|
489
487
|
// NB! mainly for 1XX<->7XX transfers
|
|
490
488
|
const newValue = `${tag}-${subfield.value.substring(4)}`;
|
|
491
|
-
//nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`,
|
|
489
|
+
//nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDevDev);
|
|
492
490
|
subfield.value = newValue;
|
|
493
491
|
}
|
package/src/subfield8Utils.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// import createDebugLogger from 'debug';
|
|
2
|
+
// import {fieldToString, nvdebug} from './utils.js';
|
|
3
|
+
|
|
2
4
|
// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield8Utils');
|
|
5
|
+
//const debugData = debug.extend('data');
|
|
6
|
+
//const debugDev = debug.extend('dev');
|
|
3
7
|
|
|
4
|
-
// import {fieldToString, nvdebug} from './utils.js';
|
|
5
8
|
|
|
6
9
|
const sf8Regexp = /^([1-9][0-9]*)(?:\.[0-9]+)?(?:\\[acprux])?$/u;
|
|
7
10
|
|
|
@@ -10,9 +13,9 @@ export function isValidSubfield8(subfield) {
|
|
|
10
13
|
return false;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}'
|
|
16
|
+
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}'`, debugDev);
|
|
14
17
|
const match = subfield.value.match(sf8Regexp);
|
|
15
|
-
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}' vs ${match.length}}
|
|
18
|
+
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}' vs ${match.length}}`, debugDev);
|
|
16
19
|
return match && match.length > 0;
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -56,7 +59,7 @@ export function fieldsGetAllSubfield8LinkingNumbers(fields) {
|
|
|
56
59
|
field.subfields.forEach(sf => {
|
|
57
60
|
const linkingNumber = getSubfield8LinkingNumber(sf);
|
|
58
61
|
if (linkingNumber > 0 && !subfield8LinkingNumbers.includes(linkingNumber)) {
|
|
59
|
-
//nvdebug(` LINK8: Add subfield \$8 ${linkingNumber} to seen values list
|
|
62
|
+
//nvdebug(` LINK8: Add subfield \$8 ${linkingNumber} to seen values list`, debugDev);
|
|
60
63
|
subfield8LinkingNumbers.push(linkingNumber);
|
|
61
64
|
}
|
|
62
65
|
});
|
|
@@ -76,10 +79,10 @@ export function add8s(fields, record) {
|
|
|
76
79
|
return fields;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
//nvdebug(`Linking number(s): ${linkingNumbers.join(', ')}
|
|
82
|
+
//nvdebug(`Linking number(s): ${linkingNumbers.join(', ')}`, debugDev);
|
|
80
83
|
linkingNumbers.forEach(number => collectLinkingNumberFields(number));
|
|
81
84
|
|
|
82
|
-
//fields.forEach(f => nvdebug(`AFTER ADDING 8s: '${fieldToString(f)}'
|
|
85
|
+
//fields.forEach(f => nvdebug(`AFTER ADDING 8s: '${fieldToString(f)}'`, debugDev));
|
|
83
86
|
|
|
84
87
|
return fields;
|
|
85
88
|
|
|
@@ -88,7 +91,7 @@ export function add8s(fields, record) {
|
|
|
88
91
|
fields = fields.filter(f => !fieldHasLinkingNumber(f, linkingNumber));
|
|
89
92
|
// Add them and their "sisters" back:
|
|
90
93
|
const addableFields = record.fields.filter(f => fieldHasLinkingNumber(f, linkingNumber));
|
|
91
|
-
//addableFields.forEach(f => nvdebug(`(RE-?)ADD ${fieldToString(f)}
|
|
94
|
+
//addableFields.forEach(f => nvdebug(`(RE-?)ADD ${fieldToString(f)}`, debugDev));
|
|
92
95
|
fields = fields.concat(addableFields);
|
|
93
96
|
|
|
94
97
|
}
|
package/src/translate-terms.js
CHANGED
|
@@ -4,6 +4,9 @@ import {fieldHasSubfield, fieldToString, nvdebug} from './utils.js';
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:translate-terms');
|
|
7
|
+
//const debugData = debug.extend('data');
|
|
8
|
+
const debugDev = debug.extend('dev');
|
|
9
|
+
|
|
7
10
|
const defaultTags = ['648', '650', '651', '655'];
|
|
8
11
|
|
|
9
12
|
const swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};
|
|
@@ -12,6 +15,7 @@ const changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};
|
|
|
12
15
|
const termCache = {};
|
|
13
16
|
|
|
14
17
|
// Author(s): Nicholas Volk
|
|
18
|
+
// eslint-disable-next-line max-lines-per-function
|
|
15
19
|
export default function () {
|
|
16
20
|
|
|
17
21
|
|
|
@@ -23,7 +27,7 @@ export default function () {
|
|
|
23
27
|
async function fix(record) {
|
|
24
28
|
const newFields = await getFields(record, defaultTags, []);
|
|
25
29
|
|
|
26
|
-
newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`,
|
|
30
|
+
newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debugDev));
|
|
27
31
|
|
|
28
32
|
newFields.forEach(nf => record.insertField(nf));
|
|
29
33
|
|
|
@@ -65,7 +69,7 @@ export default function () {
|
|
|
65
69
|
const finnishOnly = getMisses(finnishFields, swedishFields);
|
|
66
70
|
const swedishOnly = getMisses(swedishFields, finnishFields);
|
|
67
71
|
|
|
68
|
-
//
|
|
72
|
+
//nvdebug(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`, debugDev);
|
|
69
73
|
return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));
|
|
70
74
|
|
|
71
75
|
function tagAndFieldAgree(field) {
|
|
@@ -93,12 +97,12 @@ export default function () {
|
|
|
93
97
|
if (!prefLabels) {
|
|
94
98
|
return undefined;
|
|
95
99
|
}
|
|
96
|
-
//
|
|
100
|
+
//nvdebug(`pairField() WP 1: ${fieldToString(field)}`, debugDev);
|
|
97
101
|
const lexAndLang = getLexiconAndLanguage(field);
|
|
98
|
-
//
|
|
102
|
+
//nvdebug(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`, debugDev);
|
|
99
103
|
const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));
|
|
100
104
|
const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);
|
|
101
|
-
//
|
|
105
|
+
//nvdebug(`pairField() WP 4: ${JSON.stringify(prefLabel)}`, debugDev);
|
|
102
106
|
const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');
|
|
103
107
|
const sf0 = clone(field.subfields.find(sf => sf.code === '0'));
|
|
104
108
|
const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe
|
|
@@ -118,7 +122,7 @@ export default function () {
|
|
|
118
122
|
const data = await getTermData(uri);
|
|
119
123
|
|
|
120
124
|
if (!data) { // Sanity check. Miss caused by illegal id etc.
|
|
121
|
-
nvdebug(`No labels found for ${uri}`,
|
|
125
|
+
nvdebug(`No labels found for ${uri}`, debugDev);
|
|
122
126
|
return undefined;
|
|
123
127
|
}
|
|
124
128
|
|
|
@@ -223,9 +227,9 @@ function mapTagToLex(tag) {
|
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
export async function getTermData(uri) {
|
|
226
|
-
nvdebug(`getTermData(${uri})
|
|
230
|
+
nvdebug(`getTermData(${uri})`, debugDev);
|
|
227
231
|
if (termCache[uri]) { // Don't think current implementation uses the cache any more.
|
|
228
|
-
//
|
|
232
|
+
//nvdebug(`CACHED ${uri}`, debugDev);
|
|
229
233
|
return termCache[uri];
|
|
230
234
|
}
|
|
231
235
|
const tmp = await getTermDataFromFinto(uri);
|
|
@@ -252,7 +256,7 @@ async function getTermDataFromFinto(uri) {
|
|
|
252
256
|
prefLabel: processLabel(hit?.prefLabel || undefined),
|
|
253
257
|
altLabel: processLabel(hit?.altLabel || undefined)
|
|
254
258
|
};
|
|
255
|
-
//
|
|
259
|
+
//nvdebug(`NEW JSON: ${JSON.stringify(hit)}`, debugDev);
|
|
256
260
|
|
|
257
261
|
return subset;
|
|
258
262
|
|
package/src/typeOfDate-008.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
|
+
import { nvdebug } from './utils.js';
|
|
2
3
|
|
|
3
4
|
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/typeOfDate-008');
|
|
5
|
+
//const debugData = debug.extend('data');
|
|
6
|
+
const debugDev = debug.extend('dev');
|
|
4
7
|
|
|
5
8
|
export default function () {
|
|
6
9
|
return {
|
|
@@ -15,7 +18,7 @@ export default function () {
|
|
|
15
18
|
const c1114 = f008.value.substring(11, 15);
|
|
16
19
|
// if 008 06 = s, and 11-14 = #### (not year/digits)
|
|
17
20
|
if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {
|
|
18
|
-
|
|
21
|
+
nvdebug('is t and not valid 1114', debugDev);
|
|
19
22
|
return {valid: false, message: 'Invalid 008 06'};
|
|
20
23
|
}
|
|
21
24
|
|
package/src/update-field-540.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
//import createDebugLogger from 'debug';
|
|
2
|
-
import {fieldToString} from './utils.js';
|
|
2
|
+
import {fieldToString /*, nvdebug*/} from './utils.js';
|
|
3
3
|
|
|
4
4
|
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540');
|
|
5
|
+
//const debugData = debug.extend('data');
|
|
6
|
+
//const debugDev = debug.extend('dev');
|
|
5
7
|
|
|
6
8
|
// Author(s): Nicholas Volk
|
|
7
9
|
export default function () {
|
|
@@ -54,7 +56,7 @@ function validLicenseInSubfieldC(subfieldC, license) {
|
|
|
54
56
|
if (subfieldC.code !== 'c') {
|
|
55
57
|
return false;
|
|
56
58
|
}
|
|
57
|
-
//nvdebug(`Compare ${subfieldC.value} vs ${license.license}
|
|
59
|
+
//nvdebug(`Compare ${subfieldC.value} vs ${license.license}`, debugDev);
|
|
58
60
|
return license.license === subfieldC.value;
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -62,7 +64,7 @@ function validUrlInSubfieldU(subfieldU, license) {
|
|
|
62
64
|
if (subfieldU.code !== 'u') {
|
|
63
65
|
return false;
|
|
64
66
|
}
|
|
65
|
-
//nvdebug(`Compare ${subfieldU.value} vs ${license.url}
|
|
67
|
+
//nvdebug(`Compare ${subfieldU.value} vs ${license.url}`, debugDev);
|
|
66
68
|
return license.url === subfieldU.value;
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -78,12 +80,12 @@ function fieldHasOldCcLicense(field, fix) {
|
|
|
78
80
|
if (field.tag !== '540') {
|
|
79
81
|
return false;
|
|
80
82
|
}
|
|
81
|
-
//nvdebug(`NORM 540: ${fieldToString(field)}
|
|
83
|
+
//nvdebug(`NORM 540: ${fieldToString(field)}`, debugDev);
|
|
82
84
|
const validLicense = licences.find(license => field.subfields.some(sf => validLicenseInSubfieldC(sf, license)) && field.subfields.some(sf => validUrlInSubfieldU(sf, license)));
|
|
83
85
|
if (!validLicense) {
|
|
84
86
|
return false;
|
|
85
87
|
}
|
|
86
|
-
//nvdebug(` Found valid license
|
|
88
|
+
//nvdebug(` Found valid license`, debugDev);
|
|
87
89
|
if (fix) {
|
|
88
90
|
const subfieldsC = field.subfields.filter(sf => validLicenseInSubfieldC(sf, validLicense));
|
|
89
91
|
subfieldsC.forEach(c => fixC(field, c));
|
package/src/urn.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
//import fetch from 'node-fetch';
|
|
2
|
-
import {isElectronicMaterial} from './utils.js';
|
|
2
|
+
import {isElectronicMaterial, nvdebug} from './utils.js';
|
|
3
3
|
import createDebugLogger from 'debug';
|
|
4
4
|
|
|
5
5
|
const URN_GENERATOR_URL = 'https://generator.urn.fi/cgi-bin/urn_generator.cgi?type=nbn';
|
|
6
6
|
|
|
7
|
+
// eslint-disable-next-line max-lines-per-function
|
|
7
8
|
export default function (isLegalDeposit = false, useMelindaTemp = true) {
|
|
8
9
|
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:urn');
|
|
9
10
|
const debugData = debug.extend('data');
|
|
11
|
+
const debugDev = debug.extend('dev');
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
//nvdebug(`IS LEGAL DEPOSIT? ${isLegalDeposit ? 'YES' : 'NO'}`, debugDev); // eslint-disable-line no-console
|
|
12
15
|
|
|
13
16
|
// We should check that the f856 with URN has second indicator '0' (Resource), ' ' (No information provided) or '8' (No display constant generated)
|
|
14
17
|
// - if second indicator is '1' (Version of resource) or '2' (Related resource) the URN in f856 is not correct for the resource described in the record
|
|
@@ -35,12 +38,13 @@ export default function (isLegalDeposit = false, useMelindaTemp = true) {
|
|
|
35
38
|
fix
|
|
36
39
|
};
|
|
37
40
|
|
|
41
|
+
// eslint-disable-next-line max-lines-per-function
|
|
38
42
|
async function fix(record) {
|
|
39
43
|
const f856sUrn = record.fields.filter(hasLegalDepositURN);
|
|
40
|
-
|
|
44
|
+
nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugDev);
|
|
41
45
|
|
|
42
46
|
const ldSubfields = isLegalDeposit ? createLDSubfields() : [];
|
|
43
|
-
|
|
47
|
+
nvdebug(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`, debugDev);
|
|
44
48
|
|
|
45
49
|
// We add the URN even if we're not getting the legalDeposit - where does this URN resolve?
|
|
46
50
|
// We probably should not do these additions
|
|
@@ -111,7 +115,7 @@ export default function (isLegalDeposit = false, useMelindaTemp = true) {
|
|
|
111
115
|
return acc;
|
|
112
116
|
}, undefined);
|
|
113
117
|
|
|
114
|
-
|
|
118
|
+
nvdebug(`isbns: ${isbn}`, debugDev);
|
|
115
119
|
|
|
116
120
|
const {generated, value} = await createURN(isbn);
|
|
117
121
|
return {code: 'u', value, generated};
|
|
@@ -161,12 +165,12 @@ export default function (isLegalDeposit = false, useMelindaTemp = true) {
|
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
function validateLD(f856sUrn) {
|
|
164
|
-
|
|
168
|
+
nvdebug(`Validating the existence of legal deposit subfields`, debugDev);
|
|
165
169
|
const ldSubfields = createLDSubfields();
|
|
166
170
|
const f856sUrnWithLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, ldSubfields));
|
|
167
171
|
if (f856sUrnWithLdSubfields.length > 0) {
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
nvdebug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`, debugDev);
|
|
173
|
+
nvdebug(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`, debugData);
|
|
170
174
|
return true;
|
|
171
175
|
}
|
|
172
176
|
return false;
|
|
@@ -175,22 +179,22 @@ export default function (isLegalDeposit = false, useMelindaTemp = true) {
|
|
|
175
179
|
function validate(record) {
|
|
176
180
|
// if not electronic skip this validator
|
|
177
181
|
if (!isElectronicMaterial(record)) {
|
|
178
|
-
|
|
182
|
+
nvdebug(`Record is not electronic - no need to validate legal deposit URNs`, debugDev);
|
|
179
183
|
return {valid: true};
|
|
180
184
|
}
|
|
181
185
|
|
|
182
186
|
const f856sUrn = record.fields.filter(hasLegalDepositURN);
|
|
183
187
|
|
|
184
188
|
if (f856sUrn.length > 0) {
|
|
185
|
-
|
|
186
|
-
|
|
189
|
+
nvdebug(`Record has ${f856sUrn.length} URN fields`, debugDev);
|
|
190
|
+
nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugData);
|
|
187
191
|
|
|
188
192
|
if (!isLegalDeposit || validateLD(f856sUrn)) {
|
|
189
|
-
|
|
193
|
+
nvdebug(`Record is valid`, debugDev);
|
|
190
194
|
return {valid: true};
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
|
-
|
|
197
|
+
nvdebug(`No (valid) URN fields - Record is not valid`, debugDev);
|
|
194
198
|
return {valid: false};
|
|
195
199
|
}
|
|
196
200
|
}
|