@natlibfi/marc-record-validators-melinda 13.0.4 → 13.0.5
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/cyrillux-usemarcon-replacement.test.js +2 -2
- package/dist/cyrillux-usemarcon-replacement.test.js.map +2 -2
- package/dist/merge-fields/mergeConstraints.js +1 -1
- package/dist/merge-fields/mergeConstraints.js.map +2 -2
- package/dist/merge-fields/mergeField.js +2 -2
- package/dist/merge-fields/mergeField.js.map +2 -2
- package/dist/merge-fields/mergeOrAddSubfield.js +19 -5
- package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
- package/dist/punctuation2.js +16 -8
- package/dist/punctuation2.js.map +2 -2
- package/dist/punctuation2.test.js +2 -2
- package/dist/punctuation2.test.js.map +2 -2
- package/dist/sortSubfields.js +2 -2
- package/dist/sortSubfields.js.map +2 -2
- package/package.json +8 -8
- package/src/cyrillux-usemarcon-replacement.test.js +2 -2
- package/src/merge-fields/mergeConstraints.js +1 -1
- package/src/merge-fields/mergeField.js +2 -2
- package/src/merge-fields/mergeOrAddSubfield.js +28 -5
- package/src/punctuation2.js +20 -12
- package/src/punctuation2.test.js +2 -2
- package/src/sortSubfields.js +1 -1
- package/test-fixtures/cyrillux-usemarcon-replacement/f10/metadata.json +1 -1
- package/test-fixtures/merge-fields/f04/expectedResult.json +1 -2
- package/test-fixtures/merge-fields/f04/record.json +1 -2
- package/test-fixtures/merge-fields/f700_01/expectedResult.json +18 -0
- package/test-fixtures/merge-fields/f700_01/metadata.json +5 -0
- package/test-fixtures/merge-fields/f700_01/record.json +24 -0
- package/test-fixtures/merge-fields/f830_01/expectedResult.json +20 -0
- package/test-fixtures/merge-fields/f830_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f830_01/record.json +20 -0
package/src/punctuation2.js
CHANGED
|
@@ -60,7 +60,8 @@ function isIrrelevantSubfield(subfield, tag) {
|
|
|
60
60
|
if (subfield.code === dataProvenanceSubfieldCode) {
|
|
61
61
|
return true;
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
// control subfields, data provenance subfields etc do not affect the punctuation of the previous field
|
|
64
|
+
return !isContentSubfieldCode(subfield.code);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
|
|
@@ -129,7 +130,7 @@ const cleanPuncBeforeLanguage = {'code': 'atvxyz', 'followedBy': 'l', 'context':
|
|
|
129
130
|
const addX00aComma = {'add': ',', 'code': 'abcqejt', 'followedBy': 'cdegnr', 'context': doesNotEndInPunc, 'contextRHS': allowsPuncRHS};
|
|
130
131
|
const addX00dComma = {'name': 'X00$d ending in "-" does not get comma', 'add': ',', 'code': 'd', 'followedBy': 'cdeg', 'context': /[^-,.!]$/u, 'contextRHS': allowsPuncRHS};
|
|
131
132
|
const addX00aComma2 = {'add': ',', 'code': 'abcdej', 'followedBy': 'cdeg', 'context': /(?:[A-Z]|Å|Ä|Ö)\.$/u, 'contextRHS': allowsPuncRHS};
|
|
132
|
-
const addX00Dot = {'add': '.', 'code': 'abcdetv', 'followedBy': 'fklptu', 'context': needsPuncAfterAlphanumeric};
|
|
133
|
+
const addX00Dot = {'name': 'addX00Dot', 'add': '.', 'code': 'abcdetv', 'followedBy': 'fklptu', 'context': needsPuncAfterAlphanumeric};
|
|
133
134
|
const addEntryFieldFinalDot = {'name': 'X00 final dot', 'add': '.', 'code': 'abcdefghijklmnopqrstuvwxyz', 'followedBy': '#', 'context': /[^.)!?-]$/u};
|
|
134
135
|
|
|
135
136
|
|
|
@@ -144,7 +145,7 @@ const addX11Spacecolon = {name: '611 space colon(y :-)', add: ' :', code: 'nd',
|
|
|
144
145
|
const addDotBeforeLanguageSubfieldL = {'name': 'Add dot before $l', 'add': '.', 'code': 'abepst', 'followedBy': 'l', 'context': doesNotEndInPunc};
|
|
145
146
|
|
|
146
147
|
// 490:
|
|
147
|
-
const addSemicolonBeforeVolumeDesignation = {'name': 'Add " ;" before $v', 'add': ' ;', '
|
|
148
|
+
const addSemicolonBeforeVolumeDesignation = {'name': 'Add " ;" before $v', 'add': ' ;', 'followedBy': 'v', 'context': /[^;]$/u};
|
|
148
149
|
|
|
149
150
|
const NONE = 0;
|
|
150
151
|
const ADD = 2;
|
|
@@ -245,7 +246,9 @@ const legalX10punc = [cleanLegalX10Comma, cleanLegalX10Dot, cleanX00eDot, ...leg
|
|
|
245
246
|
|
|
246
247
|
const cleanLegalSeriesTitle = [ // 490 and 830
|
|
247
248
|
{'code': 'a', 'followedBy': 'a', 'remove': / =$/u},
|
|
248
|
-
{'code': '
|
|
249
|
+
{'code': 'a', 'followedBy': 'n', 'remove': /\.$/u}, // f830-only
|
|
250
|
+
{'code': 'n', 'followedBy': 'p', 'remove': /,$/u}, // f830-only
|
|
251
|
+
{'code': 'anpxyz', 'followedBy': 'xyz', 'remove': /,$/u, 'context': /.,$/u},
|
|
249
252
|
{'code': 'axyz', 'followedBy': 'v', 'remove': / *;$/u}
|
|
250
253
|
];
|
|
251
254
|
|
|
@@ -299,7 +302,7 @@ const cleanValidPunctuationRules = {
|
|
|
299
302
|
'611': legalX11Punc,
|
|
300
303
|
'630': legalEntryField,
|
|
301
304
|
// Experimental, MET366-ish (end punc in internationally valid, but we don't use it here in Finland):
|
|
302
|
-
'648': [{'code': 'a', '
|
|
305
|
+
'648': [{'code': 'a', 'context': /^[0-9]+\.$/u, 'ind2': ['4'], 'remove': /\.$/u}],
|
|
303
306
|
'700': legalX00punc,
|
|
304
307
|
'710': legalX10punc,
|
|
305
308
|
'711': legalX11Punc,
|
|
@@ -313,13 +316,18 @@ const cleanValidPunctuationRules = {
|
|
|
313
316
|
|
|
314
317
|
|
|
315
318
|
// Overgeneralizes a bit: eg. addColonToRelationshipInformation only applies to 700/710 but as others don't have $i, it's fine.
|
|
319
|
+
// Also addSemicolonBeforeVolumeDesignation applies only to 8XX:
|
|
316
320
|
const addToAllEntryFields = [addDotBeforeLanguageSubfieldL, addSemicolonBeforeVolumeDesignation, addColonToRelationshipInformation, addEntryFieldFinalDot];
|
|
317
321
|
|
|
318
322
|
|
|
319
323
|
const addX00 = [addXX0iColon, addX00aComma, addX00aComma2, addX00Dot, addX00dComma, ...addToAllEntryFields];
|
|
320
324
|
const addX10 = [addXX0iColon, addX10bDot, addX10Comma, addX10Dot, ...addToAllEntryFields];
|
|
321
325
|
const addX11 = [...addToAllEntryFields, addX11Spacecolon];
|
|
322
|
-
const addX30 = [
|
|
326
|
+
const addX30 = [
|
|
327
|
+
...addToAllEntryFields,
|
|
328
|
+
{'name': 'X30$a dot', 'code': 'a', 'followedBy': 'knp', 'add': '.', 'context': needsPuncAfterAlphanumeric},
|
|
329
|
+
{'name': 'X30 final dot', 'code': 'adfghklmnoprstv', 'followedBy': '#', 'add': '.', 'context': needsPuncAfterAlphanumeric}
|
|
330
|
+
];
|
|
323
331
|
|
|
324
332
|
const add24X = [
|
|
325
333
|
{'code': 'i', 'followedBy': 'a', 'add': ':', 'context': needsPuncAfterAlphanumeric},
|
|
@@ -339,7 +347,7 @@ const add245 = [
|
|
|
339
347
|
|
|
340
348
|
const addSeriesTitle = [ // 490 and 830
|
|
341
349
|
{'code': 'a', 'followedBy': 'a', 'add': ' =', 'context': defaultNeedsPuncAfter2},
|
|
342
|
-
{'code': '
|
|
350
|
+
{'code': 'anpxyz', 'followedBy': 'pxy', 'add': ',', 'context': defaultNeedsPuncAfter2},
|
|
343
351
|
addSemicolonBeforeVolumeDesignation // eg. 490$axyz-$v
|
|
344
352
|
];
|
|
345
353
|
|
|
@@ -521,7 +529,7 @@ function applyPunctuationRules(field, subfield1, subfield2, ruleArray = null, op
|
|
|
521
529
|
|
|
522
530
|
//nvdebug(`OP=${operation} ${tag2}: '${subfield1.code}: ${subfield1.value}' ??? '${subfield2 ? subfield2.code : '#'}'`, debugDev);
|
|
523
531
|
const candRules = ruleArray[tag2];
|
|
524
|
-
candRules.every(rule => { // uses "every", not "forEach", so that only one rule is
|
|
532
|
+
candRules.every(rule => { // uses "every", not "forEach", so that only one rule is applied to the given subfields
|
|
525
533
|
//debugRule(rule);
|
|
526
534
|
if (!checkRule(rule, field, subfield1, subfield2)) {
|
|
527
535
|
return true;
|
|
@@ -578,21 +586,21 @@ export function fieldStripPunctuation(field) {
|
|
|
578
586
|
return field;
|
|
579
587
|
}
|
|
580
588
|
|
|
581
|
-
export function fieldFixPunctuation(field) {
|
|
589
|
+
export function fieldFixPunctuation(field, externalEndPunctuation = false) {
|
|
582
590
|
if (!field.subfields) {
|
|
583
591
|
return field;
|
|
584
592
|
}
|
|
585
593
|
//nvdebug(`################### fieldFixPunctuation() TEST ${fieldToString(field)}`, debugDev);
|
|
586
594
|
|
|
587
595
|
field.subfields.forEach((sf, i) => {
|
|
588
|
-
// NB! instead of next subfield, we
|
|
589
|
-
// (In plain English: We
|
|
596
|
+
// NB! instead of next subfield, we get next *non-control-subfield*!!!
|
|
597
|
+
// (In plain English: We skip $0 ... $9 at least, maybe $w as well...)
|
|
590
598
|
// We'll need some magic for field 257 here, do we? (Also Finnish lexicons vs global lexicons in 65X fields)
|
|
591
599
|
subfieldFixPunctuation(field, sf, getNextRelevantSubfield(field, i));
|
|
592
600
|
});
|
|
593
601
|
|
|
594
602
|
// Use shared code for final punctuation (sadly this does not fix intermediate punc):
|
|
595
|
-
if (field.useExternalEndPunctuation) {
|
|
603
|
+
if (externalEndPunctuation || field.useExternalEndPunctuation) {
|
|
596
604
|
// addFinalPunctuation(field); // local version. use shared code instead.
|
|
597
605
|
validateSingleField(field, false, true); // NB! Don't use field.tag as second argument! It's a string, not an int. 3rd arg must be true (=fix)
|
|
598
606
|
}
|
package/src/punctuation2.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
2
|
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
3
|
import validatorFactory from './punctuation2.js';
|
|
4
4
|
import {READERS} from '@natlibfi/fixura';
|
|
@@ -42,5 +42,5 @@ async function callback({getFixture, fix = false}) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
await validator.fix(record);
|
|
45
|
-
assert.deepEqual(record, expectedResult);
|
|
45
|
+
assert.deepEqual(record, new MarcRecord(expectedResult));
|
|
46
46
|
}
|
package/src/sortSubfields.js
CHANGED
|
@@ -126,7 +126,7 @@ const subfieldSortOrder = [
|
|
|
126
126
|
{'tag': '800', 'sortOrder': sortOrderForX00},
|
|
127
127
|
{'tag': '810', 'sortOrder': sortOrderForX10},
|
|
128
128
|
{'tag': '811', 'sortOrder': sortOrderForX11},
|
|
129
|
-
{'tag': '830', 'sortOrder': ['a', 'n', 'x', 'v']}, //
|
|
129
|
+
{'tag': '830', 'sortOrder': ['a', 'n', 'p', 'x', 'v']}, // Sort of an extension of f490...
|
|
130
130
|
{'tag': '856', 'sortOrder': ['3', 'u', 'q', 'x', 'y', 'z', '5']}, // incomplete, LoC examples are inconclusive
|
|
131
131
|
{'tag': '880', 'sortOrder': ['a']},
|
|
132
132
|
{'tag': '946', 'sortOrder': sortOrderFor246},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Fix Cyrillux-related stuff: split 410 to 490 and 810, and split 440 to 490 and
|
|
2
|
+
"description": "Fix Cyrillux-related stuff: split 410 to 490 and 810, and split 440 to 490 and 830",
|
|
3
3
|
"comment": "Also note few indicator changes",
|
|
4
4
|
"only": false,
|
|
5
5
|
"fix": true
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
{ "code": "d", "value": "1890-1940," },
|
|
8
8
|
{ "code": "e", "value": "säveltäjä," },
|
|
9
9
|
{ "code": "e", "value": "sanoittaja," },
|
|
10
|
-
{ "code": "e", "value": "sovittaja." }
|
|
11
|
-
{ "code": "0", "value": "(FI-ASTERI-N)000123456" }
|
|
10
|
+
{ "code": "e", "value": "sovittaja." }
|
|
12
11
|
]}
|
|
13
12
|
]
|
|
14
13
|
}
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
]},
|
|
8
8
|
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
9
9
|
{ "code": "a", "value": "Sukunimi, Etunimi," },
|
|
10
|
-
{ "code": "e", "value": "sovittaja." }
|
|
11
|
-
{ "code": "0", "value": "(FI-ASTERI-N)000123456" }
|
|
10
|
+
{ "code": "e", "value": "sovittaja." }
|
|
12
11
|
]},
|
|
13
12
|
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
14
13
|
{ "code": "a", "value": "Sukunimi, Etunimi," },
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "12345cam a22123454i 4500",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
6
|
+
{ "code": "a", "value": "Sukunimi, A." },
|
|
7
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000000111" }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "Sukunimi, B." },
|
|
11
|
+
{ "code": "q", "value": "(Börje)," },
|
|
12
|
+
{ "code": "d", "value": "1234-1299." },
|
|
13
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000000123" }
|
|
14
|
+
]}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "12345cam a22123454i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Sukunimi, A." },
|
|
6
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000000111" }
|
|
7
|
+
]},
|
|
8
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
9
|
+
{ "code": "a", "value": "Sukunimi, A.," },
|
|
10
|
+
{ "code": "d", "value": "1234-1299." }
|
|
11
|
+
]},
|
|
12
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "Sukunimi, B." },
|
|
14
|
+
{ "code": "q", "value": "(Börje)" },
|
|
15
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000000123" }
|
|
16
|
+
]},
|
|
17
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
18
|
+
{ "code": "a", "value": "Sukunimi, B.," },
|
|
19
|
+
{ "code": "d", "value": "1234-1299." },
|
|
20
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000000123" }
|
|
21
|
+
]}
|
|
22
|
+
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "830", "ind1": " ", "ind2": "0", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Annales." },
|
|
6
|
+
{ "code": "n", "value": "Series B," },
|
|
7
|
+
{ "code": "p", "value": "Humaniora ;" },
|
|
8
|
+
{ "code": "v", "value": "153, 4" }
|
|
9
|
+
] },
|
|
10
|
+
{ "tag": "830", "ind1": " ", "ind2": "0", "subfields": [
|
|
11
|
+
{ "code": "a", "value": "Annales." },
|
|
12
|
+
{ "code": "n", "value": "Series B," },
|
|
13
|
+
{ "code": "x", "value": "0066-2011 ;" },
|
|
14
|
+
{ "code": "v", "value": "153, 4" },
|
|
15
|
+
{ "code": "0", "value": "(FI-ASTERI-W)000015651" }
|
|
16
|
+
] }
|
|
17
|
+
],
|
|
18
|
+
"leader": "01331cam a22003498i 4500"
|
|
19
|
+
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "830", "ind1": " ", "ind2": "0", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Annales." },
|
|
6
|
+
{ "code": "n", "value": "Series B," },
|
|
7
|
+
{ "code": "p", "value": "Humaniora ;" },
|
|
8
|
+
{ "code": "v", "value": "153, 4" }
|
|
9
|
+
] },
|
|
10
|
+
{ "tag": "830", "ind1": " ", "ind2": "0", "subfields": [
|
|
11
|
+
{ "code": "a", "value": "Annales." },
|
|
12
|
+
{ "code": "n", "value": "Series B," },
|
|
13
|
+
{ "code": "x", "value": "0066-2011 ;" },
|
|
14
|
+
{ "code": "v", "value": "153, 4" },
|
|
15
|
+
{ "code": "0", "value": "(FI-ASTERI-W)000015651" }
|
|
16
|
+
] }
|
|
17
|
+
],
|
|
18
|
+
"leader": "01331cam a22003498i 4500"
|
|
19
|
+
|
|
20
|
+
}
|