@natlibfi/marc-record-validators-melinda 12.0.0-alpha.9 → 12.0.1-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.
Files changed (292) hide show
  1. package/dist/access-rights.test.js +1 -1
  2. package/dist/access-rights.test.js.map +1 -1
  3. package/dist/addMissingField337.test.js +1 -1
  4. package/dist/addMissingField337.test.js.map +1 -1
  5. package/dist/addMissingField338.test.js +1 -1
  6. package/dist/addMissingField338.test.js.map +1 -1
  7. package/dist/cyrillux-usemarcon-replacement.test.js +4 -7
  8. package/dist/cyrillux-usemarcon-replacement.test.js.map +2 -2
  9. package/dist/cyrillux.test.js +1 -1
  10. package/dist/cyrillux.test.js.map +1 -1
  11. package/dist/disambiguateSeriesStatements.test.js +1 -7
  12. package/dist/disambiguateSeriesStatements.test.js.map +2 -2
  13. package/dist/double-commas.test.js +1 -1
  14. package/dist/double-commas.test.js.map +1 -1
  15. package/dist/drop-terms.js +122 -0
  16. package/dist/drop-terms.js.map +7 -0
  17. package/dist/drop-terms.test.js +56 -0
  18. package/dist/drop-terms.test.js.map +7 -0
  19. package/dist/empty-fields.test.js +1 -1
  20. package/dist/empty-fields.test.js.map +1 -1
  21. package/dist/ending-punctuation.test.js +39 -19
  22. package/dist/ending-punctuation.test.js.map +2 -2
  23. package/dist/field-008-18-34-character-groups.test.js +2 -8
  24. package/dist/field-008-18-34-character-groups.test.js.map +2 -2
  25. package/dist/field-505-separators.test.js +1 -7
  26. package/dist/field-505-separators.test.js.map +2 -2
  27. package/dist/field-521-fix.test.js +1 -7
  28. package/dist/field-521-fix.test.js.map +2 -2
  29. package/dist/field-exclusion.test.js +11 -8
  30. package/dist/field-exclusion.test.js.map +2 -2
  31. package/dist/field-structure.test.js +1 -1
  32. package/dist/field-structure.test.js.map +1 -1
  33. package/dist/fields-present.test.js +1 -1
  34. package/dist/fields-present.test.js.map +1 -1
  35. package/dist/fix-33X.test.js +1 -1
  36. package/dist/fix-33X.test.js.map +1 -1
  37. package/dist/fix-country-codes.test.js +1 -7
  38. package/dist/fix-country-codes.test.js.map +2 -2
  39. package/dist/fix-sami-041.js +87 -0
  40. package/dist/fix-sami-041.js.map +7 -0
  41. package/dist/fix-sami-041.test.js +40 -0
  42. package/dist/fix-sami-041.test.js.map +7 -0
  43. package/dist/fixRelatorTerms.test.js +2 -8
  44. package/dist/fixRelatorTerms.test.js.map +2 -2
  45. package/dist/fixed-fields.test.js +29 -18
  46. package/dist/fixed-fields.test.js.map +2 -2
  47. package/dist/identical-fields.test.js +1 -1
  48. package/dist/identical-fields.test.js.map +1 -1
  49. package/dist/index.js +7 -1
  50. package/dist/index.js.map +2 -2
  51. package/dist/indicator-fixes.js +10 -0
  52. package/dist/indicator-fixes.js.map +2 -2
  53. package/dist/indicator-fixes.test.js +1 -7
  54. package/dist/indicator-fixes.test.js.map +2 -2
  55. package/dist/isbn-issn.js +1 -1
  56. package/dist/isbn-issn.js.map +2 -2
  57. package/dist/isbn-issn.test.js +9 -6
  58. package/dist/isbn-issn.test.js.map +2 -2
  59. package/dist/item-language.test.js +1 -1
  60. package/dist/item-language.test.js.map +2 -2
  61. package/dist/merge-fields.test.js +2 -7
  62. package/dist/merge-fields.test.js.map +2 -2
  63. package/dist/mergeField500Lisapainokset.test.js +1 -7
  64. package/dist/mergeField500Lisapainokset.test.js.map +2 -2
  65. package/dist/mergeRelatorTermFields.test.js +1 -7
  66. package/dist/mergeRelatorTermFields.test.js.map +2 -2
  67. package/dist/multiple-subfield-0.test.js +1 -7
  68. package/dist/multiple-subfield-0.test.js.map +2 -2
  69. package/dist/normalize-dashes.test.js +1 -7
  70. package/dist/normalize-dashes.test.js.map +2 -2
  71. package/dist/normalize-identifiers.test.js +1 -7
  72. package/dist/normalize-identifiers.test.js.map +2 -2
  73. package/dist/normalize-qualifying-information.test.js +1 -7
  74. package/dist/normalize-qualifying-information.test.js.map +2 -2
  75. package/dist/normalize-utf8-diacritics.test.js +1 -7
  76. package/dist/normalize-utf8-diacritics.test.js.map +2 -2
  77. package/dist/normalizeFieldForComparison.js +24 -0
  78. package/dist/normalizeFieldForComparison.js.map +2 -2
  79. package/dist/punctuation.test.js +1 -7
  80. package/dist/punctuation.test.js.map +2 -2
  81. package/dist/punctuation2.test.js +2 -8
  82. package/dist/punctuation2.test.js.map +2 -2
  83. package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
  84. package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
  85. package/dist/remove-041-zxx.js +56 -0
  86. package/dist/remove-041-zxx.js.map +7 -0
  87. package/dist/remove-041-zxx.test.js +40 -0
  88. package/dist/remove-041-zxx.test.js.map +7 -0
  89. package/dist/removeDuplicateDataFields.test.js +2 -8
  90. package/dist/removeDuplicateDataFields.test.js.map +2 -2
  91. package/dist/removeInferiorDataFields.js +1 -9
  92. package/dist/removeInferiorDataFields.js.map +2 -2
  93. package/dist/removeInferiorDataFields.test.js +1 -7
  94. package/dist/removeInferiorDataFields.test.js.map +2 -2
  95. package/dist/resolvable-ext-references-melinda.test.js +1 -1
  96. package/dist/resolvable-ext-references-melinda.test.js.map +2 -2
  97. package/dist/resolveOrphanedSubfield6s.js +1 -3
  98. package/dist/resolveOrphanedSubfield6s.js.map +2 -2
  99. package/dist/resolveOrphanedSubfield6s.test.js +1 -7
  100. package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
  101. package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
  102. package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
  103. package/dist/sort-tags.test.js +1 -1
  104. package/dist/sort-tags.test.js.map +1 -1
  105. package/dist/sortFields.js +16 -1
  106. package/dist/sortFields.js.map +2 -2
  107. package/dist/sortFields.test.js +1 -7
  108. package/dist/sortFields.test.js.map +2 -2
  109. package/dist/sortRelatorTerms.test.js +1 -7
  110. package/dist/sortRelatorTerms.test.js.map +2 -2
  111. package/dist/sortSubfields.js +3 -1
  112. package/dist/sortSubfields.js.map +2 -2
  113. package/dist/sortSubfields.test.js +1 -7
  114. package/dist/sortSubfields.test.js.map +2 -2
  115. package/dist/stripPunctuation.js +7 -4
  116. package/dist/stripPunctuation.js.map +2 -2
  117. package/dist/stripPunctuation.test.js +1 -7
  118. package/dist/stripPunctuation.test.js.map +2 -2
  119. package/dist/subfield-exclusion.test.js +1 -1
  120. package/dist/subfield-exclusion.test.js.map +1 -1
  121. package/dist/subfield6Utils.js +1 -13
  122. package/dist/subfield6Utils.js.map +2 -2
  123. package/dist/subfieldValueNormalizations.test.js +1 -7
  124. package/dist/subfieldValueNormalizations.test.js.map +2 -2
  125. package/dist/sync-007-and-300.test.js +1 -7
  126. package/dist/sync-007-and-300.test.js.map +2 -2
  127. package/dist/sync-language.js +103 -0
  128. package/dist/sync-language.js.map +7 -0
  129. package/dist/sync-language.test.js +40 -0
  130. package/dist/sync-language.test.js.map +7 -0
  131. package/dist/translate-terms.js +121 -85
  132. package/dist/translate-terms.js.map +3 -3
  133. package/dist/translate-terms.test.js +5 -8
  134. package/dist/translate-terms.test.js.map +2 -2
  135. package/dist/unicode-decomposition.test.js +1 -1
  136. package/dist/unicode-decomposition.test.js.map +1 -1
  137. package/dist/update-field-540.test.js +2 -8
  138. package/dist/update-field-540.test.js.map +2 -2
  139. package/dist/urn.test.js +2 -8
  140. package/dist/urn.test.js.map +2 -2
  141. package/package.json +18 -16
  142. package/src/access-rights.test.js +1 -1
  143. package/src/addMissingField337.test.js +1 -1
  144. package/src/addMissingField338.test.js +1 -1
  145. package/src/cyrillux-usemarcon-replacement.test.js +4 -9
  146. package/src/cyrillux.test.js +1 -1
  147. package/src/disambiguateSeriesStatements.test.js +3 -8
  148. package/src/double-commas.test.js +1 -1
  149. package/src/drop-terms.js +162 -0
  150. package/src/drop-terms.test.js +81 -0
  151. package/src/empty-fields.test.js +1 -1
  152. package/src/ending-punctuation.test.js +28 -20
  153. package/src/field-008-18-34-character-groups.test.js +4 -9
  154. package/src/field-505-separators.test.js +3 -8
  155. package/src/field-521-fix.test.js +3 -8
  156. package/src/field-exclusion.test.js +10 -8
  157. package/src/field-structure.test.js +1 -1
  158. package/src/fields-present.test.js +1 -1
  159. package/src/fix-33X.test.js +1 -1
  160. package/src/fix-country-codes.test.js +3 -8
  161. package/src/fix-sami-041.js +113 -0
  162. package/src/fix-sami-041.test.js +52 -0
  163. package/src/fixRelatorTerms.test.js +4 -9
  164. package/src/fixed-fields.test.js +24 -18
  165. package/src/identical-fields.test.js +1 -1
  166. package/src/index.js +8 -1
  167. package/src/indicator-fixes.js +12 -0
  168. package/src/indicator-fixes.test.js +3 -8
  169. package/src/isbn-issn.js +1 -1
  170. package/src/isbn-issn.test.js +8 -6
  171. package/src/item-language.test.js +2 -2
  172. package/src/merge-fields.test.js +3 -8
  173. package/src/mergeField500Lisapainokset.test.js +3 -8
  174. package/src/mergeRelatorTermFields.test.js +3 -8
  175. package/src/multiple-subfield-0.test.js +3 -8
  176. package/src/normalize-dashes.test.js +3 -8
  177. package/src/normalize-identifiers.test.js +3 -8
  178. package/src/normalize-qualifying-information.test.js +3 -8
  179. package/src/normalize-utf8-diacritics.test.js +3 -8
  180. package/src/normalizeFieldForComparison.js +26 -0
  181. package/src/punctuation.test.js +3 -8
  182. package/src/punctuation2.test.js +4 -9
  183. package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
  184. package/src/remove-041-zxx.js +85 -0
  185. package/src/remove-041-zxx.test.js +52 -0
  186. package/src/removeDuplicateDataFields.test.js +4 -9
  187. package/src/removeInferiorDataFields.js +7 -7
  188. package/src/removeInferiorDataFields.test.js +3 -8
  189. package/src/resolvable-ext-references-melinda.test.js +5 -5
  190. package/src/resolveOrphanedSubfield6s.js +3 -3
  191. package/src/resolveOrphanedSubfield6s.test.js +3 -8
  192. package/src/sanitize-vocabulary-source-codes.test.js +3 -8
  193. package/src/sort-tags.test.js +1 -1
  194. package/src/sortFields.js +20 -1
  195. package/src/sortFields.test.js +3 -8
  196. package/src/sortRelatorTerms.test.js +3 -8
  197. package/src/sortSubfields.js +3 -1
  198. package/src/sortSubfields.test.js +3 -8
  199. package/src/stripPunctuation.js +9 -6
  200. package/src/stripPunctuation.test.js +3 -8
  201. package/src/subfield-exclusion.test.js +1 -1
  202. package/src/subfield6Utils.js +13 -13
  203. package/src/subfieldValueNormalizations.test.js +3 -8
  204. package/src/sync-007-and-300.test.js +3 -8
  205. package/src/sync-language.js +148 -0
  206. package/src/sync-language.test.js +52 -0
  207. package/src/translate-terms.js +158 -103
  208. package/src/translate-terms.test.js +12 -16
  209. package/src/unicode-decomposition.test.js +1 -1
  210. package/src/update-field-540.test.js +4 -9
  211. package/src/urn.test.js +4 -9
  212. package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
  213. package/test-fixtures/drop-terms/01/metadata.json +6 -0
  214. package/test-fixtures/drop-terms/01/record.json +35 -0
  215. package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
  216. package/test-fixtures/drop-terms/02/metadata.json +6 -0
  217. package/test-fixtures/drop-terms/02/record.json +40 -0
  218. package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
  219. package/test-fixtures/drop-terms/03/metadata.json +18 -0
  220. package/test-fixtures/drop-terms/03/record.json +39 -0
  221. package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
  222. package/test-fixtures/drop-terms/04/metadata.json +19 -0
  223. package/test-fixtures/drop-terms/04/record.json +24 -0
  224. package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
  225. package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
  226. package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
  227. package/test-fixtures/fix-sami-041/01/record.json +13 -0
  228. package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
  229. package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
  230. package/test-fixtures/fix-sami-041/02/record.json +8 -0
  231. package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
  232. package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
  233. package/test-fixtures/fix-sami-041/03/record.json +8 -0
  234. package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
  235. package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
  236. package/test-fixtures/fix-sami-041/04/record.json +10 -0
  237. package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
  238. package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
  239. package/test-fixtures/fix-sami-041/05/record.json +8 -0
  240. package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
  241. package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
  242. package/test-fixtures/indicator-fixes/11/record.json +10 -0
  243. package/test-fixtures/merge-fields/f05/metadata.json +1 -1
  244. package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
  245. package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
  246. package/test-fixtures/remove-041-zxx/01/record.json +10 -0
  247. package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
  248. package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
  249. package/test-fixtures/remove-041-zxx/02/record.json +9 -0
  250. package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
  251. package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
  252. package/test-fixtures/remove-041-zxx/11/record.json +9 -0
  253. package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
  254. package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
  255. package/test-fixtures/remove-041-zxx/12/record.json +9 -0
  256. package/test-fixtures/sort-fields/15/input.json +9 -0
  257. package/test-fixtures/sort-fields/15/metadata.json +5 -0
  258. package/test-fixtures/sort-fields/15/result.json +10 -0
  259. package/test-fixtures/sync-language/01/expectedResult.json +5 -0
  260. package/test-fixtures/sync-language/01/metadata.json +5 -0
  261. package/test-fixtures/sync-language/01/record.json +7 -0
  262. package/test-fixtures/sync-language/02/expectedResult.json +6 -0
  263. package/test-fixtures/sync-language/02/metadata.json +5 -0
  264. package/test-fixtures/sync-language/02/record.json +10 -0
  265. package/test-fixtures/sync-language/03/expectedResult.json +6 -0
  266. package/test-fixtures/sync-language/03/metadata.json +5 -0
  267. package/test-fixtures/sync-language/03/record.json +6 -0
  268. package/test-fixtures/sync-language/10/expectedResult.json +10 -0
  269. package/test-fixtures/sync-language/10/metadata.json +5 -0
  270. package/test-fixtures/sync-language/10/record.json +8 -0
  271. package/test-fixtures/sync-language/11/expectedResult.json +10 -0
  272. package/test-fixtures/sync-language/11/metadata.json +5 -0
  273. package/test-fixtures/sync-language/11/record.json +7 -0
  274. package/test-fixtures/sync-language/12/expectedResult.json +9 -0
  275. package/test-fixtures/sync-language/12/metadata.json +6 -0
  276. package/test-fixtures/sync-language/12/record.json +6 -0
  277. package/test-fixtures/sync-language/13/expectedResult.json +10 -0
  278. package/test-fixtures/sync-language/13/metadata.json +5 -0
  279. package/test-fixtures/sync-language/13/record.json +8 -0
  280. package/test-fixtures/sync-language/14/expectedResult.json +9 -0
  281. package/test-fixtures/sync-language/14/metadata.json +5 -0
  282. package/test-fixtures/sync-language/14/record.json +7 -0
  283. package/test-fixtures/sync-language/15/expectedResult.json +9 -0
  284. package/test-fixtures/sync-language/15/metadata.json +5 -0
  285. package/test-fixtures/sync-language/15/record.json +7 -0
  286. package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
  287. package/test-fixtures/translate-terms/05/metadata.json +7 -0
  288. package/test-fixtures/translate-terms/05/record.json +11 -0
  289. package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
  290. package/test-fixtures/translate-terms/06/metadata.json +7 -0
  291. package/test-fixtures/translate-terms/06/record.json +11 -0
  292. package/test-fixtures/translate-terms-data.js +23 -0
