@natlibfi/marc-record-validators-melinda 9.0.5-alpha.1 → 9.0.7-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/isbn-issn.js +126 -87
- package/dist/isbn-issn.js.map +1 -1
- package/dist/isbn-issn.spec.js +70 -15
- package/dist/isbn-issn.spec.js.map +1 -1
- package/dist/punctuation/index.js +5 -1
- package/dist/punctuation/index.js.map +1 -1
- package/dist/resolvable-ext-references-melinda.spec.js +3 -2
- package/dist/resolvable-ext-references-melinda.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/isbn-issn.js +106 -80
- package/src/isbn-issn.spec.js +38 -19
- package/src/punctuation/index.js +5 -1
- package/src/resolvable-ext-references-melinda.spec.js +2 -1
package/dist/isbn-issn.js
CHANGED
|
@@ -49,88 +49,87 @@ var _default = ({
|
|
|
49
49
|
description: 'Validates ISBN and ISSN values'
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
+
function stringHasSpace(str) {
|
|
53
|
+
return str.indexOf(' ') > -1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function trimSpaces(value) {
|
|
57
|
+
return value.replace(/^\s+/u, '').replace(/\s+$/u, '').replace(/\s+/gu, ' ');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isMultiWord(inputString) {
|
|
61
|
+
const trimmedString = trimSpaces(inputString);
|
|
62
|
+
return stringHasSpace(trimmedString);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getFirstWord(inputString) {
|
|
66
|
+
const trimmedString = trimSpaces(inputString);
|
|
67
|
+
const arr = trimmedString.split(' ');
|
|
68
|
+
return arr[0];
|
|
69
|
+
}
|
|
70
|
+
|
|
52
71
|
function invalidISBN(isbn) {
|
|
53
|
-
|
|
54
|
-
// Check the first word in string:
|
|
55
|
-
if (isbn.indexOf(' ') > -1) {
|
|
56
|
-
// const arr = isbn.split(' ');
|
|
57
|
-
// console.info(`invalidISBN(): Check '${arr[0]}' instead of '${isbn}'`); // eslint-disable-line no-console
|
|
58
|
-
// return invalidISBN(arr[0]);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
72
|
+
const isbnOnly = getFirstWord(isbn);
|
|
61
73
|
|
|
62
|
-
const auditedIsbn = _isbn.default.audit(
|
|
74
|
+
const auditedIsbn = _isbn.default.audit(isbnOnly);
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
76
|
+
return !auditedIsbn.validIsbn;
|
|
77
|
+
}
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
function invalidSubfield(subfield) {
|
|
80
|
+
if (subfield.code !== 'a') {
|
|
81
|
+
return false;
|
|
68
82
|
}
|
|
69
83
|
|
|
70
|
-
return
|
|
84
|
+
return invalidISBN(subfield.value) || isMultiWord(subfield.value);
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
function invalidField020(field) {
|
|
74
|
-
if (field.subfields && field.subfields.some(sf =>
|
|
88
|
+
if (field.subfields && field.subfields.some(sf => invalidSubfield(sf))) {
|
|
75
89
|
return true;
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
return false;
|
|
93
|
+
}
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (invalidISBN(subfield.value)) {
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
|
|
95
|
+
function subfieldsIsbnRequiresHyphenation(subfield) {
|
|
96
|
+
if (!hyphenateISBN || !['a', 'z'].includes(subfield.code)) {
|
|
89
97
|
return false;
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
if (subfield.code !== 'z' || !hyphenateISBN || invalidISBN(subfield.value)) {
|
|
94
|
-
return false;
|
|
95
|
-
} // We are only interested in $z field if it is valid ISBN that requires hyphenation:
|
|
100
|
+
const isbn = getFirstWord(subfield.value);
|
|
96
101
|
|
|
102
|
+
if (subfield.code === 'a') {
|
|
103
|
+
return requiresHyphenation(isbn);
|
|
104
|
+
} // $z is a bit hacky: hyphenation is required only iff valid and no '-' chars
|
|
97
105
|
|
|
98
|
-
return subfield.value.indexOf('-') === -1;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
if (subfield.code !== 'a' && subfield.code !== 'z') {
|
|
107
|
+
if (isbn.indexOf('-') > -1) {
|
|
104
108
|
return false;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
|
-
return
|
|
111
|
+
return !invalidISBN(isbn);
|
|
108
112
|
|
|
109
113
|
function requiresHyphenation(isbn) {
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
if (!hyphenateISBN) {
|
|
115
|
+
return false;
|
|
116
|
+
} // Handle old notation such as "978-952-396-001-5 (nid.)"
|
|
113
117
|
|
|
114
|
-
return requiresHyphenation(arr[0]);
|
|
115
|
-
}
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
const isbn2 = getFirstWord(isbn);
|
|
120
|
+
|
|
121
|
+
if (invalidISBN(isbn2)) {
|
|
118
122
|
return false;
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
|
|
125
|
+
const parsedIsbn = _isbn.default.parse(isbn2); // Return true only if existing ISBN is a valid and hyphenated 10 or 13 digit ISBN:
|
|
122
126
|
|
|
123
|
-
const parsedIsbn = _isbn.default.parse(isbn);
|
|
124
|
-
|
|
125
|
-
if (hyphenateISBN) {
|
|
126
|
-
return !(isbn === parsedIsbn.isbn10h || isbn === parsedIsbn.isbn13h);
|
|
127
|
-
}
|
|
128
127
|
|
|
129
|
-
return
|
|
128
|
+
return !(isbn2 === parsedIsbn.isbn10h || isbn2 === parsedIsbn.isbn13h);
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
function
|
|
132
|
+
function getRelevantFields(record) {
|
|
134
133
|
//return record.get(/^(?:020|022)$/u).filter(field => {
|
|
135
134
|
return record.fields.filter(field => {
|
|
136
135
|
if (!field.subfields) {
|
|
@@ -140,10 +139,11 @@ var _default = ({
|
|
|
140
139
|
|
|
141
140
|
if (field.tag === '020') {
|
|
142
141
|
if (invalidField020(field)) {
|
|
142
|
+
// checks multiwordness
|
|
143
143
|
return true;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
return
|
|
146
|
+
return fieldsIsbnRequiresHyphenation(field);
|
|
147
147
|
} // Check ISSN:
|
|
148
148
|
|
|
149
149
|
|
|
@@ -159,8 +159,8 @@ var _default = ({
|
|
|
159
159
|
return false;
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
function
|
|
163
|
-
return field.subfields && field.subfields.some(sf =>
|
|
162
|
+
function fieldsIsbnRequiresHyphenation(field) {
|
|
163
|
+
return field.subfields && field.subfields.some(sf => subfieldsIsbnRequiresHyphenation(sf));
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
function invalidField022(field) {
|
|
@@ -181,7 +181,7 @@ var _default = ({
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
function validate(record) {
|
|
184
|
-
const fields =
|
|
184
|
+
const fields = getRelevantFields(record);
|
|
185
185
|
|
|
186
186
|
if (fields.length === 0) {
|
|
187
187
|
return {
|
|
@@ -200,6 +200,15 @@ var _default = ({
|
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
const subfieldZ = field.subfields.find(sf => sf.code === 'z');
|
|
204
|
+
|
|
205
|
+
if (subfieldZ) {
|
|
206
|
+
return {
|
|
207
|
+
name: 'ISBN (subfield Z)',
|
|
208
|
+
value: subfieldZ.value
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
203
212
|
return {
|
|
204
213
|
name: 'ISBN',
|
|
205
214
|
value: undefined
|
|
@@ -236,7 +245,7 @@ var _default = ({
|
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
function fix(record) {
|
|
239
|
-
|
|
248
|
+
getRelevantFields(record).forEach(field => {
|
|
240
249
|
if (field.tag === '020') {
|
|
241
250
|
field.subfields.forEach(subfield => fixField020Subfield(field, subfield));
|
|
242
251
|
return;
|
|
@@ -256,67 +265,97 @@ var _default = ({
|
|
|
256
265
|
record.removeSubfield(subfield, field);
|
|
257
266
|
}
|
|
258
267
|
});
|
|
259
|
-
/*
|
|
260
|
-
function trimISBN(value) {
|
|
261
|
-
return trimSpaces(value.replace(/\s$/gu, '')); // handle "1234567890 (nid.)" => "1234567890" as well as spaces
|
|
262
|
-
}
|
|
263
|
-
*/
|
|
264
268
|
|
|
265
269
|
function fixField020Subfield(field, subfield) {
|
|
266
|
-
|
|
270
|
+
split020A(); // subfield and field are in the scope
|
|
271
|
+
|
|
272
|
+
addHyphens(subfield);
|
|
273
|
+
handleInvalidIsbn(field, subfield); // remove 020$a, add 020$z, Do this last, as it uses deletion
|
|
274
|
+
|
|
275
|
+
return;
|
|
276
|
+
|
|
277
|
+
function addHyphens(subfield) {
|
|
278
|
+
if (!subfieldsIsbnRequiresHyphenation(subfield)) {
|
|
279
|
+
return;
|
|
280
|
+
} // ISBN is valid but is missing hyphens
|
|
267
281
|
|
|
268
|
-
if (invalidISBN(subfield.value) || subfieldRequiresHyphenation(subfield)) {
|
|
269
|
-
console.info(` fixField020Subfield ${subfield.code} '${subfield.value}'`); // eslint-disable-line no-console
|
|
270
|
-
// ISBN is valid but is missing hyphens
|
|
271
282
|
|
|
272
283
|
const normalizedValue = normalizeIsbnValue(subfield.value);
|
|
273
284
|
|
|
274
285
|
if (normalizedValue !== undefined) {
|
|
275
286
|
// eslint-disable-line functional/no-conditional-statement
|
|
276
287
|
subfield.value = normalizedValue; // eslint-disable-line functional/immutable-data
|
|
277
|
-
} else if (subfield.code === 'a' && handleInvalid) {
|
|
278
|
-
// eslint-disable-line functional/no-conditional-statement
|
|
279
|
-
// $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)
|
|
280
|
-
field.subfields.push({
|
|
281
|
-
code: 'z',
|
|
282
|
-
value: subfield.value
|
|
283
|
-
}); // eslint-disable-line functional/immutable-data
|
|
284
|
-
|
|
285
|
-
record.removeSubfield(subfield, field);
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
|
|
289
|
-
|
|
291
|
+
function handleInvalidIsbn(field, subfield) {
|
|
292
|
+
if (subfield.code !== 'a' || !handleInvalid) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
290
295
|
|
|
291
|
-
|
|
292
|
-
//const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...
|
|
293
|
-
const auditResult = _isbn.default.audit(trimmedValue);
|
|
296
|
+
const head = getFirstWord(subfield.value);
|
|
294
297
|
|
|
295
|
-
if (
|
|
296
|
-
|
|
298
|
+
if (!invalidISBN(head)) {
|
|
299
|
+
return;
|
|
300
|
+
} // $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)
|
|
297
301
|
|
|
298
|
-
if (hyphenateISBN) {
|
|
299
|
-
// eslint-disable-line functional/no-conditional-statement
|
|
300
|
-
return trimmedValue.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h; // eslint-disable-line functional/immutable-data
|
|
301
|
-
} // Just trim
|
|
302
302
|
|
|
303
|
+
field.subfields.push({
|
|
304
|
+
code: 'z',
|
|
305
|
+
value: subfield.value
|
|
306
|
+
}); // eslint-disable-line functional/immutable-data
|
|
307
|
+
|
|
308
|
+
record.removeSubfield(subfield, field);
|
|
309
|
+
}
|
|
303
310
|
|
|
304
|
-
|
|
311
|
+
function split020A() {
|
|
312
|
+
// Move non-initial words from $a to $q:
|
|
313
|
+
if (subfield.code !== 'a') {
|
|
314
|
+
return;
|
|
305
315
|
}
|
|
306
316
|
|
|
307
|
-
|
|
317
|
+
const value = trimSpaces(subfield.value);
|
|
318
|
+
const position = value.indexOf(' ');
|
|
319
|
+
|
|
320
|
+
if (position === -1) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const head = getFirstWord(value);
|
|
325
|
+
|
|
326
|
+
if (invalidISBN(head)) {
|
|
327
|
+
// Don't split, if first word ain't ISBN
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const tail = value.substring(position + 1);
|
|
332
|
+
subfield.value = head; // eslint-disable-line functional/immutable-data
|
|
333
|
+
|
|
334
|
+
field.subfields.push({
|
|
335
|
+
code: 'q',
|
|
336
|
+
value: tail
|
|
337
|
+
}); // eslint-disable-line functional/immutable-data
|
|
308
338
|
}
|
|
309
339
|
|
|
310
340
|
function normalizeIsbnValue(value) {
|
|
311
|
-
const trimmedValue = value
|
|
341
|
+
const trimmedValue = getFirstWord(value); //const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...
|
|
342
|
+
|
|
343
|
+
const auditResult = _isbn.default.audit(trimmedValue);
|
|
312
344
|
|
|
313
|
-
if (
|
|
314
|
-
return
|
|
345
|
+
if (!auditResult.validIsbn) {
|
|
346
|
+
return undefined;
|
|
315
347
|
}
|
|
316
348
|
|
|
317
|
-
const
|
|
349
|
+
const numbersOnly = trimmedValue.replace(/[^0-9Xx]+/ug, '');
|
|
350
|
+
|
|
351
|
+
const parsedIsbn = _isbn.default.parse(trimmedValue);
|
|
352
|
+
|
|
353
|
+
if (hyphenateISBN) {
|
|
354
|
+
// eslint-disable-line functional/no-conditional-statement
|
|
355
|
+
return numbersOnly.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h; // eslint-disable-line functional/immutable-data
|
|
356
|
+
}
|
|
318
357
|
|
|
319
|
-
return
|
|
358
|
+
return numbersOnly.length === 10 ? parsedIsbn.isbn10 : parsedIsbn.isbn13; // eslint-disable-line functional/immutable-data
|
|
320
359
|
}
|
|
321
360
|
}
|
|
322
361
|
}
|
package/dist/isbn-issn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/isbn-issn.js"],"names":["hyphenateISBN","handleInvalid","validate","fix","description","invalidISBN","isbn","indexOf","auditedIsbn","ISBN","audit","validIsbn","console","info","invalidField020","field","subfields","some","sf","invalidField020a","invalidField020z","subfield","code","value","subfieldRequiresHyphenation","requiresHyphenation","arr","split","parsedIsbn","parse","isbn10h","isbn13h","getInvalidFields","record","fields","filter","tag","fieldRequiresHyphenation","invalidField022","find","subfieldAorL","undefined","subfieldY","length","valid","map","subfieldA","name","getISSN","reduce","acc","obj","msg","messages","concat","forEach","fixField020Subfield","push","removeSubfield","normalizedValue","normalizeIsbnValue","normalizeIsbnValue2","trimmedValue","auditResult","isbn10","isbn13","replace","head"],"mappings":"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","sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* MARC record validators used in Melinda\n*\n* Copyright (c) 2014-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of marc-record-validators-melinda\n*\n* marc-record-validators-melinda program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* marc-record-validators-melinda is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Lesser General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport ISBN from 'isbn3';\nimport validateISSN from '@natlibfi/issn-verify';\n\n// handleInvalid: move invalid 020$a to 020$z, and invalid 022$a to 022$y\nexport default ({hyphenateISBN = false, handleInvalid = false} = {}) => {\n return {\n validate, fix,\n description: 'Validates ISBN and ISSN values'\n };\n\n function invalidISBN(isbn) {\n // If value contains space, it's not necessarily crap. (It's typically something like \"1234567890 (nid.)\".)\n // Check the first word in string:\n if (isbn.indexOf(' ') > -1) {\n // const arr = isbn.split(' ');\n // console.info(`invalidISBN(): Check '${arr[0]}' instead of '${isbn}'`); // eslint-disable-line no-console\n // return invalidISBN(arr[0]);\n return true;\n }\n\n const auditedIsbn = ISBN.audit(isbn);\n if (!auditedIsbn.validIsbn) {\n console.info(`Invalid ISBN detected: ${isbn}`); // eslint-disable-line no-console\n return true;\n }\n return false;\n }\n\n\n function invalidField020(field) {\n if (field.subfields && field.subfields.some(sf => invalidField020a(sf) || invalidField020z(sf))) {\n return true;\n }\n return false;\n\n function invalidField020a(subfield) {\n if (subfield.code !== 'a') {\n return false;\n }\n if (invalidISBN(subfield.value)) {\n return true;\n }\n return false;\n }\n\n function invalidField020z(subfield) {\n if (subfield.code !== 'z' || !hyphenateISBN || invalidISBN(subfield.value)) {\n return false;\n }\n // We are only interested in $z field if it is valid ISBN that requires hyphenation:\n return subfield.value.indexOf('-') === -1;\n }\n }\n\n function subfieldRequiresHyphenation(subfield) {\n if (subfield.code !== 'a' && subfield.code !== 'z') {\n return false;\n }\n return requiresHyphenation(subfield.value);\n\n function requiresHyphenation(isbn) {\n if (isbn.indexOf(' ') > -1) {\n const arr = isbn.split(' ');\n console.info(`requiresHyphenation(): Check '${arr[0]}' instead of '${isbn}'`); // eslint-disable-line no-console\n return requiresHyphenation(arr[0]);\n }\n\n if (invalidISBN(isbn)) {\n return false;\n }\n console.info(`sfRH ${isbn}`); // eslint-disable-line no-console\n const parsedIsbn = ISBN.parse(isbn);\n if (hyphenateISBN) {\n return !(isbn === parsedIsbn.isbn10h || isbn === parsedIsbn.isbn13h);\n }\n return false;\n //return !(isbn === parsedIsbn.isbn10 || isbn === parsedIsbn.isbn13);\n }\n }\n\n function getInvalidFields(record) {\n //return record.get(/^(?:020|022)$/u).filter(field => {\n return record.fields.filter(field => {\n if (!field.subfields) {\n return false;\n }\n // Check ISBN:\n if (field.tag === '020') {\n if (invalidField020(field)) {\n return true;\n }\n return fieldRequiresHyphenation(field);\n }\n\n // Check ISSN:\n if (field.tag === '022') {\n if (invalidField022(field)) {\n return true;\n }\n\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n return !validateISSN(subfield.value);\n }\n return false;\n });\n\n function fieldRequiresHyphenation(field) {\n return field.subfields && field.subfields.some(sf => subfieldRequiresHyphenation(sf));\n }\n\n function invalidField022(field) {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL === undefined) {\n const subfieldY = field.subfields.find(sf => sf.code === 'y');\n if (subfieldY) {\n return false;\n }\n\n return true;\n }\n return false;\n }\n }\n\n function validate(record) {\n const fields = getInvalidFields(record);\n\n if (fields.length === 0) {\n return {valid: true};\n }\n\n return fields\n .map(field => {\n if (field.tag === '020') {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (subfieldA) {\n return {name: 'ISBN', value: subfieldA.value};\n }\n\n return {name: 'ISBN', value: undefined};\n }\n\n return {name: 'ISSN', value: getISSN()};\n\n function getISSN() {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL) {\n return subfieldAorL.value;\n }\n\n return undefined;\n }\n })\n .reduce((acc, obj) => {\n const {name, value} = obj;\n const msg = `${name} (${value}) is not valid`;\n\n return {...acc, messages: acc.messages.concat(msg)};\n }, {valid: false, messages: []});\n }\n\n\n function fix(record) {\n getInvalidFields(record).forEach(field => {\n if (field.tag === '020') {\n field.subfields.forEach(subfield => fixField020Subfield(field, subfield));\n return;\n }\n // 022 ISSN:\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n if (subfield && handleInvalid) { // eslint-disable-line functional/no-conditional-statement\n // $a/$l => $y (bit overkill to add $z and remove $a/$l instead of just renaming)\n field.subfields.push({code: 'y', value: subfield.value}); // eslint-disable-line functional/immutable-data\n record.removeSubfield(subfield, field);\n }\n });\n\n /*\n function trimISBN(value) {\n return trimSpaces(value.replace(/\\s$/gu, '')); // handle \"1234567890 (nid.)\" => \"1234567890\" as well as spaces\n }\n */\n\n function fixField020Subfield(field, subfield) {\n console.info(`fixField020Subfield ${subfield.code} '${subfield.value}'`); // eslint-disable-line no-console\n if (invalidISBN(subfield.value) || subfieldRequiresHyphenation(subfield)) {\n console.info(` fixField020Subfield ${subfield.code} '${subfield.value}'`); // eslint-disable-line no-console\n // ISBN is valid but is missing hyphens\n const normalizedValue = normalizeIsbnValue(subfield.value);\n if (normalizedValue !== undefined) { // eslint-disable-line functional/no-conditional-statement\n subfield.value = normalizedValue; // eslint-disable-line functional/immutable-data\n } else if (subfield.code === 'a' && handleInvalid) { // eslint-disable-line functional/no-conditional-statement\n // $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)\n field.subfields.push({code: 'z', value: subfield.value}); // eslint-disable-line functional/immutable-data\n record.removeSubfield(subfield, field);\n }\n }\n return;\n\n function normalizeIsbnValue2(trimmedValue) {\n //const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...\n const auditResult = ISBN.audit(trimmedValue);\n if (auditResult.validIsbn) {\n const parsedIsbn = ISBN.parse(trimmedValue);\n if (hyphenateISBN) { // eslint-disable-line functional/no-conditional-statement\n return trimmedValue.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h; // eslint-disable-line functional/immutable-data\n }\n // Just trim\n return trimmedValue.length === 10 ? parsedIsbn.isbn10 : parsedIsbn.isbn13; // eslint-disable-line functional/immutable-data\n }\n return undefined;\n }\n\n function normalizeIsbnValue(value) {\n const trimmedValue = value.replace(/^\\s+/gu, '');\n if (trimmedValue.indexOf(' ') === -1) {\n return normalizeIsbnValue2(trimmedValue);\n }\n const [head] = trimmedValue.split(' ');\n // NB! We currently drop the tail part, as it prevents us from pairing doubles. Parametrize?\n return normalizeIsbnValue2(head);\n }\n }\n }\n};\n"],"file":"isbn-issn.js"}
|
|
1
|
+
{"version":3,"sources":["../src/isbn-issn.js"],"names":["hyphenateISBN","handleInvalid","validate","fix","description","stringHasSpace","str","indexOf","trimSpaces","value","replace","isMultiWord","inputString","trimmedString","getFirstWord","arr","split","invalidISBN","isbn","isbnOnly","auditedIsbn","ISBN","audit","validIsbn","invalidSubfield","subfield","code","invalidField020","field","subfields","some","sf","subfieldsIsbnRequiresHyphenation","includes","requiresHyphenation","isbn2","parsedIsbn","parse","isbn10h","isbn13h","getRelevantFields","record","fields","filter","tag","fieldsIsbnRequiresHyphenation","invalidField022","find","subfieldAorL","undefined","subfieldY","length","valid","map","subfieldA","name","subfieldZ","getISSN","reduce","acc","obj","msg","messages","concat","forEach","fixField020Subfield","push","removeSubfield","split020A","addHyphens","handleInvalidIsbn","normalizedValue","normalizeIsbnValue","head","position","tail","substring","trimmedValue","auditResult","numbersOnly","isbn10","isbn13"],"mappings":"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","sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* MARC record validators used in Melinda\n*\n* Copyright (c) 2014-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of marc-record-validators-melinda\n*\n* marc-record-validators-melinda program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* marc-record-validators-melinda is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Lesser General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport ISBN from 'isbn3';\nimport validateISSN from '@natlibfi/issn-verify';\n\n// handleInvalid: move invalid 020$a to 020$z, and invalid 022$a to 022$y\nexport default ({hyphenateISBN = false, handleInvalid = false} = {}) => {\n return {\n validate, fix,\n description: 'Validates ISBN and ISSN values'\n };\n\n function stringHasSpace(str) {\n return str.indexOf(' ') > -1;\n }\n\n function trimSpaces(value) {\n return value.replace(/^\\s+/u, '').replace(/\\s+$/u, '').replace(/\\s+/gu, ' ');\n }\n\n function isMultiWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n return stringHasSpace(trimmedString);\n }\n\n function getFirstWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n const arr = trimmedString.split(' ');\n return arr[0];\n }\n\n function invalidISBN(isbn) {\n const isbnOnly = getFirstWord(isbn);\n const auditedIsbn = ISBN.audit(isbnOnly);\n return !auditedIsbn.validIsbn;\n }\n\n function invalidSubfield(subfield) {\n if (subfield.code !== 'a') {\n return false;\n }\n return invalidISBN(subfield.value) || isMultiWord(subfield.value);\n }\n\n\n function invalidField020(field) {\n if (field.subfields && field.subfields.some(sf => invalidSubfield(sf))) {\n return true;\n }\n return false;\n }\n\n function subfieldsIsbnRequiresHyphenation(subfield) {\n if (!hyphenateISBN || !['a', 'z'].includes(subfield.code)) {\n return false;\n }\n\n const isbn = getFirstWord(subfield.value);\n if (subfield.code === 'a') {\n return requiresHyphenation(isbn);\n }\n\n // $z is a bit hacky: hyphenation is required only iff valid and no '-' chars\n if (isbn.indexOf('-') > -1) {\n return false;\n }\n return !invalidISBN(isbn);\n\n function requiresHyphenation(isbn) {\n if (!hyphenateISBN) {\n return false;\n }\n // Handle old notation such as \"978-952-396-001-5 (nid.)\"\n const isbn2 = getFirstWord(isbn);\n\n if (invalidISBN(isbn2)) {\n return false;\n }\n\n const parsedIsbn = ISBN.parse(isbn2);\n // Return true only if existing ISBN is a valid and hyphenated 10 or 13 digit ISBN:\n return !(isbn2 === parsedIsbn.isbn10h || isbn2 === parsedIsbn.isbn13h);\n }\n }\n\n function getRelevantFields(record) {\n //return record.get(/^(?:020|022)$/u).filter(field => {\n return record.fields.filter(field => {\n if (!field.subfields) {\n return false;\n }\n // Check ISBN:\n if (field.tag === '020') {\n if (invalidField020(field)) { // checks multiwordness\n return true;\n }\n return fieldsIsbnRequiresHyphenation(field);\n }\n\n // Check ISSN:\n if (field.tag === '022') {\n if (invalidField022(field)) {\n return true;\n }\n\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n return !validateISSN(subfield.value);\n }\n return false;\n });\n\n function fieldsIsbnRequiresHyphenation(field) {\n return field.subfields && field.subfields.some(sf => subfieldsIsbnRequiresHyphenation(sf));\n }\n\n function invalidField022(field) {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL === undefined) {\n const subfieldY = field.subfields.find(sf => sf.code === 'y');\n if (subfieldY) {\n return false;\n }\n\n return true;\n }\n return false;\n }\n }\n\n function validate(record) {\n const fields = getRelevantFields(record);\n\n if (fields.length === 0) {\n return {valid: true};\n }\n\n return fields\n .map(field => {\n if (field.tag === '020') {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (subfieldA) {\n return {name: 'ISBN', value: subfieldA.value};\n }\n const subfieldZ = field.subfields.find(sf => sf.code === 'z');\n if (subfieldZ) {\n return {name: 'ISBN (subfield Z)', value: subfieldZ.value};\n }\n\n return {name: 'ISBN', value: undefined};\n }\n\n return {name: 'ISSN', value: getISSN()};\n\n function getISSN() {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL) {\n return subfieldAorL.value;\n }\n\n return undefined;\n }\n })\n .reduce((acc, obj) => {\n const {name, value} = obj;\n const msg = `${name} (${value}) is not valid`;\n\n return {...acc, messages: acc.messages.concat(msg)};\n }, {valid: false, messages: []});\n }\n\n\n function fix(record) {\n getRelevantFields(record).forEach(field => {\n if (field.tag === '020') {\n field.subfields.forEach(subfield => fixField020Subfield(field, subfield));\n return;\n }\n // 022 ISSN:\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n if (subfield && handleInvalid) { // eslint-disable-line functional/no-conditional-statement\n // $a/$l => $y (bit overkill to add $z and remove $a/$l instead of just renaming)\n field.subfields.push({code: 'y', value: subfield.value}); // eslint-disable-line functional/immutable-data\n record.removeSubfield(subfield, field);\n }\n });\n\n\n function fixField020Subfield(field, subfield) {\n split020A(); // subfield and field are in the scope\n addHyphens(subfield);\n handleInvalidIsbn(field, subfield); // remove 020$a, add 020$z, Do this last, as it uses deletion\n return;\n\n function addHyphens(subfield) {\n if (!subfieldsIsbnRequiresHyphenation(subfield)) {\n return;\n }\n // ISBN is valid but is missing hyphens\n const normalizedValue = normalizeIsbnValue(subfield.value);\n if (normalizedValue !== undefined) { // eslint-disable-line functional/no-conditional-statement\n subfield.value = normalizedValue; // eslint-disable-line functional/immutable-data\n }\n }\n\n function handleInvalidIsbn(field, subfield) {\n if (subfield.code !== 'a' || !handleInvalid) {\n return;\n }\n const head = getFirstWord(subfield.value);\n if (!invalidISBN(head)) {\n return;\n }\n // $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)\n field.subfields.push({code: 'z', value: subfield.value}); // eslint-disable-line functional/immutable-data\n record.removeSubfield(subfield, field);\n }\n\n function split020A() {\n // Move non-initial words from $a to $q:\n if (subfield.code !== 'a') {\n return;\n }\n const value = trimSpaces(subfield.value);\n const position = value.indexOf(' ');\n if (position === -1) {\n return;\n }\n const head = getFirstWord(value);\n if (invalidISBN(head)) { // Don't split, if first word ain't ISBN\n return;\n }\n const tail = value.substring(position + 1);\n subfield.value = head; // eslint-disable-line functional/immutable-data\n field.subfields.push({code: 'q', value: tail}); // eslint-disable-line functional/immutable-data\n }\n\n function normalizeIsbnValue(value) {\n const trimmedValue = getFirstWord(value);\n //const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...\n const auditResult = ISBN.audit(trimmedValue);\n if (!auditResult.validIsbn) {\n return undefined;\n }\n const numbersOnly = trimmedValue.replace(/[^0-9Xx]+/ug, '');\n const parsedIsbn = ISBN.parse(trimmedValue);\n if (hyphenateISBN) { // eslint-disable-line functional/no-conditional-statement\n return numbersOnly.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h; // eslint-disable-line functional/immutable-data\n }\n return numbersOnly.length === 10 ? parsedIsbn.isbn10 : parsedIsbn.isbn13; // eslint-disable-line functional/immutable-data\n }\n }\n }\n};\n"],"file":"isbn-issn.js"}
|
package/dist/isbn-issn.spec.js
CHANGED
|
@@ -14,7 +14,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
14
14
|
*
|
|
15
15
|
* MARC record validators used in Melinda
|
|
16
16
|
*
|
|
17
|
-
* Copyright (c) 2014-
|
|
17
|
+
* Copyright (c) 2014-2022 University Of Helsinki (The National Library Of Finland)
|
|
18
18
|
*
|
|
19
19
|
* This file is part of marc-record-validators-melinda
|
|
20
20
|
*
|
|
@@ -98,6 +98,15 @@ describe('isbn-issn', () => {
|
|
|
98
98
|
code: 'a',
|
|
99
99
|
value: 'foo'
|
|
100
100
|
}]
|
|
101
|
+
}, {
|
|
102
|
+
tag: '020',
|
|
103
|
+
ind1: ' ',
|
|
104
|
+
ind2: ' ',
|
|
105
|
+
subfields: [{
|
|
106
|
+
code: 'a',
|
|
107
|
+
value: '90-68-31-372-X'
|
|
108
|
+
}] // contains an extra hyphen
|
|
109
|
+
|
|
101
110
|
}, {
|
|
102
111
|
tag: '022',
|
|
103
112
|
ind1: ' ',
|
|
@@ -151,18 +160,10 @@ describe('isbn-issn', () => {
|
|
|
151
160
|
messages: ['ISSN (undefined) is not valid']
|
|
152
161
|
});
|
|
153
162
|
});
|
|
154
|
-
it('Finds the record invalid (
|
|
163
|
+
it('Finds the record invalid (reason: multiword)', async () => {
|
|
155
164
|
const validator = await (0, _isbnIssn.default)();
|
|
156
165
|
const record = new _marcRecord.MarcRecord({
|
|
157
166
|
fields: [{
|
|
158
|
-
tag: '020',
|
|
159
|
-
ind1: ' ',
|
|
160
|
-
ind2: ' ',
|
|
161
|
-
subfields: [{
|
|
162
|
-
code: 'a',
|
|
163
|
-
value: ' 9789519155470'
|
|
164
|
-
}]
|
|
165
|
-
}, {
|
|
166
167
|
tag: '020',
|
|
167
168
|
ind1: ' ',
|
|
168
169
|
ind2: ' ',
|
|
@@ -175,7 +176,7 @@ describe('isbn-issn', () => {
|
|
|
175
176
|
const result = await validator.validate(record);
|
|
176
177
|
(0, _chai.expect)(result).to.eql({
|
|
177
178
|
valid: false,
|
|
178
|
-
messages: ['ISBN (
|
|
179
|
+
messages: ['ISBN (978-600-377-017-1 (nid.)) is not valid']
|
|
179
180
|
});
|
|
180
181
|
});
|
|
181
182
|
it('Finds the record invalid (ISSN in \'l\'-subfield)', async () => {
|
|
@@ -218,6 +219,15 @@ describe('isbn-issn', () => {
|
|
|
218
219
|
code: 'a',
|
|
219
220
|
value: '9789519155470'
|
|
220
221
|
}]
|
|
222
|
+
}, {
|
|
223
|
+
tag: '020',
|
|
224
|
+
ind1: ' ',
|
|
225
|
+
ind2: ' ',
|
|
226
|
+
subfields: [{
|
|
227
|
+
code: 'a',
|
|
228
|
+
value: '9068-31-372-X'
|
|
229
|
+
}] // legal digits, but bad hyphenation
|
|
230
|
+
|
|
221
231
|
}, {
|
|
222
232
|
tag: '020',
|
|
223
233
|
ind1: ' ',
|
|
@@ -231,7 +241,7 @@ describe('isbn-issn', () => {
|
|
|
231
241
|
const result = await validator.validate(record);
|
|
232
242
|
(0, _chai.expect)(result).to.eql({
|
|
233
243
|
valid: false,
|
|
234
|
-
messages: ['ISBN (9789519155470) is not valid', 'ISBN (386006004X) is not valid']
|
|
244
|
+
messages: ['ISBN (9789519155470) is not valid', 'ISBN (9068-31-372-X) is not valid', 'ISBN (386006004X) is not valid']
|
|
235
245
|
});
|
|
236
246
|
});
|
|
237
247
|
it.skip('Finds the record invalid (Missing ISBN)');
|
|
@@ -382,18 +392,19 @@ describe('isbn-issn', () => {
|
|
|
382
392
|
ind2: ' ',
|
|
383
393
|
subfields: [{
|
|
384
394
|
code: 'a',
|
|
385
|
-
value: '9786003770171 (
|
|
395
|
+
value: '9786003770171 (nidottu)'
|
|
386
396
|
}]
|
|
387
397
|
}]
|
|
388
398
|
});
|
|
389
399
|
await validator.fix(record);
|
|
390
|
-
(0, _chai.expect)(record.fields).to.eql([
|
|
400
|
+
(0, _chai.expect)(record.fields).to.eql([// NB! Initial space does not need to be removed. It's crap, but not this fixer's crap.
|
|
401
|
+
{
|
|
391
402
|
tag: '020',
|
|
392
403
|
ind1: ' ',
|
|
393
404
|
ind2: ' ',
|
|
394
405
|
subfields: [{
|
|
395
406
|
code: 'a',
|
|
396
|
-
value: '9786003770171'
|
|
407
|
+
value: ' 9786003770171'
|
|
397
408
|
}]
|
|
398
409
|
}, {
|
|
399
410
|
tag: '020',
|
|
@@ -402,6 +413,9 @@ describe('isbn-issn', () => {
|
|
|
402
413
|
subfields: [{
|
|
403
414
|
code: 'a',
|
|
404
415
|
value: '9786003770171'
|
|
416
|
+
}, {
|
|
417
|
+
code: 'q',
|
|
418
|
+
value: '(nidottu)'
|
|
405
419
|
}]
|
|
406
420
|
}]);
|
|
407
421
|
});
|
|
@@ -440,6 +454,10 @@ describe('isbn-issn', () => {
|
|
|
440
454
|
}, {
|
|
441
455
|
code: 'z',
|
|
442
456
|
value: 'foo bar'
|
|
457
|
+
}, // NB! Technically $q should come before $z subfields, but this is good enough.
|
|
458
|
+
{
|
|
459
|
+
code: 'q',
|
|
460
|
+
value: '(nid.)'
|
|
443
461
|
}]
|
|
444
462
|
}]);
|
|
445
463
|
});
|
|
@@ -451,6 +469,14 @@ describe('isbn-issn', () => {
|
|
|
451
469
|
fields: [{
|
|
452
470
|
tag: '005',
|
|
453
471
|
value: 'whatever'
|
|
472
|
+
}, {
|
|
473
|
+
tag: '020',
|
|
474
|
+
ind1: ' ',
|
|
475
|
+
ind2: ' ',
|
|
476
|
+
subfields: [{
|
|
477
|
+
code: 'q',
|
|
478
|
+
value: 'sidottu'
|
|
479
|
+
}]
|
|
454
480
|
}, {
|
|
455
481
|
tag: '024',
|
|
456
482
|
ind1: ' ',
|
|
@@ -465,6 +491,14 @@ describe('isbn-issn', () => {
|
|
|
465
491
|
(0, _chai.expect)(record.fields).to.eql([{
|
|
466
492
|
tag: '005',
|
|
467
493
|
value: 'whatever'
|
|
494
|
+
}, {
|
|
495
|
+
tag: '020',
|
|
496
|
+
ind1: ' ',
|
|
497
|
+
ind2: ' ',
|
|
498
|
+
subfields: [{
|
|
499
|
+
code: 'q',
|
|
500
|
+
value: 'sidottu'
|
|
501
|
+
}]
|
|
468
502
|
}, {
|
|
469
503
|
tag: '024',
|
|
470
504
|
ind1: ' ',
|
|
@@ -496,6 +530,15 @@ describe('isbn-issn', () => {
|
|
|
496
530
|
code: 'a',
|
|
497
531
|
value: '917153086X'
|
|
498
532
|
}]
|
|
533
|
+
}, {
|
|
534
|
+
tag: '020',
|
|
535
|
+
ind1: ' ',
|
|
536
|
+
ind2: ' ',
|
|
537
|
+
subfields: [{
|
|
538
|
+
code: 'a',
|
|
539
|
+
value: '9068-31-372-X'
|
|
540
|
+
}] // legal digits, but bad hyphenation
|
|
541
|
+
|
|
499
542
|
}, {
|
|
500
543
|
tag: '020',
|
|
501
544
|
ind1: ' ',
|
|
@@ -540,12 +583,24 @@ describe('isbn-issn', () => {
|
|
|
540
583
|
value: '91-7153-086-X'
|
|
541
584
|
}]
|
|
542
585
|
}, {
|
|
586
|
+
tag: '020',
|
|
587
|
+
ind1: ' ',
|
|
588
|
+
ind2: ' ',
|
|
589
|
+
subfields: [{
|
|
590
|
+
code: 'a',
|
|
591
|
+
value: '90-6831-372-X'
|
|
592
|
+
}]
|
|
593
|
+
}, // corrected hyphens
|
|
594
|
+
{
|
|
543
595
|
tag: '020',
|
|
544
596
|
ind1: ' ',
|
|
545
597
|
ind2: ' ',
|
|
546
598
|
subfields: [{
|
|
547
599
|
code: 'a',
|
|
548
600
|
value: '3-86006-004-X'
|
|
601
|
+
}, {
|
|
602
|
+
code: 'q',
|
|
603
|
+
value: '(nid.)'
|
|
549
604
|
}]
|
|
550
605
|
}, {
|
|
551
606
|
tag: '020',
|