@natlibfi/marc-record-validators-melinda 11.5.5 → 11.6.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/dist/field-505-separators.js +3 -0
- package/dist/field-505-separators.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/modernize-502.js +117 -0
- package/dist/modernize-502.js.map +1 -0
- package/dist/modernize-502.spec.js +49 -0
- package/dist/modernize-502.spec.js.map +1 -0
- package/dist/punctuation2.js +17 -4
- package/dist/punctuation2.js.map +1 -1
- package/dist/subfieldValueNormalizations.js +47 -8
- package/dist/subfieldValueNormalizations.js.map +1 -1
- package/package.json +7 -6
- package/src/field-505-separators.js +3 -0
- package/src/index.js +2 -0
- package/src/modernize-502.js +118 -0
- package/src/modernize-502.spec.js +48 -0
- package/src/punctuation2.js +6 -4
- package/src/subfieldValueNormalizations.js +50 -9
- package/test-fixtures/field-505-separators/03/expectedResult.json +23 -0
- package/test-fixtures/field-505-separators/03/metadata.json +6 -0
- package/test-fixtures/field-505-separators/03/record.json +21 -0
- package/test-fixtures/modernize-502/01/expectedResult.json +6 -0
- package/test-fixtures/modernize-502/01/metadata.json +5 -0
- package/test-fixtures/modernize-502/01/record.json +15 -0
- package/test-fixtures/modernize-502/02/expectedResult.json +29 -0
- package/test-fixtures/modernize-502/02/metadata.json +5 -0
- package/test-fixtures/modernize-502/02/record.json +31 -0
- package/test-fixtures/normalize-subfield-value/04/expectedResult.json +24 -0
- package/test-fixtures/normalize-subfield-value/04/metadata.json +5 -0
- package/test-fixtures/normalize-subfield-value/04/record.json +22 -0
- package/test-fixtures/normalize-subfield-value/05/expectedResult.json +27 -0
- package/test-fixtures/normalize-subfield-value/05/metadata.json +6 -0
- package/test-fixtures/normalize-subfield-value/05/record.json +25 -0
- package/test-fixtures/punctuation2/01/expectedResult.json +2 -2
- package/test-fixtures/punctuation2/100_and_880/expectedResult.json +12 -2
- package/test-fixtures/punctuation2/100_and_880/metadata.json +2 -1
- package/test-fixtures/punctuation2/100_and_880/record.json +12 -2
- package/test-fixtures/punctuation2/97/expectedResult.json +1 -1
- package/test-fixtures/punctuation2/98/expectedResult.json +2 -2
- package/test-fixtures/sort-relator-terms/f02/expectedResult.json +8 -1
- package/test-fixtures/sort-relator-terms/f02/record.json +7 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//import createDebugLogger from 'debug';
|
|
2
|
+
import clone from 'clone';
|
|
3
|
+
import {fieldToString} from './utils';
|
|
4
|
+
|
|
5
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/modernize-502');
|
|
6
|
+
|
|
7
|
+
// Author(s): Nicholas Volk
|
|
8
|
+
export default function () {
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
description: 'Normalizes Finnish national convention 502$a$c$d fields to a 502$a (which is better supported by LoC).',
|
|
12
|
+
validate, fix
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function fix(record) {
|
|
16
|
+
const res = {message: [], fix: [], valid: true};
|
|
17
|
+
|
|
18
|
+
record.fields.forEach(field => {
|
|
19
|
+
normalizeField502(field);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
23
|
+
return res;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function validate(record) {
|
|
27
|
+
const res = {message: []};
|
|
28
|
+
|
|
29
|
+
record.fields.forEach(field => {
|
|
30
|
+
validateField(field, res);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
34
|
+
return res;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function validateField(field, res) {
|
|
38
|
+
if (!field.subfields) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const orig = fieldToString(field);
|
|
42
|
+
|
|
43
|
+
const normalizedField = normalizeField502(clone(field));
|
|
44
|
+
const mod = fieldToString(normalizedField);
|
|
45
|
+
if (orig !== mod) { // Fail as the input is "broken"/"crap"/sumthing
|
|
46
|
+
res.message.push(`Fix '${orig}' => '${mod}'`); // eslint-disable-line functional/immutable-data
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
export function normalizeField502(field) {
|
|
55
|
+
if (!field.subfields) {
|
|
56
|
+
return field;
|
|
57
|
+
}
|
|
58
|
+
const acd = field.subfields.filter(sf => 'acd'.includes(sf.code));
|
|
59
|
+
const str = acd.map(sf => sf.code).join('');
|
|
60
|
+
// Check that we have relevant subfields and that they are in relevant order (with each other):
|
|
61
|
+
if (!['acd', 'ac', 'ad'].includes(str)) {
|
|
62
|
+
return field;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// "a = acd[0]"" is way more readable than "[a] = acd"...
|
|
66
|
+
const a = acd[0]; // eslint-disable-line prefer-destructuring
|
|
67
|
+
const c = acd[1].code === 'c' ? acd[1] : null;
|
|
68
|
+
const d = acd[acd.length - 1].code === 'd' ? acd[acd.length - 1] : null;
|
|
69
|
+
|
|
70
|
+
//console.log(JSON.stringify(d)); // eslint-disable-line no-console
|
|
71
|
+
|
|
72
|
+
if (!hasValidA() || !hasValidD()) {
|
|
73
|
+
return field;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const newValue = `${extractA()}--${extractC()}${extractD()}`;
|
|
77
|
+
a.value = newValue; // eslint-disable-line functional/immutable-data
|
|
78
|
+
field.subfields = field.subfields.filter(sf => !['c', 'd'].includes(sf.code)); // eslint-disable-line functional/immutable-data
|
|
79
|
+
return field;
|
|
80
|
+
|
|
81
|
+
function extractA() {
|
|
82
|
+
return a.value.replace(/[ ,:]+$/u, '');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function extractC() {
|
|
86
|
+
if (!c) {
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
if (c) {
|
|
90
|
+
// Here we assume that there was correct punctuation between $c and $d...
|
|
91
|
+
return `${c.value}${d ? ' ' : ''}`;
|
|
92
|
+
}
|
|
93
|
+
return c.value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function extractD() {
|
|
97
|
+
return d ? d.value : '';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function hasValidA() {
|
|
101
|
+
// Belongs to https://finto.fi/mts/fi/page/m91
|
|
102
|
+
if (a.value.match(/^(?:AMK-opinnäytetyö|Anbalyysiseminaarityö|Artikkeliväitöskirja|Diplomityö|Erikoistyö|Esseeväitöskirja|Kandidaatintutkielma|Laudaturseminaarityö|Laudaturtyö|Lisensiaatintyö|Lopputyö|Monografiaväitöskirja|Opinnäyte|Opinnäytetyö|Pro gradu -tutkielma|Proseminaarityö|Seminaarityö|Väitöskirja|Ylempi AMK-opinnäytetyö)[, :]*$/u) ||
|
|
103
|
+
a.value.match(/^(?:Analysseminariearbete|Artikelavhandling|Diplomarbete|Doktorsavhandling|Essäavhandling|Högre YH-examensarbete|Kandidatavhandling|Laudaturarbete|Laudaturseminariearbete|Licentiatavhandling|Lärdomsprov|Monografiavhandling|Pro gradu-avhandling|Proseminariearbete|Seminariearbete|Slutarbete|Specialarbete|YH-examesarbete)[:, ]*$/u)) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
function hasValidD() {
|
|
111
|
+
if (!d) { // We can live without $d:
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
// Content makes sense:
|
|
115
|
+
return d.value.match(/^\[?(?:[0-9]{4}|[0-9]{4}-[0-9]{4}|1[89]uu|Vuosien [0-9]{4} ja [0-9]{4} välillä)[\].]{0,2}$/u);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
|
+
import validatorFactory from './modernize-502';
|
|
4
|
+
import {READERS} from '@natlibfi/fixura';
|
|
5
|
+
import generateTests from '@natlibfi/fixugen';
|
|
6
|
+
//import createDebugLogger from 'debug';
|
|
7
|
+
|
|
8
|
+
generateTests({
|
|
9
|
+
callback,
|
|
10
|
+
path: [__dirname, '..', 'test-fixtures', 'modernize-502'],
|
|
11
|
+
useMetadataFile: true,
|
|
12
|
+
recurse: false,
|
|
13
|
+
fixura: {
|
|
14
|
+
reader: READERS.JSON
|
|
15
|
+
},
|
|
16
|
+
mocha: {
|
|
17
|
+
before: () => testValidatorFactory()
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/modernize-502:test');
|
|
22
|
+
|
|
23
|
+
async function testValidatorFactory() {
|
|
24
|
+
const validator = await validatorFactory();
|
|
25
|
+
|
|
26
|
+
expect(validator)
|
|
27
|
+
.to.be.an('object')
|
|
28
|
+
.that.has.any.keys('description', 'validate');
|
|
29
|
+
|
|
30
|
+
expect(validator.description).to.be.a('string');
|
|
31
|
+
expect(validator.validate).to.be.a('function');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function callback({getFixture, fix = false}) {
|
|
35
|
+
const validator = await validatorFactory();
|
|
36
|
+
const record = new MarcRecord(getFixture('record.json'));
|
|
37
|
+
const expectedResult = getFixture('expectedResult.json');
|
|
38
|
+
// console.log(expectedResult); // eslint-disable-line
|
|
39
|
+
|
|
40
|
+
if (!fix) {
|
|
41
|
+
const result = await validator.validate(record);
|
|
42
|
+
expect(result).to.eql(expectedResult);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await validator.fix(record);
|
|
47
|
+
expect(record).to.eql(expectedResult);
|
|
48
|
+
}
|
package/src/punctuation2.js
CHANGED
|
@@ -100,13 +100,14 @@ const puncIsProbablyPunc = /(?:[a-z0-9)]|å|ä|ö) ?[.,:;]$/u;
|
|
|
100
100
|
|
|
101
101
|
// Will unfortunately trigger "Sukunimi, Th." type:
|
|
102
102
|
const removeColons = {'code': 'abcdefghijklmnopqrstuvwxyz', 'remove': / *[;:]$/u};
|
|
103
|
-
const removeX00Comma = {'code': '
|
|
103
|
+
const removeX00Comma = {'code': 'abcdejnqt', 'followedBy': 'abcdenqtv#', 'context': /.,$/u, 'remove': /,$/u};
|
|
104
104
|
const cleanRHS = {'code': 'abcd', 'followedBy': 'bcde', 'context': /(?:(?:[a-z0-9]|å|ä|ö)\.|,)$/u, 'contextRHS': blocksPuncRHS, 'remove': /[.,]$/u};
|
|
105
105
|
const cleanX00dCommaOrDot = {'code': 'd', 'followedBy': 'et#', 'context': /[0-9]-[,.]$/u, 'remove': /[,.]$/u};
|
|
106
106
|
const cleanX00aDot = {'code': 'abcde', 'followedBy': 'cdegj', 'context': dotIsProbablyPunc, 'remove': /\.$/u};
|
|
107
107
|
const cleanCorruption = {'code': 'abcdefghijklmnopqrstuvwxyz', 'remove': / \.$/u};
|
|
108
108
|
// These $e dot removals are tricky: before removing the comma, we should know that it ain't an abbreviation such as "esitt."...
|
|
109
109
|
const cleanX00eDot = {'code': 'e', 'followedBy': 'egj#', 'context': /(?:[ai]ja|jä)[.,]$/u, 'remove': /\.$/u};
|
|
110
|
+
const cleanX11jDot = {'code': 'e', 'followedBy': 'egj#', 'context': /(?:[ai]ja|jä)[.,]$/u, 'remove': /\.$/u};
|
|
110
111
|
const removeCommaBeforeLanguageSubfieldL = {'followedBy': 'l', 'remove': /,$/u};
|
|
111
112
|
const removeCommaBeforeTitleSubfieldT = {'followedBy': 't', 'remove': /,$/u};
|
|
112
113
|
|
|
@@ -117,7 +118,8 @@ const cleanPuncBeforeLanguage = {'code': 'atvxyz', 'followedBy': 'l', 'context':
|
|
|
117
118
|
const addX00aComma = {'add': ',', 'code': 'abcqej', 'followedBy': 'cdeg', 'context': doesNotEndInPunc, 'contextRHS': allowsPuncRHS};
|
|
118
119
|
const addX00dComma = {'name': 'X00$d ending in "-" does not get comma', 'add': ',', 'code': 'd', 'followedBy': 'cdeg', 'context': /[^-,.!]$/u, 'contextRHS': allowsPuncRHS};
|
|
119
120
|
const addX00aComma2 = {'add': ',', 'code': 'abcdej', 'followedBy': 'cdeg', 'context': /(?:[A-Z]|Å|Ä|Ö)\.$/u, 'contextRHS': allowsPuncRHS};
|
|
120
|
-
const addX00Dot = {'add': '.', 'code': 'abcdetv', 'followedBy': '
|
|
121
|
+
const addX00Dot = {'add': '.', 'code': 'abcdetv', 'followedBy': 'fklptu', 'context': needsPuncAfterAlphanumeric};
|
|
122
|
+
const addEntryFieldFinalDot = {'name': 'X00 final dot', 'add': '.', 'code': 'abcdefghijklmnopqrstuvwxyz', 'followedBy': '#', 'context': /[^.)]$/u};
|
|
121
123
|
|
|
122
124
|
|
|
123
125
|
const addX10iColon = {name: 'Punctuate relationship information', add: ':', code: 'i', context: defaultNeedsPuncAfter2};
|
|
@@ -145,7 +147,7 @@ const removeCrapFromAllEntryFields = [removeCommaBeforeLanguageSubfieldL, remove
|
|
|
145
147
|
|
|
146
148
|
const removeX00Whatever = [removeX00Comma, cleanX00aDot, cleanX00eDot, cleanCorruption, cleanX00dCommaOrDot, cleanRHS, X00RemoveDotAfterBracket, removeColons, cleanPuncBeforeLanguage, ...removeCrapFromAllEntryFields];
|
|
147
149
|
const removeX10Whatever = [removeX00Comma, cleanX00aDot, cleanX00eDot, cleanCorruption, removeColons, cleanPuncBeforeLanguage, ...removeCrapFromAllEntryFields];
|
|
148
|
-
const removeX11Whatever = [...removeCrapFromAllEntryFields];
|
|
150
|
+
const removeX11Whatever = [removeX00Comma, cleanX11jDot, ...removeCrapFromAllEntryFields];
|
|
149
151
|
const removeX30Whatever = removeCrapFromAllEntryFields;
|
|
150
152
|
|
|
151
153
|
const remove490And830Whatever = [{'code': 'axyzv', 'followedBy': 'axyzv', 'remove': /(?: *;| *=|,)$/u}];
|
|
@@ -299,7 +301,7 @@ const cleanValidPunctuationRules = {
|
|
|
299
301
|
|
|
300
302
|
|
|
301
303
|
// Overgeneralizes a bit: eg. addColonToRelationshipInformation only applies to 700/710 but as others don't have $i, it's fine.
|
|
302
|
-
const addToAllEntryFields = [addDotBeforeLanguageSubfieldL, addSemicolonBeforeVolumeDesignation, addColonToRelationshipInformation];
|
|
304
|
+
const addToAllEntryFields = [addDotBeforeLanguageSubfieldL, addSemicolonBeforeVolumeDesignation, addColonToRelationshipInformation, addEntryFieldFinalDot];
|
|
303
305
|
|
|
304
306
|
|
|
305
307
|
const addX00 = [addX00aComma, addX00aComma2, addX00Dot, addX00dComma, ...addToAllEntryFields];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//import createDebugLogger from 'debug';
|
|
2
2
|
import clone from 'clone';
|
|
3
|
-
import {fieldHasSubfield, fieldToString} from './utils';
|
|
3
|
+
import {fieldHasSubfield, fieldToString, getCatalogingLanguage} from './utils';
|
|
4
4
|
import {fieldFixPunctuation} from './punctuation2';
|
|
5
5
|
import {fieldGetUnambiguousTag} from './subfield6Utils';
|
|
6
6
|
|
|
7
|
+
// NB! You should probably run punctuation fixes after this validator!
|
|
7
8
|
|
|
8
9
|
// Author(s): Nicholas Volk
|
|
9
10
|
export default function () {
|
|
@@ -14,10 +15,11 @@ export default function () {
|
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
function fix(record) {
|
|
18
|
+
const catLang = getCatalogingLanguage(record, 'fin');
|
|
17
19
|
const res = {message: [], fix: [], valid: true};
|
|
18
20
|
|
|
19
21
|
record.fields.forEach(field => {
|
|
20
|
-
normalizeSubfieldValues(field);
|
|
22
|
+
normalizeSubfieldValues(field, catLang);
|
|
21
23
|
});
|
|
22
24
|
|
|
23
25
|
// message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
@@ -25,23 +27,24 @@ export default function () {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
function validate(record) {
|
|
30
|
+
const catLang = getCatalogingLanguage(record, 'fin');
|
|
28
31
|
const res = {message: []};
|
|
29
32
|
|
|
30
33
|
record.fields.forEach(field => {
|
|
31
|
-
validateField(field, res);
|
|
34
|
+
validateField(field, res, catLang);
|
|
32
35
|
});
|
|
33
36
|
|
|
34
37
|
res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
35
38
|
return res;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
function validateField(field, res) {
|
|
41
|
+
function validateField(field, res, catLang) {
|
|
39
42
|
if (!field.subfields) {
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
42
45
|
const orig = fieldToString(field);
|
|
43
46
|
|
|
44
|
-
const normalizedField = normalizeSubfieldValues(clone(field));
|
|
47
|
+
const normalizedField = normalizeSubfieldValues(clone(field), catLang);
|
|
45
48
|
const mod = fieldToString(normalizedField);
|
|
46
49
|
if (orig !== mod) { // Fail as the input is "broken"/"crap"/sumthing
|
|
47
50
|
res.message.push(`'${orig}' requires subfield internal mods/normalization`); // eslint-disable-line functional/immutable-data
|
|
@@ -73,9 +76,46 @@ function handleInitials(value, subfieldCode, field) {
|
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
function getNormalizedValue(subfield, field) {
|
|
77
|
-
return uppercaseLanguage(handleMovies(handleInitials(subfield.value, subfield.code, field)));
|
|
79
|
+
function getNormalizedValue(subfield, field, catLang) {
|
|
80
|
+
return handleFikt(uppercaseLanguage(handleMovies(handleInitials(subfield.value, subfield.code, field))));
|
|
78
81
|
|
|
82
|
+
function handleFikt(value) {
|
|
83
|
+
if (subfield.code !== 'c' || field.tag !== '600') {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return wrapFiktiivinenHahmo(expandFikt(value));
|
|
88
|
+
|
|
89
|
+
function wrapFiktiivinenHahmo(value) {
|
|
90
|
+
if (value.includes('(')) { // Some kind of parentheses already found -> nothing to do here
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
if (value.match(/^(?:fiktiivinen hahmo|fiktiv gestalt|fiktiivinen yhteisö)[,.]?$/u)) {
|
|
94
|
+
// Hope that some other module handles punctuation, if needed:
|
|
95
|
+
return `(${value.replace(/[.,]$/u, '')})`;
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// wrap text around parentheses
|
|
101
|
+
function expandFikt(value) {
|
|
102
|
+
if (field.ind1 === '3') { // Not handling "fiktiivinen yhteisö" at the moment
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (value.match(/\bfikt\.?(?:$|[,)])/u) && !value.match(/fikt.*fikt/ui)) {
|
|
107
|
+
// NB! Dot '.' in 'fikt.' might also be punctuation as well. Run punctuation2 fixer after this fixer!
|
|
108
|
+
if (catLang === 'fin') {
|
|
109
|
+
return value.replace(/\bfikt\./u, 'fiktiivinen hahmo');
|
|
110
|
+
}
|
|
111
|
+
if (catLang === 'swe') {
|
|
112
|
+
return value.replace(/\bfikt\./u, 'fiktiv gestalt');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|
|
79
119
|
|
|
80
120
|
function handleMovies(value) {
|
|
81
121
|
if (subfield.code === 'a' && ['130', '630', '730'].includes(field.tag)) {
|
|
@@ -85,6 +125,7 @@ function getNormalizedValue(subfield, field) {
|
|
|
85
125
|
return value;
|
|
86
126
|
}
|
|
87
127
|
|
|
128
|
+
|
|
88
129
|
function uppercaseLanguage(value) { // Part of MET-549
|
|
89
130
|
const relevantTags = ['130', '240', '243', '600', '610', '611', '630', '700', '710', '711', '730', '800', '810', '811', '830'];
|
|
90
131
|
|
|
@@ -108,12 +149,12 @@ function getNormalizedValue(subfield, field) {
|
|
|
108
149
|
}
|
|
109
150
|
}
|
|
110
151
|
|
|
111
|
-
function normalizeSubfieldValues(field) {
|
|
152
|
+
function normalizeSubfieldValues(field, catLang) {
|
|
112
153
|
if (!field.subfields) {
|
|
113
154
|
return field;
|
|
114
155
|
}
|
|
115
156
|
field.subfields.forEach((subfield, index) => {
|
|
116
|
-
field.subfields[index].value = getNormalizedValue(subfield, field); // eslint-disable-line functional/immutable-data
|
|
157
|
+
field.subfields[index].value = getNormalizedValue(subfield, field, catLang); // eslint-disable-line functional/immutable-data
|
|
117
158
|
});
|
|
118
159
|
return field;
|
|
119
160
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{
|
|
5
|
+
"tag": "005",
|
|
6
|
+
"value": "20220202020202.0"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"tag": "505", "ind1": "0", "ind2": " ",
|
|
10
|
+
"subfields": [
|
|
11
|
+
{ "code": "a", "value": "1. Johdanto -- 2. Käsitteelliset lähtökohdat -- 3. Teoksen lähestymistapa, aineistot ja tutkimusmenetelmät -- 4. Nousu eliittiin -- 5. Huippujohtajiin kohdistuvat odotukset -- 6. Vallan verkostot -- 7. Eliittien asenteellinen yhtenäisyys -- 8. Horisontaalinen uraliikkuvuus -- 9. Eliitit muutoksessa." }
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"tag": "505", "ind1": "0", "ind2": " ",
|
|
16
|
+
"subfields": [
|
|
17
|
+
{ "code": "g" },
|
|
18
|
+
{ "code": "t"}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"leader": ""
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": [
|
|
3
|
+
{
|
|
4
|
+
"tag": "005",
|
|
5
|
+
"value": "20220202020202.0"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"tag": "505", "ind1": "0", "ind2": " ",
|
|
9
|
+
"subfields": [
|
|
10
|
+
{ "code": "a", "value": "1. Johdanto -- 2. Käsitteelliset lähtökohdat -- 3. Teoksen lähestymistapa, aineistot ja tutkimusmenetelmät -- 4. Nousu eliittiin -- 5. Huippujohtajiin kohdistuvat odotukset -- 6. Vallan verkostot -- 7. Eliittien asenteellinen yhtenäisyys -- 8. Horisontaalinen uraliikkuvuus -- 9. Eliitit muutoksessa." }
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"tag": "505", "ind1": "0", "ind2": " ",
|
|
15
|
+
"subfields": [
|
|
16
|
+
{ "code": "g" },
|
|
17
|
+
{ "code": "t"}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": [
|
|
3
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
4
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Väitöskirja :" },
|
|
6
|
+
{ "code": "c", "value": "Helsingin yliopisto," },
|
|
7
|
+
{ "code": "d", "value": "1980." }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "Uimamaisterin päättökoe :" },
|
|
11
|
+
{ "code": "c", "value": "Helsingin Uimastadion," },
|
|
12
|
+
{ "code": "d", "value": "1980." }
|
|
13
|
+
]}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
6
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
7
|
+
{ "code": "a", "value": "Väitöskirja--Helsingin yliopisto, 1980." }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "Väitöskirja--Helsingin yliopisto, 1980." }
|
|
11
|
+
]},
|
|
12
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "Uimamaisterin päättökoe :" },
|
|
14
|
+
{ "code": "c", "value": "Helsingin Uimastadion," },
|
|
15
|
+
{ "code": "d", "value": "1980." }
|
|
16
|
+
]},
|
|
17
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
18
|
+
{ "code": "a", "value": "Pro gradu -avledning :" },
|
|
19
|
+
{ "code": "c", "value": "Helsingfors universitet," },
|
|
20
|
+
{ "code": "d", "value": "19uu." }
|
|
21
|
+
]},
|
|
22
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
23
|
+
{ "code": "a", "value": "Opinnäyte--Unicafe Rotunda." }
|
|
24
|
+
]},
|
|
25
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
26
|
+
{ "code": "a", "value": "Opinnäyte--2099." }
|
|
27
|
+
]}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": [
|
|
3
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
4
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Väitöskirja :" },
|
|
6
|
+
{ "code": "c", "value": "Helsingin yliopisto," },
|
|
7
|
+
{ "code": "d", "value": "1980." }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "Väitöskirja--Helsingin yliopisto, 1980." }
|
|
11
|
+
]},
|
|
12
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "Uimamaisterin päättökoe :" },
|
|
14
|
+
{ "code": "c", "value": "Helsingin Uimastadion," },
|
|
15
|
+
{ "code": "d", "value": "1980." }
|
|
16
|
+
]},
|
|
17
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
18
|
+
{ "code": "a", "value": "Pro gradu -avledning :" },
|
|
19
|
+
{ "code": "c", "value": "Helsingfors universitet," },
|
|
20
|
+
{ "code": "d", "value": "19uu." }
|
|
21
|
+
]},
|
|
22
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
23
|
+
{ "code": "a", "value": "Opinnäyte :" },
|
|
24
|
+
{ "code": "c", "value": "Unicafe Rotunda." }
|
|
25
|
+
]},
|
|
26
|
+
{ "tag": "502", "ind1": " ", "ind2": " ", "subfields": [
|
|
27
|
+
{ "code": "a", "value": "Opinnäyte," },
|
|
28
|
+
{ "code": "d", "value": "2099." }
|
|
29
|
+
]}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
6
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
7
|
+
{ "code": "a", "value": "What, Ever," },
|
|
8
|
+
{ "code": "c", "value": "(fiktiivinen hahmo)" }
|
|
9
|
+
]},
|
|
10
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
11
|
+
{ "code": "a", "value": "What, Never" },
|
|
12
|
+
{ "code": "c", "value": "(fiktiivinen hahmo)" }
|
|
13
|
+
]},
|
|
14
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
15
|
+
{ "code": "a", "value": "What, Fever" },
|
|
16
|
+
{ "code": "c", "value": "(fiktiivinen hahmo)" }
|
|
17
|
+
]},
|
|
18
|
+
{ "tag": "600", "ind1": "3", "ind2": "4", "subfields": [
|
|
19
|
+
{ "code": "a", "value": "Whatever" },
|
|
20
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
21
|
+
]}
|
|
22
|
+
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": [
|
|
3
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
4
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "What, Ever," },
|
|
6
|
+
{ "code": "c", "value": "fikt." }
|
|
7
|
+
]},
|
|
8
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
9
|
+
{ "code": "a", "value": "What, Never" },
|
|
10
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
11
|
+
]},
|
|
12
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "What, Fever" },
|
|
14
|
+
{ "code": "c", "value": "fiktiivinen hahmo." }
|
|
15
|
+
]},
|
|
16
|
+
{ "tag": "600", "ind1": "3", "ind2": "4", "subfields": [
|
|
17
|
+
{ "code": "a", "value": "Whatever" },
|
|
18
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
19
|
+
]}
|
|
20
|
+
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
6
|
+
{ "tag": "040", "ind1": " ", "ind2": " ", "subfields": [
|
|
7
|
+
{ "code": "b", "value": "swe" }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "What, Ever," },
|
|
11
|
+
{ "code": "c", "value": "(fiktiv gestalt)" }
|
|
12
|
+
]},
|
|
13
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
14
|
+
{ "code": "a", "value": "What, Never" },
|
|
15
|
+
{ "code": "c", "value": "(fiktiv gestalt)" }
|
|
16
|
+
]},
|
|
17
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
18
|
+
{ "code": "a", "value": "What, Fever" },
|
|
19
|
+
{ "code": "c", "value": "(fiktiivinen hahmo)" }
|
|
20
|
+
]},
|
|
21
|
+
{ "tag": "600", "ind1": "3", "ind2": "4", "subfields": [
|
|
22
|
+
{ "code": "a", "value": "Whatever" },
|
|
23
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
24
|
+
]}
|
|
25
|
+
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fields": [
|
|
3
|
+
{ "tag": "005", "value": "20220202020202.0" },
|
|
4
|
+
{ "tag": "040", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "b", "value": "swe" }
|
|
6
|
+
]},
|
|
7
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
8
|
+
{ "code": "a", "value": "What, Ever," },
|
|
9
|
+
{ "code": "c", "value": "fikt." }
|
|
10
|
+
]},
|
|
11
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
12
|
+
{ "code": "a", "value": "What, Never" },
|
|
13
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
14
|
+
]},
|
|
15
|
+
{ "tag": "600", "ind1": "1", "ind2": "4", "subfields": [
|
|
16
|
+
{ "code": "a", "value": "What, Fever" },
|
|
17
|
+
{ "code": "c", "value": "fiktiivinen hahmo." }
|
|
18
|
+
]},
|
|
19
|
+
{ "tag": "600", "ind1": "3", "ind2": "4", "subfields": [
|
|
20
|
+
{ "code": "a", "value": "Whatever" },
|
|
21
|
+
{ "code": "c", "value": "(fikt.)" }
|
|
22
|
+
]}
|
|
23
|
+
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"message": [
|
|
3
3
|
"'100 1# ‡a Tuisku, Sara ‡e turkulainen ‡e testaaja' => '100 1# ‡a Tuisku, Sara, ‡e turkulainen, ‡e testaaja.'",
|
|
4
4
|
"'700 1# ‡a Reipas, R. ‡d 2000- ‡e esittäjä' => '700 1# ‡a Reipas, R., ‡d 2000- ‡e esittäjä.'",
|
|
5
|
-
"'700 1# ‡a Reippaahko, R. ‡d 2000-' => '700 1# ‡a Reippaahko, R., ‡d 2000
|
|
5
|
+
"'700 1# ‡a Reippaahko, R. ‡d 2000-' => '700 1# ‡a Reippaahko, R., ‡d 2000-.'",
|
|
6
6
|
"'700 1# ‡a Reippaampi, R. ‡d 2000-2050 ‡e esittäjä' => '700 1# ‡a Reippaampi, R., ‡d 2000-2050, ‡e esittäjä.'",
|
|
7
7
|
"'700 1# ‡a Reippain, R. ‡d 2000-2050' => '700 1# ‡a Reippain, R., ‡d 2000-2050.'",
|
|
8
|
-
"'700 1# ‡a Nalle, P. ‡d 1926- ‡0 (FIN11)000000000' => '700 1# ‡a Nalle, P., ‡d 1926
|
|
8
|
+
"'700 1# ‡a Nalle, P. ‡d 1926- ‡0 (FIN11)000000000' => '700 1# ‡a Nalle, P., ‡d 1926-. ‡0 (FIN11)000000000'"
|
|
9
9
|
],
|
|
10
10
|
"valid": false
|
|
11
11
|
|