package/src/sortFields.js CHANGED
@@ -211,7 +211,7 @@ export function fieldOrderComparator(fieldA, fieldB) {
211
211
 
212
212
  //const sorterFunctions = [sortByTag, sortByIndexTerms, sortAlphabetically, sortByRelatorTerm, sortByOccurrenceNumber, preferFenniKeep, sortByFieldLinkAndSequenceNumber];
213
213
 
214
- const sorterFunctions = [sortByTag, sortByIndexTerms, sortAlphabetically, sortByRelatorTerm, sortBySubfield6, preferFenniKeep, sortByFieldLinkAndSequenceNumber];
214
+ const sorterFunctions = [sortByTag, sortByIndexTerms, sortAlphabetically, sortByRelatorTerm, sortBySubfield6, preferFenniKeep, sortByFieldLinkAndSequenceNumber, sortByHacks];
215
215
  //const sorterFunctions = [sortByIndexTerms, sortByRelatorTerm, sortByOccurrenceNumber, preferFenniKeep, sortByFieldLinkAndSequenceNumber];
216
216
 
217
217
  return globalFieldOrderComparator(fieldA, fieldB, sorterFunctions);
@@ -390,6 +390,25 @@ function sortByFieldLinkAndSequenceNumber(fieldA, fieldB) { // Sort by subfield
390
390
  return -1;
391
391
  }
392
392
 
393
+ function sortByHacks(fieldA, fieldB) {
394
+ // Place for various hackier rules
395
+
396
+ if (fieldA.tag === fieldB.tag) {
397
+ if (fieldA.tag === '041') {
398
+ // If we have multiple f041, we want to put the $2-less first; Values from $2 whatever can not be copied to 008/35-37. (See sync-language.js.)
399
+ const a2 = fieldA.subfields.some(sf => sf.code === '2');
400
+ const b2 = fieldB.subfields.some(sf => sf.code === '2');
401
+ if (a2 && !b2) {
402
+ return 1;
403
+ }
404
+ if (b2 && !a2) {
405
+ return -1;
406
+ }
407
+ }
408
+
409
+ }
410
+ return 0;
411
+ }
393
412
 
394
413
  function sortBySubfield6(fieldA, fieldB) { // Sort by subfield $6, ex-sortByOccurrenceNumber...
395
414
  if (fieldA.tag !== '880' || fieldB.tag !== '880') {
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './sortFields.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortFields:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortFields:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
29
29
  assert.equal(typeof validator.validate, 'function');
30
30
  }
31
31
 
32
- async function callback({getFixture, enabled = true, fix = true}) {
33
- if (enabled === false) {
34
- debug('TEST SKIPPED!');
35
- return;
36
- }
37
-
32
+ async function callback({getFixture, fix = true}) {
38
33
  const validator = await validatorFactory();
39
34
  const record = new MarcRecord(getFixture('input.json'));
40
35
  const expectedResult = getFixture('result.json');
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './sortRelatorTerms.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -20,7 +20,7 @@ generateTests({
20
20
  }
21
21
  });
22
22
 
23
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortRelatorTerms:test');
23
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortRelatorTerms:test');
24
24
 
25
25
  async function testValidatorFactory() {
26
26
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator.validate, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false}) {
39
34
  const validator = await validatorFactory();
40
35
  const record = new MarcRecord(getFixture('record.json'));
41
36
  const expectedResult = getFixture('expectedResult.json');
@@ -136,7 +136,9 @@ function getSubfieldSortOrder(field) {
136
136
  debugDev(`sort order for ${field.tag}: ${entry[0].sortOrder}`);
137
137
  return entry[0].sortOrder;
138
138
  }
139
- nvdebug(`WARNING!\tNo subfield order found for ${field.tag}.`);
139
+ if (!['300'].includes(field.tag)) { // Lis tags which use normal $a...$z order here!
140
+ nvdebug(`WARNING!\tNo subfield order found for ${field.tag}.`);
141
+ }
140
142
  return [];
141
143
  }
