@natlibfi/marc-record-validators-melinda 10.13.1-alpha.2 → 10.14.0-alpha.1
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/ending-punctuation-conf.js +3 -6
- package/dist/ending-punctuation-conf.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/punctuation/rules/aut.js +1 -2
- package/dist/punctuation/rules/aut.js.map +1 -1
- package/dist/punctuation/rules/bib.js +1 -2
- package/dist/punctuation/rules/bib.js.map +1 -1
- package/dist/punctuation2.js +40 -14
- package/dist/punctuation2.js.map +1 -1
- package/dist/removeInferiorDataFields.js +166 -168
- package/dist/removeInferiorDataFields.js.map +1 -1
- package/dist/sortFields.js +383 -0
- package/dist/sortFields.js.map +1 -0
- package/dist/sortFields.spec.js +51 -0
- package/dist/sortFields.spec.js.map +1 -0
- package/dist/sortRelatorTerms.js +3 -25
- package/dist/sortRelatorTerms.js.map +1 -1
- package/dist/sortSubfields.js +14 -4
- package/dist/sortSubfields.js.map +1 -1
- package/dist/sortSubfields.spec.js +4 -3
- package/dist/sortSubfields.spec.js.map +1 -1
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -1
- package/package.json +7 -7
- package/src/index.js +3 -1
- package/src/punctuation2.js +14 -7
- package/src/removeInferiorDataFields.js +166 -169
- package/src/sortFields.js +393 -0
- package/src/sortFields.spec.js +52 -0
- package/src/sortRelatorTerms.js +3 -25
- package/src/sortSubfields.js +18 -4
- package/src/sortSubfields.spec.js +3 -3
- package/src/utils.js +5 -0
- package/test-fixtures/remove-inferior-datafields/f01/expectedResult.json +12 -0
- package/test-fixtures/remove-inferior-datafields/f01/record.json +19 -0
- package/test-fixtures/sort-fields/01/input.json +32 -0
- package/test-fixtures/sort-fields/01/metadata.json +5 -0
- package/test-fixtures/sort-fields/01/result.json +29 -0
- package/test-fixtures/sort-fields/02/input.json +49 -0
- package/test-fixtures/sort-fields/02/metadata.json +4 -0
- package/test-fixtures/sort-fields/02/result.json +50 -0
- package/test-fixtures/sort-fields/03/input.json +20 -0
- package/test-fixtures/sort-fields/03/metadata.json +5 -0
- package/test-fixtures/sort-fields/03/result.json +21 -0
- package/test-fixtures/sort-fields/04/input.json +13 -0
- package/test-fixtures/sort-fields/04/metadata.json +4 -0
- package/test-fixtures/sort-fields/04/result.json +13 -0
- package/test-fixtures/sort-fields/05/input.json +27 -0
- package/test-fixtures/sort-fields/05/metadata.json +4 -0
- package/test-fixtures/sort-fields/05/result.json +28 -0
- package/test-fixtures/sort-fields/06/input.json +36 -0
- package/test-fixtures/sort-fields/06/metadata.json +4 -0
- package/test-fixtures/sort-fields/06/result.json +37 -0
- package/test-fixtures/sort-fields/07/input.json +21 -0
- package/test-fixtures/sort-fields/07/metadata.json +4 -0
- package/test-fixtures/sort-fields/07/result.json +22 -0
- package/test-fixtures/sort-fields/08/input.json +29 -0
- package/test-fixtures/sort-fields/08/metadata.json +5 -0
- package/test-fixtures/sort-fields/08/result.json +29 -0
- package/test-fixtures/sort-fields/09/input.json +41 -0
- package/test-fixtures/sort-fields/09/metadata.json +5 -0
- package/test-fixtures/sort-fields/09/result.json +42 -0
- package/test-fixtures/sort-fields/10/input.json +54 -0
- package/test-fixtures/sort-fields/10/metadata.json +5 -0
- package/test-fixtures/sort-fields/10/result.json +53 -0
- package/test-fixtures/sort-subfields/f02/expectedResult.json +26 -0
- package/test-fixtures/sort-subfields/f02/metadata.json +7 -0
- package/test-fixtures/sort-subfields/f02/record.json +25 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
2
|
import {fieldToChain, sameField} from './removeDuplicateDataFields';
|
|
3
3
|
import {fieldGetOccurrenceNumberPairs, fieldHasValidSubfield6, fieldSevenToOneOccurrenceNumber, fieldsToNormalizedString} from './subfield6Utils';
|
|
4
|
-
import {fieldsToString, fieldToString, nvdebug} from './utils';
|
|
4
|
+
import {fieldHasSubfield, fieldsToString, fieldToString, nvdebug, uniqArray} from './utils';
|
|
5
5
|
import {fieldHasValidSubfield8} from './subfield8Utils';
|
|
6
6
|
import {encodingLevelIsBetterThanPrepublication, getEncodingLevel} from './prepublicationUtils';
|
|
7
7
|
import {cloneAndNormalizeFieldForComparison} from './normalizeFieldForComparison';
|
|
@@ -42,49 +42,56 @@ export default function () {
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
function deriveInferiorChains(fields, record) {
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
//nvdebug(`======= GOT ${fields.length} FIELDS TO CHAINIFY`);
|
|
46
|
+
const hash = {};
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
fields.forEach(field => fieldDeriveChainDeletables(field));
|
|
48
|
+
fields.forEach(f => fieldToChainToDeletables(f));
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
return hash;
|
|
51
|
+
|
|
52
|
+
//nvdebug(`WP1: GOT ${todoList.length} CHAINS`);
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
// here we map deletableStringObject[str] => field. The idea is to help debugging. We don't actually need the field object...
|
|
56
|
+
//return deriveChainDeletables(todoList);
|
|
57
|
+
|
|
58
|
+
function fieldToChainToDeletables(field) {
|
|
52
59
|
const chain = fieldToChain(field, record);
|
|
53
|
-
if (chain.length
|
|
60
|
+
if (chain.length < 2) {
|
|
54
61
|
return;
|
|
55
62
|
}
|
|
56
63
|
const chainAsString = fieldsToNormalizedString(chain, 0, true, true);
|
|
64
|
+
const arr = deriveChainDeletables([chainAsString]);
|
|
65
|
+
//nvdebug(`GOT ${arr.length} DELETABLES FOR ${chainAsString}`);
|
|
66
|
+
arr.forEach(val => {
|
|
67
|
+
if (!(val in hash)) { // eslint-disable-line functional/no-conditional-statements
|
|
68
|
+
hash[val] = field; // eslint-disable-line functional/immutable-data
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
57
72
|
|
|
58
|
-
|
|
73
|
+
function deriveChainDeletables(todoList, deletables = []) {
|
|
74
|
+
const [chainAsString, ...stillToDo] = todoList;
|
|
75
|
+
if (chainAsString === undefined) {
|
|
76
|
+
return deletables;
|
|
77
|
+
}
|
|
59
78
|
|
|
60
79
|
// Fix MRA-476 (part 1): one $6 value can be worse than the other
|
|
61
|
-
|
|
62
|
-
while (tmp.match(/ ‡6 [0-9X][0-9][0-9]-(?:XX|[0-9]+)\/[^ ]+/u)) {
|
|
63
|
-
tmp = tmp.replace(/( ‡6 [0-9X][0-9][0-9]-(?:XX|[0-9]+))\/[^ ]+/u, '$1');
|
|
64
|
-
//nvdebug(`FFS: ${tmp}`);
|
|
65
|
-
deletableStringsObject[tmp] = field;
|
|
66
|
-
}
|
|
80
|
+
const withoutScriptIdentificationCode = chainAsString.replace(/( ‡6 [0-9X][0-9][0-9]-(?:XX|[0-9]+))\/[^ ]+/u, '$1'); // eslint-disable-line prefer-named-capture-group
|
|
67
81
|
|
|
68
82
|
// Remove keepless versions:
|
|
69
|
-
|
|
70
|
-
while (tmp.match(/ ‡9 [A-Z]+<KEEP>/)) {
|
|
71
|
-
tmp = tmp.replace(/ ‡9 [A-Z]+<KEEP>/, '');
|
|
72
|
-
deletableStringsObject[tmp] = field;
|
|
73
|
-
//nvdebug(`FFS: ${tmp}`);
|
|
74
|
-
}
|
|
83
|
+
const keepless = chainAsString.replace(/ ‡9 [A-Z]+<KEEP>/u, '');
|
|
75
84
|
|
|
76
85
|
// MRA-433: 490 ind1=1 vs ind1=0: remove latter (luckily no 2nd indicator etc)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
const linked490Ind1 = chainAsString.replace(/^490 1/u, '490 0').replace(/\t880 1/ug, '\t880 0');
|
|
87
|
+
const arr = [withoutScriptIdentificationCode, keepless, linked490Ind1].filter(val => val !== chainAsString);
|
|
88
|
+
if (arr.length > 0) {
|
|
89
|
+
return deriveChainDeletables([...stillToDo, ...arr], [...deletables, ...arr]);
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
return deriveChainDeletables(stillToDo, deletables);
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
/* eslint-enable */
|
|
87
|
-
return deletableStringsObject;
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
function isRelevantChain6(field, record) {
|
|
@@ -102,13 +109,8 @@ function isRelevantChain6(field, record) {
|
|
|
102
109
|
return false;
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
field.tmpInferiorId = 666;
|
|
108
|
-
const result = chain[0].tmpInferiorId === 666 ? true : false;
|
|
109
|
-
delete field.tmpInferiorId;
|
|
110
|
-
/* eslint-enable */
|
|
111
|
-
return result;
|
|
112
|
+
// Check whether our field is the head of a chain:
|
|
113
|
+
return sameField(field, chain[0]);
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
export function removeInferiorChains(record, fix = true) {
|
|
@@ -122,13 +124,43 @@ export function removeInferiorChains(record, fix = true) {
|
|
|
122
124
|
return [];
|
|
123
125
|
}
|
|
124
126
|
|
|
125
|
-
nvdebug(`removeInferiorChains() has ${fields.length} fields-in-chain(s), and a list of ${nChains} deletable(s)`);
|
|
127
|
+
//nvdebug(`removeInferiorChains() has ${fields.length} fields-in-chain(s), and a list of ${nChains} deletable(s)`);
|
|
128
|
+
|
|
129
|
+
return innerRemoveInferiorChains(fields);
|
|
130
|
+
|
|
131
|
+
function innerRemoveInferiorChains(fields, deletedStringsArray = []) {
|
|
132
|
+
const [currField, ...remainingFields] = fields;
|
|
133
|
+
|
|
134
|
+
if (currField === undefined) {
|
|
135
|
+
return deletedStringsArray;
|
|
136
|
+
}
|
|
126
137
|
|
|
138
|
+
const chain = fieldToChain(currField, record);
|
|
139
|
+
if (chain.length === 0 || !sameField(currField, chain[0])) {
|
|
140
|
+
return innerRemoveInferiorChains(remainingFields, deletedStringsArray);
|
|
141
|
+
}
|
|
127
142
|
|
|
128
|
-
|
|
143
|
+
const chainAsString = fieldsToNormalizedString(chain, 0, true, true);
|
|
144
|
+
if (!(chainAsString in deletableChainsAsKeys)) {
|
|
145
|
+
return innerRemoveInferiorChains(remainingFields, deletedStringsArray);
|
|
146
|
+
}
|
|
129
147
|
|
|
130
|
-
|
|
131
|
-
|
|
148
|
+
const triggeringField = deletableChainsAsKeys[chainAsString];
|
|
149
|
+
const triggeringChain = fieldToChain(triggeringField, record);
|
|
150
|
+
|
|
151
|
+
// If the inferior (deletable) chain is 1XX-based, convert the triggering better chain from 7XX to 1XX:
|
|
152
|
+
if (chainContains1XX(chain)) { // eslint-disable-line functional/no-conditional-statements
|
|
153
|
+
triggeringChain.forEach(f => sevenToOne(f, triggeringChain));
|
|
154
|
+
}
|
|
155
|
+
//nvdebug(`iRIS6C: ${chainAsString}`);
|
|
156
|
+
const deletedString = fieldsToString(chain);
|
|
157
|
+
const message = `DEL: '${deletedString}' REASON: '${fieldsToString(triggeringChain)}'`;
|
|
158
|
+
if (fix) { // eslint-disable-line functional/no-conditional-statements
|
|
159
|
+
//nvdebug(`INFERIOR $6 CHAIN REMOVAL: ${message}}`, debug);
|
|
160
|
+
chain.forEach(field => record.removeField(field));
|
|
161
|
+
}
|
|
162
|
+
return innerRemoveInferiorChains(remainingFields, [...deletedStringsArray, message]);
|
|
163
|
+
}
|
|
132
164
|
|
|
133
165
|
function chainContains1XX(chain) {
|
|
134
166
|
return chain.some(f => f.tag.substring(0, 1) === '1');
|
|
@@ -146,150 +178,116 @@ export function removeInferiorChains(record, fix = true) {
|
|
|
146
178
|
pairs.forEach(pairedField => fieldSevenToOneOccurrenceNumber(pairedField));
|
|
147
179
|
}
|
|
148
180
|
|
|
149
|
-
|
|
150
|
-
const chain = fieldToChain(field, record);
|
|
151
|
-
if (chain.length === 0 || !sameField(field, chain[0])) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
181
|
+
}
|
|
154
182
|
|
|
155
|
-
const chainAsString = fieldsToNormalizedString(chain, 0, true, true);
|
|
156
|
-
if (chainAsString in deletableChainsAsKeys) {
|
|
157
|
-
const triggeringField = deletableChainsAsKeys[chainAsString];
|
|
158
|
-
const triggeringChain = fieldToChain(triggeringField, record);
|
|
159
183
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const message = `DEL: '${deletedString}' REASON: '${fieldsToString(triggeringChain)}'`;
|
|
167
|
-
deletedStringsArray.push(message);
|
|
168
|
-
if (fix) {
|
|
169
|
-
nvdebug(`INFERIOR $6 CHAIN REMOVAL: ${message}}`, debug);
|
|
170
|
-
chain.forEach(currField => record.removeField(currField));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
184
|
+
function getIdentifierlessAndKeeplessSubsets(fieldAsString) {
|
|
185
|
+
// The rules below are not perfect (in complex cases they don't catch all permutations), but good enough:
|
|
186
|
+
// Remove identifier(s) (MELKEHITYS-2383-ish):
|
|
187
|
+
|
|
188
|
+
const identifierlessString = fieldAsString.replace(/ ‡[01] [^‡]+($| ‡)/u, '$1'); // eslint-disable-line prefer-named-capture-group
|
|
189
|
+
const keeplessString = fieldAsString.replace(/ ‡9 [A-Z]+<KEEP>/u, '');
|
|
174
190
|
|
|
175
|
-
|
|
176
|
-
return deletedStringsArray;
|
|
191
|
+
return [identifierlessString, keeplessString].filter(val => val !== fieldAsString);
|
|
177
192
|
}
|
|
178
193
|
|
|
179
|
-
function deriveIndividualDeletables490(
|
|
194
|
+
function deriveIndividualDeletables490(todoList, deletables = []) {
|
|
195
|
+
const [fieldAsString, ...stillToDo] = todoList;
|
|
196
|
+
if (fieldAsString === undefined) {
|
|
197
|
+
return deletables;
|
|
198
|
+
}
|
|
199
|
+
//nvdebug(`PROCESS ${fieldAsString}`);
|
|
180
200
|
if (!fieldAsString.match(/^490/u)) {
|
|
181
|
-
return
|
|
201
|
+
return deriveIndividualDeletables490(stillToDo, deletables);
|
|
182
202
|
}
|
|
183
203
|
|
|
184
|
-
/* eslint-disable */
|
|
185
|
-
let deletable490s = [];
|
|
186
|
-
|
|
187
204
|
// $6-less version (keep this first)
|
|
188
|
-
|
|
189
|
-
if ( tmp !== fieldAsString) {
|
|
190
|
-
fieldAsString = tmp; // NB! Carry on with $6-less version!
|
|
191
|
-
deletable490s.push(tmp);
|
|
192
|
-
}
|
|
205
|
+
const sixless = fieldAsString.replace(/ ‡6 [^‡]+ ‡/u, ' ‡');
|
|
193
206
|
|
|
194
207
|
// Without final $v or $x:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
208
|
+
const withoutFinalVOrX = fieldAsString.replace(/ *[;,] ‡[vx] [^‡]+$/u, '');
|
|
209
|
+
// Add intermediate $x-less version
|
|
210
|
+
const xless = fieldAsString.replace(/, ‡x [^‡]+(, ‡x| ; ‡v)/u, '$1'); // eslint-disable-line prefer-named-capture-group
|
|
199
211
|
|
|
200
|
-
// Add
|
|
201
|
-
|
|
202
|
-
// Add final $v/$x-less version
|
|
203
|
-
if ( tmp !== fieldAsString) {
|
|
204
|
-
deletable490s.push(tmp);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Add $xv-less version
|
|
208
|
-
tmp = fieldAsString.replace(/, ‡x [^‡]+ ‡v [^‡]+$/u, '');
|
|
209
|
-
if ( tmp !== fieldAsString) {
|
|
210
|
-
deletable490s.push(tmp);
|
|
211
|
-
}
|
|
212
|
+
// Add $xv-less version (handled by recursion?)
|
|
213
|
+
const xvless = fieldAsString.replace(/, ‡x [^‡]+ ‡v [^‡]+$/u, '');
|
|
212
214
|
|
|
213
215
|
// MRA-433-ish (non-chain): 490 ind1=1 vs ind1=0: remove latter
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
deletable490s.push(tmp);
|
|
218
|
-
const arr = deriveIndividualDeletables490(tmp);
|
|
219
|
-
arr.forEach(val => deletable490s.push(val));
|
|
220
|
-
}
|
|
216
|
+
const modifiedInd2 = fieldAsString.match(/^490 1/u) ? `490 0${fieldAsString.substring(5)}` : fieldAsString;
|
|
217
|
+
|
|
218
|
+
const arr = [sixless, withoutFinalVOrX, xless, xvless, modifiedInd2].filter(val => val !== fieldAsString);
|
|
221
219
|
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
nvdebug(
|
|
220
|
+
/*
|
|
221
|
+
if (arr.length) { // eslint-disable-line functional/no-conditional-statements
|
|
222
|
+
nvdebug(`${arr.length} derivation(s) for ${fieldAsString}`);
|
|
223
|
+
nvdebug(arr.join('\n'));
|
|
225
224
|
}
|
|
226
|
-
|
|
227
|
-
return
|
|
225
|
+
*/
|
|
226
|
+
return arr;
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
function deriveIndividualDeletables(record) {
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
const todoList = record.fields.map(f => fieldToString(f));
|
|
231
|
+
//const finishedRecord = encodingLevelIsBetterThanPrepublication(getEncodingLevel(record));
|
|
233
232
|
|
|
234
|
-
const
|
|
233
|
+
const deletableStringsArray = processTodoList(todoList);
|
|
235
234
|
|
|
236
|
-
|
|
235
|
+
return uniqArray(deletableStringsArray);
|
|
237
236
|
|
|
238
|
-
function
|
|
239
|
-
const
|
|
237
|
+
function processTodoList(thingsToDo, deletables = []) {
|
|
238
|
+
const [currString, ...stillToDo] = thingsToDo;
|
|
239
|
+
|
|
240
|
+
if (currString === undefined) {
|
|
241
|
+
return deletables;
|
|
242
|
+
}
|
|
240
243
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
deletableStringsArray.push(tmp);
|
|
244
|
+
if (currString.match(/^[1678]00/u)) {
|
|
245
|
+
// Proof-of-concpet rule. Should be improved eventually...
|
|
246
|
+
if (currString.match(/, ‡e [^‡]+\.$/u)) {
|
|
247
|
+
const tmp = currString.replace(/, ‡e [^‡]+\.$/u, '.');
|
|
248
|
+
return processTodoList([tmp, ...stillToDo], [...deletables, tmp]);
|
|
247
249
|
}
|
|
248
250
|
}
|
|
249
251
|
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
deletableStringsArray.push(tmp);
|
|
259
|
-
}
|
|
260
|
-
//nvdebug(`505 ORIGINAL: '${fieldAsString}'`)
|
|
261
|
-
//nvdebug(`505 DERIVATE: '${tmp}'`)
|
|
252
|
+
if (currString.match(/^505 .0.*-- ‡t/u)) { // MRA-413-ish
|
|
253
|
+
const tmp = currString.replace(/ -- ‡t /gu, ' -- '). // remove non-initial $t subfields
|
|
254
|
+
replace(/ ‡[rg] /gu, ' '). // remove $r and $g subfields
|
|
255
|
+
replace(/ ‡t /u, ' ‡a '). // change first $t to $a
|
|
256
|
+
// ind2: '1' => '#':
|
|
257
|
+
replace(/^505 (.)0/u, '505 $1#'); // eslint-disable-line prefer-named-capture-group
|
|
258
|
+
if (tmp !== currString) {
|
|
259
|
+
return processTodoList([tmp, ...stillToDo], [...deletables, tmp]);
|
|
262
260
|
}
|
|
261
|
+
//nvdebug(`505 ORIGINAL: '${fieldAsString}'`)
|
|
262
|
+
//nvdebug(`505 DERIVATE: '${tmp}'`)
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
// MET-381: remove occurence number TAG-00, if TAG-NN existists
|
|
266
|
-
if (
|
|
267
|
-
tmp =
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`);
|
|
275
|
-
deletableStringsArray.push(tmp);
|
|
276
|
-
}
|
|
266
|
+
if (currString.match(/^880.* ‡6 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {
|
|
267
|
+
const tmp = currString.replace(/( ‡6 [0-9][0-9][0-9])-[0-9]+/u, '$1-00'); // eslint-disable-line prefer-named-capture-group
|
|
268
|
+
//nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`);
|
|
269
|
+
//deletableStringsArray.push(tmp);
|
|
270
|
+
if (tmp.match(/ ‡6 [0-9][0-9][0-9]-00\/[^ ]+ /u)) {
|
|
271
|
+
const tmp2 = tmp.replace(/( ‡6 [0-9][0-9][0-9]-00)[^ ]+/u, '$1'); // eslint-disable-line prefer-named-capture-group
|
|
272
|
+
//nvdebug(`MET-381: ADD TO DELETABLES: '${tmp2}'`);
|
|
273
|
+
return processTodoList(stillToDo, [...deletables, tmp, tmp2]);
|
|
277
274
|
}
|
|
275
|
+
return processTodoList(stillToDo, [...deletables, tmp]);
|
|
278
276
|
}
|
|
279
277
|
|
|
280
|
-
const d490 = deriveIndividualDeletables490(
|
|
281
|
-
d490.
|
|
278
|
+
const d490 = deriveIndividualDeletables490([currString]);
|
|
279
|
+
if (d490.length) {
|
|
280
|
+
return processTodoList([...stillToDo, ...d490], [...deletables, ...d490]);
|
|
281
|
+
}
|
|
282
|
+
// d490.forEach(str => deletables.push(str)); // eslint-disable-line functional/immutable-data
|
|
282
283
|
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
tmp = tmp.replace(/ ‡9 [A-Z]+<KEEP>/u, '');
|
|
287
|
-
deletableStringsArray.push(tmp);
|
|
284
|
+
const subsets = getIdentifierlessAndKeeplessSubsets(currString); // eslint-disable-line no-param-reassign
|
|
285
|
+
if (subsets.length) {
|
|
286
|
+
return processTodoList([...stillToDo, ...subsets], [...deletables, ...subsets]);
|
|
288
287
|
}
|
|
289
288
|
|
|
289
|
+
return processTodoList(stillToDo, deletables);
|
|
290
290
|
}
|
|
291
|
-
/* eslint-enable */
|
|
292
|
-
return deletableStringsArray; // we should do uniq!
|
|
293
291
|
|
|
294
292
|
}
|
|
295
293
|
|
|
@@ -298,32 +296,31 @@ function fieldToNormalizedString(field) {
|
|
|
298
296
|
return fieldToString(normalizedField);
|
|
299
297
|
}
|
|
300
298
|
|
|
301
|
-
function deriveIndividualNormalizedDeletables(record) {
|
|
302
|
-
/* eslint-disable */
|
|
303
|
-
let deletableNormalizedStringsArray = [];
|
|
304
|
-
|
|
299
|
+
function deriveIndividualNormalizedDeletables(record) { // MET-461:
|
|
305
300
|
const recordIsFinished = encodingLevelIsBetterThanPrepublication(getEncodingLevel(record));
|
|
301
|
+
if (!recordIsFinished) {
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
const relevantFields = record.fields.filter(f => ['245', '246'].includes(f.tag) && fieldHasSubfield(f, 'a'));
|
|
306
305
|
|
|
307
|
-
|
|
306
|
+
return deriveDeletable946s(relevantFields);
|
|
308
307
|
|
|
309
|
-
function
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// MET-461:
|
|
314
|
-
if (recordIsFinished && ['245', '246'].includes(field.tag) && fieldAsNormalizedString.match(/ ‡a /u)) {
|
|
315
|
-
tmp = fieldAsNormalizedString;
|
|
316
|
-
tmp = tmp.replace(/^(...) ../u, '946 ##'); // Ind
|
|
317
|
-
tmp = tmp.replace(" ‡a ", " ‡i nimeke onixissa ‡a "); // NB! This is added in the normalized lower-cased form!
|
|
318
|
-
tmp = tmp.replace(/(?: \/)? ‡c[^‡]+$/u, ''); // Can $c be non-last?
|
|
319
|
-
deletableNormalizedStringsArray.push(tmp);
|
|
320
|
-
deletableNormalizedStringsArray.push(`${tmp} ‡5 MELINDA`); // MET-461 comment. NB! $5 is never normalized
|
|
308
|
+
function deriveDeletable946s(fields, results = []) {
|
|
309
|
+
const [currField, ...remainingFields] = fields;
|
|
310
|
+
if (currField === undefined) {
|
|
311
|
+
return results;
|
|
321
312
|
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/* eslint-enable */
|
|
325
|
-
return deletableNormalizedStringsArray; // we should do uniq!
|
|
326
313
|
|
|
314
|
+
const fieldAsNormalizedString = fieldToNormalizedString(currField);
|
|
315
|
+
const tmp = fieldAsNormalizedString.replace(/^(?:...) ../u, '946 ##'). // <= Change tag to 946 and indicators to '##'
|
|
316
|
+
replace(' ‡a ', ' ‡i nimeke onixissa ‡a '). // Add $i before $a. NB! This is added in the normalized lower-cased form!
|
|
317
|
+
replace(/(?: \/)? ‡c[^‡]+$/u, ''); // Remove $c. (Can $c be non-last?)
|
|
318
|
+
const candArray = [tmp, `${tmp} ‡5 MELINDA`].filter(val => val !== fieldAsNormalizedString);
|
|
319
|
+
if (candArray.length) {
|
|
320
|
+
return deriveDeletable946s(remainingFields, [...results, ...candArray]);
|
|
321
|
+
}
|
|
322
|
+
return deriveDeletable946s(remainingFields, results);
|
|
323
|
+
}
|
|
327
324
|
}
|
|
328
325
|
|
|
329
326
|
export function removeIndividualInferiorDatafields(record, fix = true) { // No $6 nor $8 in field
|
|
@@ -339,7 +336,7 @@ export function removeIndividualInferiorDatafields(record, fix = true) { // No $
|
|
|
339
336
|
|
|
340
337
|
if (fix) { // eslint-disable-line functional/no-conditional-statements
|
|
341
338
|
hits.forEach(field => {
|
|
342
|
-
nvdebug(`Remove inferior field: ${fieldToString(field)}
|
|
339
|
+
//nvdebug(`Remove inferior field: ${fieldToString(field)}`, debug);
|
|
343
340
|
record.removeField(field);
|
|
344
341
|
});
|
|
345
342
|
}
|
|
@@ -367,8 +364,8 @@ export function removeInferiorDatafields(record, fix = true) {
|
|
|
367
364
|
const removables6 = removeInferiorChains(record, fix); // Lone subfield $6 chains
|
|
368
365
|
// HOW TO HANDLE $6+$8 combos? Skipping is relatively OK.
|
|
369
366
|
|
|
370
|
-
nvdebug(`REMOVABLES:\n ${removables.join('\n ')}
|
|
371
|
-
nvdebug(`REMOVABLES 6:\n ${removables6.join('\n ')}
|
|
367
|
+
nvdebug(`REMOVABLES:\n ${removables.join('\n ')}`, debug);
|
|
368
|
+
nvdebug(`REMOVABLES 6:\n ${removables6.join('\n ')}`, debug);
|
|
372
369
|
|
|
373
370
|
const removablesAll = removables.concat(removables6); //.concat(removables8);
|
|
374
371
|
|