142
144
 
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './sortSubfields.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -20,7 +20,7 @@ generateTests({
20
20
  }
21
21
  });
22
22
 
23
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortSubfields:test');
23
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sortSubfields:test');
24
24
 
25
25
  async function testValidatorFactory() {
26
26
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator.validate, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false, tagPattern = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false, tagPattern = false}) {
39
34
  const validator = await validatorFactory(tagPattern);
40
35
  const record = new MarcRecord(getFixture('record.json'));
41
36
  const expectedResult = getFixture('expectedResult.json');
@@ -6,26 +6,29 @@
6
6
  */
7
7
 
8
8
  import {fieldGetFixedString, fieldNeedsModification, fieldStripPunctuation} from './punctuation2.js';
9
- // import createDebugLogger from 'debug';
10
- import {fieldToString, nvdebug} from './utils.js';
9
+ import createDebugLogger from 'debug';
11
10
 
12
- // const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/punctuation2');
11
+ import {fieldToString} from './utils.js';
12
+
13
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/punctuation2');
14
+
15
+ const description = 'Strip punctuation in data fields';
13
16
 
14
17
  export default function () {
15
18
  return {
16
- description: 'Strip punctuation to data fields',
19
+ description: description,
17
20
  validate, fix
18
21
  };
19
22
 
20
23
  function fix(record) {
21
- nvdebug('Strip punctuation to data fields: fixer');
24
+ debug(`${description}: fixer`);
22
25
  const res = {message: [], fix: [], valid: true};
23
26
  record.fields.forEach(f => fieldStripPunctuation(f));
24
27
  return res;
25
28
  }
26
29
 
27
30
  function validate(record) {
28
- nvdebug('Strip punctuation to data fields: validate');
31
+ debug(`${description}: validate`);
29
32
 
30
33
  const fieldsNeedingModification = record.fields.filter(f => fieldNeedsModification(f, false));
31
34
 
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './stripPunctuation.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -20,7 +20,7 @@ generateTests({
20
20
  }
21
21
  });
22
22
 
23
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/stripPunctuation:test');
23
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/stripPunctuation:test');
24
24
 
25
25
  async function testValidatorFactory() {
26
26
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator.validate, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false}) {
39
34
  const validator = await validatorFactory();
40
35
  const record = new MarcRecord(getFixture('record.json'));
41
36
  const expectedResult = getFixture('expectedResult.json');
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert';
2
2
  import {MarcRecord} from '@natlibfi/marc-record';
3
- import validatorFactory from '../src/subfield-exclusion.js';
3
+ import validatorFactory from './subfield-exclusion.js';
4
4
  import {describe, it} from 'node:test';
5
5
 
6
6
  //chai.use(chaiAsPromised);
@@ -1,12 +1,12 @@
1
- import createDebugLogger from 'debug';
1
+ //import createDebugLogger from 'debug';
2
2
  // const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');
3
3
 
4
4
  import {add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils.js';
5
- import {fieldHasSubfield, fieldToString, fieldsToString, nvdebug, subfieldToString} from './utils.js';
5
+ import {fieldHasSubfield, fieldToString, /* fieldsToString, */ nvdebug, subfieldToString} from './utils.js';
6
6
 
7
- const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils');
7
+ //const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils');
8
8
  //const debugData = debug.extend('data');
9
- const debugDev = debug.extend('dev');
9
+ //const debugDev = debug.extend('dev');
10
10
 
11
11
  // NB! Subfield 6 is non-repeatable and it should always comes first!
12
12
  // NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.
@@ -71,7 +71,7 @@ export function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurre
71
71
  }
72
72
  // We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...
73
73
  const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1');
74
- nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);
74
+ //nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);
75
75
  return key === tagAndOccurrenceNumber;
76
76
  }
77
77
 
@@ -222,7 +222,7 @@ export function fieldGetOccurrenceNumberPairs(field, candFields) {
222
222
  nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);
223
223
  return pairs;
224
224
  }
225
- nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);
225
+ //nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);
226
226
  pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));
227
227
  return pairs;
228
228
  }
@@ -357,7 +357,7 @@ function guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {
357
357
  export function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag = false) {
358
358
  const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);
359
359
 
360
- nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);
360
+ //nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);
361
361
  const strings = fields.map(field => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag));
362
362
  strings.sort();
363
363
  return strings.join('\t__SEPARATOR__\t');
@@ -445,7 +445,7 @@ export function isFirstLinkedSubfield6Field(field, record) {
445
445
  }
446
446
  const chain = getAllLinkedSubfield6Fields(field, record);
447
447
  if (!isRelevantSubfield6Chain(chain)) {
448
- nvdebug(`Rejected 6: ${fieldsToString(chain)}`);
448
+ //nvdebug(`Rejected 6: ${fieldsToString(chain)}`);
449
449
  return false;
450
450
  }
451
451
 
@@ -472,13 +472,13 @@ export function get6s(field, candidateFields) { // NB! Convert field to fields!!
472
472
  if (sixes.length === 0) {
473
473
  return [field];
474
474
  }
475
- nvdebug(`SIXES: ${sixes.length}`);
475
+ //nvdebug(`SIXES: ${sixes.length}`);
476
476
  const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');
477
- nvdebug(occurrenceNumbers.join(' -- '));
477
+ //nvdebug(occurrenceNumbers.join(' -- '));
478
478
 
479
479
  const relevantFields = candidateFields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));
480
- nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);
481
- relevantFields.forEach(f => nvdebug(fieldToString(f)));
480
+ //nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);
481
+ //relevantFields.forEach(f => nvdebug(fieldToString(f)));
482
482
  return relevantFields;
483
483
  }
484
484
 
@@ -488,6 +488,6 @@ export function resetSubfield6Tag(subfield, tag) {
488
488
  }
489
489
  // NB! mainly for 1XX<->7XX transfers
490
490
  const newValue = `${tag}-${subfield.value.substring(4)}`;
491
- nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);
491
+ //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);
492
492
  subfield.value = newValue;
493
493
  }
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './subfieldValueNormalizations.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -20,7 +20,7 @@ generateTests({
20
20
  }
21
21
  });
22
22
 
23
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/subfieldValueNormalizations:test');
23
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/subfieldValueNormalizations:test');
24
24
 
25
25
  async function testValidatorFactory() {
26
26
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false}) {
39
34
  const validator = await validatorFactory();
40
35
 
41
36
  const recordFixture = getFixture('record.json');
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './sync-007-and-300.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -20,7 +20,7 @@ generateTests({
20
20
  }
21
21
 
22
22
  });
23
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sync-007-and-300:test');
23
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sync-007-and-300:test');
24
24
 
25
25
  async function testValidatorFactory() {
26
26
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator.validate, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false}) {
39
34
  const validator = await validatorFactory();
40
35
  const record = new MarcRecord(getFixture('record.json'));
41
36
  const expectedResult = getFixture('expectedResult.json');
@@ -0,0 +1,148 @@
1
+ // Author(s): Nicholas Volk
2
+
3
+ //import createDebugLogger from 'debug';
4
+ import clone from 'clone';
5
+
6
+ import {fieldToString} from './utils.js';
7
+
8
+ // const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sync-language');
9
+
10
+ export default function () {
11
+
12
+ return {
13
+ description: 'Sync 008/35-37 and 041$a/$d',
14
+ validate, fix
15
+ };
16
+
17
+ function getSubfieldCodeFor041(record) {
18
+ const c = record?.leader[6];
19
+ if (c === 'i' || c === 'j') {
20
+ return 'd';
21
+ }
22
+ return 'a';
23
+ }
24
+
25
+ function transferableValue(val) {
26
+ if (val.match(/^[a-z]{3}$/u)) {
27
+ // 'zxx' is an exception to the otherwise relatively transitive 008/35-37 <=> 041$a relationship...
28
+ // https://wiki.helsinki.fi/xwiki/bin/view/rdasovellusohje/RDA-kuvailu%20MARC%2021%20-formaatilla/RDA-sovellusohje/008%20Kontrollikentt%C3%A4/#Hmp.35-37Kieli
29
+ // "008-kielikoodi on sama kuin ensimmäinen 041-kentän a- (tai d-) osakenttä. Poikkeuksen muodostaa koodi zxx:
30
+ // jos tietueen 008ssa on kielikoodi zxx (ei kielellistä sisältöä, esim. soitinmusiikki), tietueessa ei voi olla 041 a- eikä d-osakenttää."
31
+ // So 'zxx' ain't transferable (done here), and it should be removed from 041 ($a and $d at least, not done here nor elsewhere at the moment...)
32
+ // Note that 'mul' and 'und' are treated (in this validator) the same as normal values.
33
+ if (val === 'zxx') {
34
+ return false;
35
+ }
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+
41
+
42
+ function zxxRemoval041(record, field, validateMode) {
43
+ const fields041 = record.fields.filter(f => f.tag === '041');
44
+
45
+ return handleZxx(fields041);
46
+
47
+ function handleZxx(fields, result = []) {
48
+ const [currField, ...remainingFields] = fields;
49
+ if ( !currField) {
50
+ return result;
51
+ }
52
+ // Theoretically 'zxx' might mean something in ISO-639-3 or some other language code list:
53
+ if (!field.subfields || field.subfields.some(sf => sf.code === '2')) {
54
+ return handleZxx(remainingFields, result);
55
+ }
56
+ // Presumable 'zxx' is bad in any data subfield, not just 'a' and 'd':
57
+ const otherSubfields = field.subfields.some(sf => !sf.code.match(/^[a-z]$/u || sf.value !== 'zxx'));
58
+ if (otherSubfields.length === field.subfields.length) {
59
+ return handleZxx(remainingFields, result);
60
+ }
61
+ const originalString = fieldToString(field);
62
+ if (otherSubfields.length === 0) {
63
+ const message = `Remove '${originalString}'`;
64
+ if (!validateMode) {
65
+ record.removeField(field);
66
+ }
67
+ return handleZxx(remainingFields, [...result, message]);
68
+ }
69
+ // Some subfields are removed:
70
+ if (validateMode) {
71
+ // NB! In validation field is not really deleted, and the non-deleted field might trigger other fixes (than won't be done to a deleted field) later on
72
+ const clonedField = clone(field);
73
+ clonedField.subfields = otherSubfields;
74
+ const modifiedString = fieldToString(clonedField);
75
+ const message = `Modify '${originalString}' => '${modifiedString}`;
76
+ return handleZxx(remainingFields, [...result, message]);
77
+ }
78
+ field.subfields = otherSubfields;
79
+ const modifiedString = fieldToString(field);
80
+ const message = `Modify '${originalString}' => '${modifiedString}`;
81
+ return handleZxx(remainingFields, [...result, message]);
82
+ }
83
+
84
+
85
+ }
86
+
87
+ function sync008And041(record, validateMode) {
88
+ const f008 = record.fields.find(f => f.tag === '008');
89
+ const f041 = record.fields.find(f => f.tag === '041');
90
+
91
+ if (!f008 || f008.value.length !== 40) { // Some sanity checks
92
+ return [];
93
+ }
94
+
95
+ const subfieldCode = getSubfieldCodeFor041(record);
96
+ const lang008 = f008.value.substring(35, 38);
97
+
98
+ if (!f041) {
99
+ // Insert missing 041
100
+ if (transferableValue(lang008)) {
101
+ const newField = {'tag': '041', 'ind1': ' ', 'ind2': ' ', 'subfields': [ {'code': subfieldCode, 'value': lang008}]};
102
+ if (!validateMode) {
103
+ record.insertField(newField);
104
+ }
105
+ return [ `Add '${fieldToString(newField)}'` ];
106
+ }
107
+ // Can't do anything, and we only report this we can fix...
108
+ return [];
109
+ }
110
+
111
+ const firstRelevantSubfield = f041.subfields.find(sf => sf.code === subfieldCode);
112
+
113
+ // NB! If $2 is set, *never* copy it's value to 008/35-37... Otherwise we might a loop in Aleph.
114
+ // Note that if $2 is used, 008/35-37 should actually be '|||'. Now we just aggressively leave it alone.
115
+ if (!firstRelevantSubfield || !transferableValue(firstRelevantSubfield.value) || f041.subfields.some(sf => sf.code === '2') || lang008 === firstRelevantSubfield.value) {
116
+ return []
117
+ }
118
+
119
+ // Update 008/35-37:
120
+ const cloned008 = clone(f008);
121
+ cloned008.value = `${f008.value.substring(0, 35)}${firstRelevantSubfield.value}${f008.value.substring(38)}`;
122
+
123
+
124
+ if (!validateMode) {
125
+ f008.value = cloned008.value;
126
+ }
127
+ return [ `Modify '${f008.value}' to '${cloned008.value}'` ];
128
+ }
129
+
130
+ function fix(record, validateMode = false) {
131
+ const zxxMessages = zxxRemoval041(record, validateMode);
132
+
133
+ const syncMessages = sync008And041(record, validateMode);
134
+
135
+ const messages = [...zxxMessages, ...syncMessages];
136
+
137
+ if (validateMode) {
138
+ return {message: messages, valid: messages.length === 0};
139
+ }
140
+ return {message: [], fix: messages, valid: true};
141
+ }
142
+
143
+
144
+ function validate(record) {
145
+ return fix(record, true);
146
+ }
147
+ }
148
+
@@ -0,0 +1,52 @@
1
+ import assert from 'node:assert/strict';
2
+ //import createDebugLogger from 'debug';
3
+
4
+ import validatorFactory from './sync-language.js';
5
+
6
+ import {MarcRecord} from '@natlibfi/marc-record';
7
+ import {READERS} from '@natlibfi/fixura';
8
+ import generateTests from '@natlibfi/fixugen';
9
+
10
+ generateTests({
11
+ callback,
12
+ path: [import.meta.dirname, '..', 'test-fixtures', 'sync-language'],
13
+ useMetadataFile: true,
14
+ recurse: false,
15
+ fixura: {
16
+ reader: READERS.JSON
17
+ },
18
+ hooks: {
19
+ before: async () => {
20
+ testValidatorFactory();
21
+ }
22
+ }
23
+ });
24
+
25
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/drop-terms:test');
26
+
27
+ async function testValidatorFactory() {
28
+ const validator = await validatorFactory();
29
+
30
+ assert.equal(typeof validator, 'object');
31
+ assert.equal(typeof validator.description, 'string');
32
+ assert.equal(typeof validator.validate, 'function');
33
+ }
34
+
35
+ async function callback({getFixture, fix = false}) {
36
+ const validator = await validatorFactory();
37
+ const record = new MarcRecord(getFixture('record.json'));
38
+ const expectedResult = getFixture('expectedResult.json');
39
+ //const expectedResult = new MarcRecord(getFixture('expectedResult.json'));
40
+ // console.log(expectedResult); // eslint-disable-line
41
+
42
+ if (!fix) {
43
+ const result = await validator.validate(record);
44
+ assert.deepEqual(result, expectedResult);
45
+ const originalRecord = new MarcRecord(getFixture('record.json'));
46
+ assert.deepEqual(record, originalRecord); // The record should now change in validation-only
47
+ return;
48
+ }
49
+
50
+ await validator.fix(record);
51
+ assert.deepEqual(record, new MarcRecord(expectedResult));
52
+ }