@natlibfi/marc-record-validators-melinda 12.1.0-alpha.1 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/.github/workflows/melinda-node-tests-and-publish.yml +17 -17
  2. package/README.md +1 -1
  3. package/dist/addMissingField041.js +6 -3
  4. package/dist/addMissingField041.js.map +2 -2
  5. package/dist/addMissingField336.js +7 -4
  6. package/dist/addMissingField336.js.map +2 -2
  7. package/dist/addMissingField337.js +6 -3
  8. package/dist/addMissingField337.js.map +2 -2
  9. package/dist/addMissingField338.js +8 -5
  10. package/dist/addMissingField338.js.map +2 -2
  11. package/dist/cyrillux-usemarcon-replacement.js +5 -2
  12. package/dist/cyrillux-usemarcon-replacement.js.map +2 -2
  13. package/dist/cyrillux.js +24 -18
  14. package/dist/cyrillux.js.map +2 -2
  15. package/dist/dataProvenanceUtils.js +19 -0
  16. package/dist/dataProvenanceUtils.js.map +7 -0
  17. package/dist/disambiguateSeriesStatements.js +2 -1
  18. package/dist/disambiguateSeriesStatements.js.map +2 -2
  19. package/dist/disambiguateSeriesStatements.test.js +1 -7
  20. package/dist/disambiguateSeriesStatements.test.js.map +2 -2
  21. package/dist/drop-terms.js +123 -0
  22. package/dist/drop-terms.js.map +7 -0
  23. package/dist/drop-terms.test.js +56 -0
  24. package/dist/drop-terms.test.js.map +7 -0
  25. package/dist/field-008-18-34-character-groups.test.js +1 -7
  26. package/dist/field-008-18-34-character-groups.test.js.map +2 -2
  27. package/dist/field-505-separators.test.js +1 -7
  28. package/dist/field-505-separators.test.js.map +2 -2
  29. package/dist/field-521-fix.test.js +1 -7
  30. package/dist/field-521-fix.test.js.map +2 -2
  31. package/dist/fix-33X.js +7 -4
  32. package/dist/fix-33X.js.map +2 -2
  33. package/dist/fix-33X.test.js +1 -1
  34. package/dist/fix-33X.test.js.map +1 -1
  35. package/dist/fix-country-codes.js +5 -0
  36. package/dist/fix-country-codes.js.map +2 -2
  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-language-codes.js +5 -1
  40. package/dist/fix-language-codes.js.map +2 -2
  41. package/dist/fix-sami-041.js +109 -0
  42. package/dist/fix-sami-041.js.map +7 -0
  43. package/dist/fix-sami-041.test.js +40 -0
  44. package/dist/fix-sami-041.test.js.map +7 -0
  45. package/dist/fixRelatorTerms.js +2 -0
  46. package/dist/fixRelatorTerms.js.map +2 -2
  47. package/dist/fixRelatorTerms.test.js +1 -7
  48. package/dist/fixRelatorTerms.test.js.map +2 -2
  49. package/dist/index.js +18 -4
  50. package/dist/index.js.map +2 -2
  51. package/dist/indicator-fixes.js +15 -1
  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/item-language.js +41 -39
  56. package/dist/item-language.js.map +2 -2
  57. package/dist/item-language.test.js +3 -3
  58. package/dist/item-language.test.js.map +2 -2
  59. package/dist/melindaCustomMergeFields.js +31 -0
  60. package/dist/melindaCustomMergeFields.js.map +2 -2
  61. package/dist/merge-fields/controlSubfields.js.map +2 -2
  62. package/dist/merge-fields/counterpartField.js +149 -152
  63. package/dist/merge-fields/counterpartField.js.map +3 -3
  64. package/dist/merge-fields/dataProvenance.js +6 -20
  65. package/dist/merge-fields/dataProvenance.js.map +2 -2
  66. package/dist/merge-fields/index.js +1 -1
  67. package/dist/merge-fields/index.js.map +2 -2
  68. package/dist/merge-fields/mergableIndicator.js +1 -5
  69. package/dist/merge-fields/mergableIndicator.js.map +2 -2
  70. package/dist/merge-fields/mergableTag.js +2 -0
  71. package/dist/merge-fields/mergableTag.js.map +2 -2
  72. package/dist/merge-fields/mergeConfig.js +2 -0
  73. package/dist/merge-fields/mergeConfig.js.map +2 -2
  74. package/dist/merge-fields/mergeConstraints.js +38 -35
  75. package/dist/merge-fields/mergeConstraints.js.map +3 -3
  76. package/dist/merge-fields/mergeField.js +4 -3
  77. package/dist/merge-fields/mergeField.js.map +2 -2
  78. package/dist/merge-fields/mergeOrAddSubfield.js +8 -7
  79. package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
  80. package/dist/merge-fields/mergeSubfield.js +5 -1
  81. package/dist/merge-fields/mergeSubfield.js.map +2 -2
  82. package/dist/merge-fields/worldKnowledge.js +52 -0
  83. package/dist/merge-fields/worldKnowledge.js.map +2 -2
  84. package/dist/merge-fields.test.js +4 -9
  85. package/dist/merge-fields.test.js.map +2 -2
  86. package/dist/mergeField500Lisapainokset.test.js +1 -7
  87. package/dist/mergeField500Lisapainokset.test.js.map +2 -2
  88. package/dist/mergeRelatorTermFields.js +9 -6
  89. package/dist/mergeRelatorTermFields.js.map +2 -2
  90. package/dist/mergeRelatorTermFields.test.js +1 -7
  91. package/dist/mergeRelatorTermFields.test.js.map +2 -2
  92. package/dist/multiple-subfield-0.test.js +1 -7
  93. package/dist/multiple-subfield-0.test.js.map +2 -2
  94. package/dist/normalize-dashes.js +9 -6
  95. package/dist/normalize-dashes.js.map +2 -2
  96. package/dist/normalize-dashes.test.js +1 -7
  97. package/dist/normalize-dashes.test.js.map +2 -2
  98. package/dist/normalize-identifiers.js.map +2 -2
  99. package/dist/normalize-identifiers.test.js +1 -7
  100. package/dist/normalize-identifiers.test.js.map +2 -2
  101. package/dist/normalize-qualifying-information.test.js +1 -7
  102. package/dist/normalize-qualifying-information.test.js.map +2 -2
  103. package/dist/normalize-utf8-diacritics.js.map +2 -2
  104. package/dist/normalize-utf8-diacritics.test.js +1 -7
  105. package/dist/normalize-utf8-diacritics.test.js.map +2 -2
  106. package/dist/normalizeFieldForComparison.js +24 -14
  107. package/dist/normalizeFieldForComparison.js.map +2 -2
  108. package/dist/normalizeSubfieldValueForComparison.js.map +1 -1
  109. package/dist/prepublicationUtils.js +1 -1
  110. package/dist/prepublicationUtils.js.map +2 -2
  111. package/dist/punctuation.test.js +1 -7
  112. package/dist/punctuation.test.js.map +2 -2
  113. package/dist/punctuation2.js +15 -12
  114. package/dist/punctuation2.js.map +2 -2
  115. package/dist/punctuation2.test.js +1 -7
  116. package/dist/punctuation2.test.js.map +2 -2
  117. package/dist/reindexSubfield6OccurenceNumbers.js +11 -10
  118. package/dist/reindexSubfield6OccurenceNumbers.js.map +2 -2
  119. package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
  120. package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
  121. package/dist/remove-041-zxx.js +56 -0
  122. package/dist/remove-041-zxx.js.map +7 -0
  123. package/dist/remove-041-zxx.test.js +40 -0
  124. package/dist/remove-041-zxx.test.js.map +7 -0
  125. package/dist/removeDuplicateDataFields.js +4 -26
  126. package/dist/removeDuplicateDataFields.js.map +2 -2
  127. package/dist/removeDuplicateDataFields.test.js +1 -7
  128. package/dist/removeDuplicateDataFields.test.js.map +2 -2
  129. package/dist/removeInferiorDataFields.js +82 -45
  130. package/dist/removeInferiorDataFields.js.map +3 -3
  131. package/dist/removeInferiorDataFields.test.js +5 -9
  132. package/dist/removeInferiorDataFields.test.js.map +2 -2
  133. package/dist/resolveOrphanedSubfield6s.js +4 -5
  134. package/dist/resolveOrphanedSubfield6s.js.map +2 -2
  135. package/dist/resolveOrphanedSubfield6s.test.js +1 -7
  136. package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
  137. package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
  138. package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
  139. package/dist/sortFields.js +16 -1
  140. package/dist/sortFields.js.map +2 -2
  141. package/dist/sortFields.test.js +1 -7
  142. package/dist/sortFields.test.js.map +2 -2
  143. package/dist/sortRelatorTerms.test.js +1 -7
  144. package/dist/sortRelatorTerms.test.js.map +2 -2
  145. package/dist/sortSubfields.js +27 -21
  146. package/dist/sortSubfields.js.map +2 -2
  147. package/dist/sortSubfields.test.js +1 -7
  148. package/dist/sortSubfields.test.js.map +2 -2
  149. package/dist/stripPunctuation.js +7 -3
  150. package/dist/stripPunctuation.js.map +2 -2
  151. package/dist/stripPunctuation.test.js +1 -7
  152. package/dist/stripPunctuation.test.js.map +2 -2
  153. package/dist/subfield6Utils.js +2 -12
  154. package/dist/subfield6Utils.js.map +2 -2
  155. package/dist/subfield8Utils.js +0 -5
  156. package/dist/subfield8Utils.js.map +2 -2
  157. package/dist/subfieldValueNormalizations.test.js +1 -7
  158. package/dist/subfieldValueNormalizations.test.js.map +2 -2
  159. package/dist/sync-007-and-300.test.js +1 -7
  160. package/dist/sync-007-and-300.test.js.map +2 -2
  161. package/dist/sync-language.js +103 -0
  162. package/dist/sync-language.js.map +7 -0
  163. package/dist/sync-language.test.js +40 -0
  164. package/dist/sync-language.test.js.map +7 -0
  165. package/dist/translate-terms.js +124 -87
  166. package/dist/translate-terms.js.map +3 -3
  167. package/dist/translate-terms.test.js +5 -8
  168. package/dist/translate-terms.test.js.map +2 -2
  169. package/dist/typeOfDate-008.js +3 -1
  170. package/dist/typeOfDate-008.js.map +2 -2
  171. package/dist/update-field-540.js.map +2 -2
  172. package/dist/update-field-540.test.js +1 -7
  173. package/dist/update-field-540.test.js.map +2 -2
  174. package/dist/urn.js +13 -12
  175. package/dist/urn.js.map +2 -2
  176. package/dist/urn.test.js +1 -7
  177. package/dist/urn.test.js.map +2 -2
  178. package/dist/utils.js +29 -3
  179. package/dist/utils.js.map +2 -2
  180. package/package.json +20 -27
  181. package/src/addMissingField041.js +8 -4
  182. package/src/addMissingField336.js +10 -5
  183. package/src/addMissingField337.js +9 -5
  184. package/src/addMissingField338.js +11 -6
  185. package/src/cyrillux-usemarcon-replacement.js +9 -5
  186. package/src/cyrillux.js +34 -23
  187. package/src/dataProvenanceUtils.js +21 -0
  188. package/src/disambiguateSeriesStatements.js +4 -1
  189. package/src/disambiguateSeriesStatements.test.js +3 -8
  190. package/src/drop-terms.js +164 -0
  191. package/src/drop-terms.test.js +81 -0
  192. package/src/field-008-18-34-character-groups.test.js +3 -8
  193. package/src/field-505-separators.test.js +3 -8
  194. package/src/field-521-fix.test.js +3 -8
  195. package/src/fix-33X.js +10 -6
  196. package/src/fix-33X.test.js +1 -1
  197. package/src/fix-country-codes.js +7 -3
  198. package/src/fix-country-codes.test.js +3 -8
  199. package/src/fix-language-codes.js +8 -4
  200. package/src/fix-sami-041.js +147 -0
  201. package/src/fix-sami-041.test.js +52 -0
  202. package/src/fixRelatorTerms.js +5 -0
  203. package/src/fixRelatorTerms.test.js +3 -8
  204. package/src/index.js +20 -7
  205. package/src/indicator-fixes.js +22 -7
  206. package/src/indicator-fixes.test.js +3 -8
  207. package/src/item-language.js +49 -42
  208. package/src/item-language.test.js +3 -3
  209. package/src/melindaCustomMergeFields.js +31 -0
  210. package/src/merge-fields/controlSubfields.js +0 -1
  211. package/src/merge-fields/counterpartField.js +191 -290
  212. package/src/merge-fields/dataProvenance.js +8 -25
  213. package/src/merge-fields/index.js +1 -1
  214. package/src/merge-fields/mergableIndicator.js +4 -5
  215. package/src/merge-fields/mergableTag.js +2 -0
  216. package/src/merge-fields/mergeConfig.js +2 -1
  217. package/src/merge-fields/mergeConstraints.js +41 -36
  218. package/src/merge-fields/mergeField.js +4 -7
  219. package/src/merge-fields/mergeOrAddSubfield.js +8 -7
  220. package/src/merge-fields/mergeSubfield.js +11 -2
  221. package/src/merge-fields/worldKnowledge.js +77 -3
  222. package/src/merge-fields.test.js +5 -10
  223. package/src/mergeField500Lisapainokset.test.js +3 -8
  224. package/src/mergeRelatorTermFields.js +12 -11
  225. package/src/mergeRelatorTermFields.test.js +3 -8
  226. package/src/multiple-subfield-0.test.js +3 -8
  227. package/src/normalize-dashes.js +13 -7
  228. package/src/normalize-dashes.test.js +3 -8
  229. package/src/normalize-identifiers.js +12 -19
  230. package/src/normalize-identifiers.test.js +3 -8
  231. package/src/normalize-qualifying-information.test.js +3 -8
  232. package/src/normalize-utf8-diacritics.js +6 -3
  233. package/src/normalize-utf8-diacritics.test.js +3 -8
  234. package/src/normalizeFieldForComparison.js +39 -22
  235. package/src/normalizeSubfieldValueForComparison.js +2 -2
  236. package/src/prepublicationUtils.js +1 -1
  237. package/src/punctuation.test.js +3 -8
  238. package/src/punctuation2.js +44 -40
  239. package/src/punctuation2.test.js +3 -8
  240. package/src/reindexSubfield6OccurenceNumbers.js +13 -11
  241. package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
  242. package/src/remove-041-zxx.js +85 -0
  243. package/src/remove-041-zxx.test.js +52 -0
  244. package/src/removeDuplicateDataFields.js +30 -28
  245. package/src/removeDuplicateDataFields.test.js +3 -8
  246. package/src/removeInferiorDataFields.js +126 -71
  247. package/src/removeInferiorDataFields.test.js +7 -10
  248. package/src/resolveOrphanedSubfield6s.js +7 -5
  249. package/src/resolveOrphanedSubfield6s.test.js +3 -8
  250. package/src/sanitize-vocabulary-source-codes.test.js +3 -8
  251. package/src/sortFields.js +20 -1
  252. package/src/sortFields.test.js +3 -8
  253. package/src/sortRelatorTerms.test.js +3 -8
  254. package/src/sortSubfields.js +31 -25
  255. package/src/sortSubfields.test.js +3 -8
  256. package/src/stripPunctuation.js +10 -5
  257. package/src/stripPunctuation.test.js +3 -8
  258. package/src/subfield6Utils.js +31 -33
  259. package/src/subfield8Utils.js +10 -7
  260. package/src/subfieldValueNormalizations.test.js +3 -8
  261. package/src/sync-007-and-300.test.js +3 -8
  262. package/src/sync-language.js +148 -0
  263. package/src/sync-language.test.js +52 -0
  264. package/src/translate-terms.js +168 -109
  265. package/src/translate-terms.test.js +12 -16
  266. package/src/typeOfDate-008.js +4 -1
  267. package/src/update-field-540.js +7 -5
  268. package/src/update-field-540.test.js +3 -8
  269. package/src/urn.js +17 -13
  270. package/src/urn.test.js +3 -8
  271. package/src/utils.js +39 -12
  272. package/test-fixtures/cyrillux/f02b/expectedResult.json +23 -0
  273. package/test-fixtures/cyrillux/f02b/metadata.json +11 -0
  274. package/test-fixtures/cyrillux/f02b/record.json +14 -0
  275. package/test-fixtures/cyrillux/f14/expectedResult.json +32 -0
  276. package/test-fixtures/cyrillux/f14/metadata.json +10 -0
  277. package/test-fixtures/cyrillux/f14/record.json +14 -0
  278. package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
  279. package/test-fixtures/drop-terms/01/metadata.json +6 -0
  280. package/test-fixtures/drop-terms/01/record.json +35 -0
  281. package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
  282. package/test-fixtures/drop-terms/02/metadata.json +6 -0
  283. package/test-fixtures/drop-terms/02/record.json +40 -0
  284. package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
  285. package/test-fixtures/drop-terms/03/metadata.json +18 -0
  286. package/test-fixtures/drop-terms/03/record.json +39 -0
  287. package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
  288. package/test-fixtures/drop-terms/04/metadata.json +19 -0
  289. package/test-fixtures/drop-terms/04/record.json +24 -0
  290. package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
  291. package/test-fixtures/fix-relator-terms/f02/metadata.json +1 -1
  292. package/test-fixtures/fix-relator-terms/f04/expectedResult.json +18 -0
  293. package/test-fixtures/fix-relator-terms/f04/metadata.json +5 -0
  294. package/test-fixtures/fix-relator-terms/f04/record.json +20 -0
  295. package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
  296. package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
  297. package/test-fixtures/fix-sami-041/01/record.json +14 -0
  298. package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
  299. package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
  300. package/test-fixtures/fix-sami-041/02/record.json +8 -0
  301. package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
  302. package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
  303. package/test-fixtures/fix-sami-041/03/record.json +8 -0
  304. package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
  305. package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
  306. package/test-fixtures/fix-sami-041/04/record.json +10 -0
  307. package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
  308. package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
  309. package/test-fixtures/fix-sami-041/05/record.json +8 -0
  310. package/test-fixtures/fix-sami-041/06/expectedResult.json +10 -0
  311. package/test-fixtures/fix-sami-041/06/metadata.json +4 -0
  312. package/test-fixtures/fix-sami-041/06/record.json +9 -0
  313. package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
  314. package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
  315. package/test-fixtures/indicator-fixes/11/record.json +10 -0
  316. package/test-fixtures/merge-fields/f042_01/expectedResult.json +12 -0
  317. package/test-fixtures/merge-fields/f042_01/metadata.json +6 -0
  318. package/test-fixtures/merge-fields/f042_01/record.json +13 -0
  319. package/test-fixtures/merge-fields/f05/metadata.json +1 -1
  320. package/test-fixtures/merge-fields/f06/expectedResult.json +42 -0
  321. package/test-fixtures/merge-fields/f06/metadata.json +6 -0
  322. package/test-fixtures/merge-fields/f06/record.json +41 -0
  323. package/test-fixtures/merge-fields/f07/expectedResult.json +18 -0
  324. package/test-fixtures/merge-fields/f07/metadata.json +6 -0
  325. package/test-fixtures/merge-fields/f07/record.json +18 -0
  326. package/test-fixtures/merge-fields/f08/expectedResult.json +12 -0
  327. package/test-fixtures/merge-fields/f08/metadata.json +7 -0
  328. package/test-fixtures/merge-fields/f08/record.json +10 -0
  329. package/test-fixtures/merge-fields/f09/expectedResult.json +14 -0
  330. package/test-fixtures/merge-fields/f09/metadata.json +6 -0
  331. package/test-fixtures/merge-fields/f09/record.json +14 -0
  332. package/test-fixtures/merge-fields/f10/expectedResult.json +25 -0
  333. package/test-fixtures/merge-fields/f10/metadata.json +6 -0
  334. package/test-fixtures/merge-fields/f10/record.json +25 -0
  335. package/test-fixtures/merge-fields/f11/expectedResult.json +40 -0
  336. package/test-fixtures/merge-fields/f11/metadata.json +7 -0
  337. package/test-fixtures/merge-fields/f11/record.json +50 -0
  338. package/test-fixtures/merge-fields/f12/expectedResult.json +17 -0
  339. package/test-fixtures/merge-fields/f12/metadata.json +6 -0
  340. package/test-fixtures/merge-fields/f12/record.json +25 -0
  341. package/test-fixtures/merge-fields/f13/expectedResult.json +18 -0
  342. package/test-fixtures/merge-fields/f13/metadata.json +6 -0
  343. package/test-fixtures/merge-fields/f13/record.json +28 -0
  344. package/test-fixtures/merge-fields/f14/expectedResult.json +25 -0
  345. package/test-fixtures/merge-fields/f14/metadata.json +6 -0
  346. package/test-fixtures/merge-fields/f14/record.json +25 -0
  347. package/test-fixtures/merge-fields/f15/expectedResult.json +8 -0
  348. package/test-fixtures/merge-fields/f15/metadata.json +6 -0
  349. package/test-fixtures/merge-fields/f15/record.json +9 -0
  350. package/test-fixtures/merge-fields/f16/expectedResult.json +12 -0
  351. package/test-fixtures/merge-fields/f16/metadata.json +7 -0
  352. package/test-fixtures/merge-fields/f16/record.json +13 -0
  353. package/test-fixtures/merge-fields/f300_01/expectedResult.json +9 -0
  354. package/test-fixtures/merge-fields/f300_01/metadata.json +6 -0
  355. package/test-fixtures/merge-fields/f300_01/record.json +8 -0
  356. package/test-fixtures/merge-fields/f300_02/expectedResult.json +13 -0
  357. package/test-fixtures/merge-fields/f300_02/metadata.json +6 -0
  358. package/test-fixtures/merge-fields/f300_02/record.json +16 -0
  359. package/test-fixtures/merge-fields/f300_03/expectedResult.json +13 -0
  360. package/test-fixtures/merge-fields/f300_03/metadata.json +6 -0
  361. package/test-fixtures/merge-fields/f300_03/record.json +16 -0
  362. package/test-fixtures/merge-fields/f490_01/expectedResult.json +13 -0
  363. package/test-fixtures/merge-fields/f490_01/metadata.json +6 -0
  364. package/test-fixtures/merge-fields/f490_01/record.json +16 -0
  365. package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
  366. package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
  367. package/test-fixtures/remove-041-zxx/01/record.json +10 -0
  368. package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
  369. package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
  370. package/test-fixtures/remove-041-zxx/02/record.json +9 -0
  371. package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
  372. package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
  373. package/test-fixtures/remove-041-zxx/11/record.json +9 -0
  374. package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
  375. package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
  376. package/test-fixtures/remove-041-zxx/12/record.json +9 -0
  377. package/test-fixtures/remove-inferior-datafields/f17/expectedResult.json +11 -0
  378. package/test-fixtures/remove-inferior-datafields/f17/metadata.json +5 -0
  379. package/test-fixtures/remove-inferior-datafields/f17/record.json +15 -0
  380. package/test-fixtures/remove-inferior-datafields/f18/expectedResult.json +13 -0
  381. package/test-fixtures/remove-inferior-datafields/f18/metadata.json +5 -0
  382. package/test-fixtures/remove-inferior-datafields/f18/record.json +18 -0
  383. package/test-fixtures/remove-inferior-datafields/f19/expectedResult.json +17 -0
  384. package/test-fixtures/remove-inferior-datafields/f19/metadata.json +5 -0
  385. package/test-fixtures/remove-inferior-datafields/f19/record.json +18 -0
  386. package/test-fixtures/remove-inferior-datafields/f20/expectedResult.json +15 -0
  387. package/test-fixtures/remove-inferior-datafields/f20/metadata.json +5 -0
  388. package/test-fixtures/remove-inferior-datafields/f20/record.json +29 -0
  389. package/test-fixtures/sort-fields/15/input.json +9 -0
  390. package/test-fixtures/sort-fields/15/metadata.json +5 -0
  391. package/test-fixtures/sort-fields/15/result.json +10 -0
  392. package/test-fixtures/sync-language/01/expectedResult.json +5 -0
  393. package/test-fixtures/sync-language/01/metadata.json +5 -0
  394. package/test-fixtures/sync-language/01/record.json +7 -0
  395. package/test-fixtures/sync-language/02/expectedResult.json +6 -0
  396. package/test-fixtures/sync-language/02/metadata.json +5 -0
  397. package/test-fixtures/sync-language/02/record.json +10 -0
  398. package/test-fixtures/sync-language/03/expectedResult.json +6 -0
  399. package/test-fixtures/sync-language/03/metadata.json +5 -0
  400. package/test-fixtures/sync-language/03/record.json +6 -0
  401. package/test-fixtures/sync-language/10/expectedResult.json +10 -0
  402. package/test-fixtures/sync-language/10/metadata.json +5 -0
  403. package/test-fixtures/sync-language/10/record.json +8 -0
  404. package/test-fixtures/sync-language/11/expectedResult.json +10 -0
  405. package/test-fixtures/sync-language/11/metadata.json +5 -0
  406. package/test-fixtures/sync-language/11/record.json +7 -0
  407. package/test-fixtures/sync-language/12/expectedResult.json +9 -0
  408. package/test-fixtures/sync-language/12/metadata.json +6 -0
  409. package/test-fixtures/sync-language/12/record.json +6 -0
  410. package/test-fixtures/sync-language/13/expectedResult.json +10 -0
  411. package/test-fixtures/sync-language/13/metadata.json +5 -0
  412. package/test-fixtures/sync-language/13/record.json +8 -0
  413. package/test-fixtures/sync-language/14/expectedResult.json +9 -0
  414. package/test-fixtures/sync-language/14/metadata.json +5 -0
  415. package/test-fixtures/sync-language/14/record.json +7 -0
  416. package/test-fixtures/sync-language/15/expectedResult.json +9 -0
  417. package/test-fixtures/sync-language/15/metadata.json +5 -0
  418. package/test-fixtures/sync-language/15/record.json +7 -0
  419. package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
  420. package/test-fixtures/translate-terms/05/metadata.json +7 -0
  421. package/test-fixtures/translate-terms/05/record.json +11 -0
  422. package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
  423. package/test-fixtures/translate-terms/06/metadata.json +7 -0
  424. package/test-fixtures/translate-terms/06/record.json +11 -0
  425. package/test-fixtures/translate-terms-data.js +23 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/merge-fields/mergeOrAddSubfield.js"],
4
- "sourcesContent": ["import createDebugLogger from 'debug';\nimport {cloneAndNormalizeFieldForComparison, isEnnakkotietoSubfieldG} from '../normalizeFieldForComparison.js';\nimport {normalizeAs, normalizeControlSubfieldValue} from '../normalize-identifiers.js';\nimport {fieldHasSubfield, fieldToString, isControlSubfieldCode, nvdebug, subfieldIsRepeatable, subfieldToString} from '../utils.js';\nimport {mergeSubfield} from './mergeSubfield.js';\nimport {sortAdjacentSubfields} from '../sortSubfields.js';\n\nimport {valueCarriesMeaning} from './worldKnowledge.js';\nimport {resetSubfield6Tag} from '../subfield6Utils.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeOrAddSubfield');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nfunction catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) {\n if (targetField.tag !== '040' || candSubfieldData.code !== 'd') {\n return false;\n }\n nvdebug(`${fieldToString(targetField)} vs $d ${candSubfieldData.originalValue}}`, debugDev);\n // Add hard-coded exceptions here\n if (targetField.subfields.some(sf => sf.code === 'a' && sf.value === candSubfieldData.originalValue)) {\n nvdebug('040\u2021d matched 040\u2021a', debugDev);\n return true;\n }\n return false;\n}\n\nfunction ennakkotietoInSubfieldG(candSubfieldData) {\n if (isEnnakkotietoSubfieldG({'code': candSubfieldData.code, 'value': candSubfieldData.originalValue})) {\n // Skip just \u2021g subfield or the whole field?\n // We decided to skip just this subfield. We want at least $0 and maybe even more from ennakkotieto.\n debugDev(`Skip '\u2021g ${candSubfieldData.originalValue}'`);\n return true;\n }\n return false;\n}\n\n\nfunction mergeOrAddSubfieldNotRequiredSpecialCases(targetField, candSubfieldData) {\n\n // Don't bring WHATEVER<KEEP> from source 7XX to base 1XX.\n // Exceptionally we can merge <KEEP>ed 7XX with un-<KEEP>ed 1XX as 1XX should not use <KEEP>s.\n if (targetField.tag.charAt(0) === '1' && candSubfieldData.tag.charAt(0) === '7' && candSubfieldData.code === '9' && candSubfieldData.originalValue.match(/<KEEP>/u)) {\n return true;\n }\n\n // Don't add 264$b 'Kustannuspaikka tuntematon' etc\n if (!valueCarriesMeaning(targetField.tag, candSubfieldData.code, candSubfieldData.normalizedValue)) {\n return true;\n }\n\n\n // Don't add $0 subfields that mean the same even if they look different:\n const alephIdentifierType = normalizeAs(targetField.tag, candSubfieldData.code);\n if (alephIdentifierType !== undefined) {\n const normalizedSubfieldValue = normalizeControlSubfieldValue(candSubfieldData.originalValue, alephIdentifierType);\n if (targetField.subfields.some(sf => normalizeControlSubfieldValue(sf.value) === normalizedSubfieldValue && sf.code === candSubfieldData.code)) {\n return true;\n }\n }\n return false;\n}\n\n\nfunction skipNormalizedComparison(tag, subfieldCode, subfieldValue) {\n if (tag === '020' && subfieldCode === 'a') {\n return true;\n }\n // Hackish: we want 'ntamo' to win 'Ntamo'...\n // If there are other similar excepting put them into an array.\n if (['110', '610', '710', '810'].includes(tag) && subfieldCode === 'a' && subfieldValue.substring(0, 5) === 'ntamo') {\n return true;\n }\n return false;\n}\n\nfunction mergeOrAddSubfieldNotRequired(targetField, candSubfieldData) {\n if (catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) || ennakkotietoInSubfieldG(candSubfieldData)) {\n return true;\n }\n\n if (mergeOrAddSubfieldNotRequiredSpecialCases(targetField, candSubfieldData)) {\n return true;\n }\n\n const relevantTargetSubfields = targetField.subfields.filter(sf => sf.code === candSubfieldData.code);\n // Target field does not have this subfield yet:\n if (relevantTargetSubfields.length === 0) {\n return false;\n }\n nvdebug(` Look for identical subfields in '${fieldToString(targetField)}' using`, debugDev);\n nvdebug(` ORIG. \u2021${candSubfieldData.code} ${candSubfieldData.originalValue}`, debugDev);\n nvdebug(` NO-PUNC \u2021${candSubfieldData.code} ${candSubfieldData.punctuationlessValue}`, debugDev);\n if (relevantTargetSubfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.originalValue)) {\n return true;\n }\n if (relevantTargetSubfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.punctuationlessValue)) {\n return true;\n }\n\n if (!skipNormalizedComparison(targetField.tag, candSubfieldData.code, candSubfieldData.originalValue)) {\n const normalizedTargetField = cloneAndNormalizeFieldForComparison(targetField);\n nvdebug(` Look for identical normalized subfields in '${fieldToString(normalizedTargetField)}'`, debugDev);\n nvdebug(` NO-PUNC \u2021${candSubfieldData.code} ${candSubfieldData.normalizedValue})`, debugDev);\n\n if (normalizedTargetField.subfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.normalizedValue)) {\n // Subfield with identical normalized value exists. Do nothing.\n // Not ideal 382\u2021n subfields, I guess... Nor 505\u2021trg repetitions... These need to be fixed...\n return true;\n }\n }\n\n return false; // (note that this is a double negation: not required is false)\n}\n\nfunction addSubfield(targetField, candSubfield) {\n nvdebug(` Added subfield '${subfieldToString(candSubfield)}' to field`, debugDev);\n // Add subfield to the end of all subfields. NB! Implement a separate function that does this + subfield reordering somehow...\n targetField.subfields.push(candSubfield);\n\n targetField.merged = 1;\n\n setPunctuationFlag(targetField, candSubfield);\n sortAdjacentSubfields(targetField);\n\n}\n\nfunction setPunctuationFlag(field, addedSubfield) {\n if (isControlSubfieldCode(addedSubfield.code)) { // These are never punctuation related\n return;\n }\n field.useExternalEndPunctuation = 1;\n}\n\n\nfunction resetPaired880(candFieldPair880, targetField, punctlessCandSubfield) {\n // No relevant:\n if (punctlessCandSubfield.code !== '6') {\n return;\n }\n if (targetField.tag === '880') {\n return;\n }\n // NB! $6 comes first:\n if (candFieldPair880 === undefined || !candFieldPair880.subfields || candFieldPair880.subfields[0].code !== '6') {\n return;\n\n }\n nvdebug(`880 contents: ${fieldToString(candFieldPair880)}`, debugDev);\n resetSubfield6Tag(candFieldPair880.subfields[0], targetField.tag);\n}\n\nexport function mergeOrAddSubfield(targetField, candSubfieldData, candFieldPairs880 = []) {\n\n const candSubfieldAsString = `${candSubfieldData.code} ${candSubfieldData.originalValue}`;\n\n nvdebug(` Q: mergeOrAddSubfield '${candSubfieldAsString}'\\n with field '${fieldToString(targetField)}'?`, debugDev);\n if (mergeOrAddSubfieldNotRequired(targetField, candSubfieldData)) {\n nvdebug(` A: No. No need to merge nor to add the subfield '${candSubfieldAsString}'`, debugDev);\n return;\n }\n\n const candSubfield = {'code': candSubfieldData.code, 'value': candSubfieldData.punctuationlessValue};\n\n // Currently only for X00$d 1984- => 1984-2000 type of changes, where source version is better that what base has.\n // It all other cases the original subfield is kept.\n const original = fieldToString(targetField);\n\n if (mergeSubfield(targetField, candSubfield)) { // We might need the normalizedCandSubfield later on\n mergeSubfieldPostprocessor();\n return;\n }\n\n // Subfield codes missing from the original record can be added by default:\n if (addSubfieldWithPreviouslyUnseenSubfieldCode()) {\n return;\n }\n\n // melindaCustomMergeFields.json tells us whether the subfield is repeatable or not:\n if (subfieldIsRepeatable(targetField.tag, candSubfield.code)) {\n // We don't want to add multiple, say, 260$c\n if (['260', '264'].includes(targetField.tag)) {\n nvdebug(` A: Exceptionally skip repeatable existing subfield '${subfieldToString(candSubfield)}'`, debugDev);\n return;\n }\n nvdebug(` A: Yes. Add repeatable subfield '${subfieldToString(candSubfield)}'`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n addSubfield(targetField, candSubfield);\n return;\n }\n\n nvdebug(` A: No. Non-repeatable subfield '${subfieldToString(candSubfield)}'`, debugDev);\n return;\n\n function mergeSubfieldPostprocessor() {\n if (original !== fieldToString(targetField)) {\n nvdebug(` A: Merge. Subfield '${candSubfieldAsString}' replaces the original subfield.`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n return;\n }\n nvdebug(` A: No. Field ${original} already had the same or a synonymous or a better merge candidate than our subfield '${candSubfieldAsString}'.`, debugDev);\n return;\n }\n\n function addSubfieldWithPreviouslyUnseenSubfieldCode() {\n if (!fieldHasSubfield(targetField, candSubfield.code)) {\n nvdebug(` A: Yes. Add previously unseen subfield '${subfieldToString(candSubfield)}'`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n candFieldPairs880.forEach(pair => resetPaired880(pair, targetField, candSubfield));\n addSubfield(targetField, candSubfield);\n return true;\n }\n return false;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import createDebugLogger from 'debug';\nimport {cloneAndNormalizeFieldForComparison} from '../normalizeFieldForComparison.js';\nimport {normalizeAs, normalizeControlSubfieldValue} from '../normalize-identifiers.js';\nimport {fieldHasSubfield, fieldToString, isContentSubfieldCode, nvdebug, subfieldIsRepeatable, subfieldToString} from '../utils.js';\nimport {mergeSubfield} from './mergeSubfield.js';\nimport {sortAdjacentSubfields} from '../sortSubfields.js';\n\nimport {valueCarriesMeaning} from './worldKnowledge.js';\nimport {resetSubfield6Tag} from '../subfield6Utils.js';\nimport {isEnnakkotietoSubfield} from '../prepublicationUtils.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeOrAddSubfield');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nfunction catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) {\n if (targetField.tag !== '040' || candSubfieldData.code !== 'd') {\n return false;\n }\n nvdebug(`${fieldToString(targetField)} vs $d ${candSubfieldData.originalValue}}`, debugDev);\n // Add hard-coded exceptions here\n if (targetField.subfields.some(sf => sf.code === 'a' && sf.value === candSubfieldData.originalValue)) {\n nvdebug('040\u2021d matched 040\u2021a', debugDev);\n return true;\n }\n return false;\n}\n\nfunction dataContainsPrepublicationSubfield(candSubfieldData) {\n if (isEnnakkotietoSubfield({'code': candSubfieldData.code, 'value': candSubfieldData.originalValue})) {\n // Skip just \u2021g subfield or the whole field?\n // We decided to skip just this subfield. We want at least $0 and maybe even more from ennakkotieto.\n debugDev(`Skip '\u2021${candSubfieldData.code} ${candSubfieldData.originalValue}'`);\n return true;\n }\n return false;\n}\n\n\nfunction mergeOrAddSubfieldNotRequiredSpecialCases(targetField, candSubfieldData) {\n\n // Don't bring WHATEVER<KEEP> from source 7XX to base 1XX.\n // Exceptionally we can merge <KEEP>ed 7XX with un-<KEEP>ed 1XX as 1XX should not use <KEEP>s.\n if (targetField.tag.charAt(0) === '1' && candSubfieldData.tag.charAt(0) === '7' && candSubfieldData.code === '9' && candSubfieldData.originalValue.match(/<KEEP>/u)) {\n return true;\n }\n\n // Don't add 264$b 'Kustannuspaikka tuntematon' etc\n if (!valueCarriesMeaning(targetField.tag, candSubfieldData.code, candSubfieldData.normalizedValue)) {\n return true;\n }\n\n\n // Don't add $0 subfields that mean the same even if they look different:\n const alephIdentifierType = normalizeAs(targetField.tag, candSubfieldData.code);\n if (alephIdentifierType !== undefined) {\n const normalizedSubfieldValue = normalizeControlSubfieldValue(candSubfieldData.originalValue, alephIdentifierType);\n if (targetField.subfields.some(sf => normalizeControlSubfieldValue(sf.value) === normalizedSubfieldValue && sf.code === candSubfieldData.code)) {\n return true;\n }\n }\n return false;\n}\n\n\nfunction skipNormalizedComparison(tag, subfieldCode, subfieldValue) {\n if (tag === '020' && subfieldCode === 'a') {\n return true;\n }\n // Hackish: we want 'ntamo' to win 'Ntamo'...\n // If there are other similar excepting put them into an array.\n if (['110', '610', '710', '810'].includes(tag) && subfieldCode === 'a' && subfieldValue.substring(0, 5) === 'ntamo') {\n return true;\n }\n return false;\n}\n\nfunction mergeOrAddSubfieldNotRequired(targetField, candSubfieldData) {\n if (catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) || dataContainsPrepublicationSubfield(candSubfieldData)) {\n return true;\n }\n\n if (mergeOrAddSubfieldNotRequiredSpecialCases(targetField, candSubfieldData)) {\n return true;\n }\n\n const relevantTargetSubfields = targetField.subfields.filter(sf => sf.code === candSubfieldData.code);\n // Target field does not have this subfield yet:\n if (relevantTargetSubfields.length === 0) {\n return false;\n }\n nvdebug(` Look for identical subfields in '${fieldToString(targetField)}' using`, debugDev);\n nvdebug(` ORIG. \u2021${candSubfieldData.code} ${candSubfieldData.originalValue}`, debugDev);\n nvdebug(` NO-PUNC \u2021${candSubfieldData.code} ${candSubfieldData.punctuationlessValue}`, debugDev);\n if (relevantTargetSubfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.originalValue)) {\n return true;\n }\n if (relevantTargetSubfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.punctuationlessValue)) {\n return true;\n }\n\n if (!skipNormalizedComparison(targetField.tag, candSubfieldData.code, candSubfieldData.originalValue)) {\n const normalizedTargetField = cloneAndNormalizeFieldForComparison(targetField);\n nvdebug(` Look for identical normalized subfields in '${fieldToString(normalizedTargetField)}'`, debugDev);\n nvdebug(` NO-PUNC \u2021${candSubfieldData.code} ${candSubfieldData.normalizedValue})`, debugDev);\n\n if (normalizedTargetField.subfields.some(sf => sf.code === candSubfieldData.code && sf.value === candSubfieldData.normalizedValue)) {\n // Subfield with identical normalized value exists. Do nothing.\n // Not ideal 382\u2021n subfields, I guess... Nor 505\u2021trg repetitions... These need to be fixed...\n return true;\n }\n }\n\n return false; // (note that this is a double negation: not required is false)\n}\n\nfunction addSubfield(targetField, candSubfield) {\n nvdebug(` Added subfield '${subfieldToString(candSubfield)}' to field`, debugDev);\n // Add subfield to the end of all subfields. NB! Implement a separate function that does this + subfield reordering somehow...\n targetField.subfields.push(candSubfield);\n\n targetField.merged = 1;\n\n setPunctuationFlag(targetField, candSubfield);\n sortAdjacentSubfields(targetField);\n\n}\n\nfunction setPunctuationFlag(field, addedSubfield) {\n if (!isContentSubfieldCode(addedSubfield.code, field.tag)) { // These are never punctuation related\n return;\n }\n field.useExternalEndPunctuation = 1;\n}\n\n\nfunction resetPaired880(candFieldPair880, targetField, punctlessCandSubfield) {\n // No relevant:\n if (punctlessCandSubfield.code !== '6') {\n return;\n }\n if (targetField.tag === '880') {\n return;\n }\n // NB! $6 comes first:\n if (candFieldPair880 === undefined || !candFieldPair880.subfields || candFieldPair880.subfields[0].code !== '6') {\n return;\n\n }\n nvdebug(`880 contents: ${fieldToString(candFieldPair880)}`, debugDev);\n resetSubfield6Tag(candFieldPair880.subfields[0], targetField.tag);\n}\n\nexport function mergeOrAddSubfield(targetField, candSubfieldData, candFieldPairs880 = []) {\n\n const candSubfieldAsString = `${candSubfieldData.code} ${candSubfieldData.originalValue}`;\n\n nvdebug(` Q: mergeOrAddSubfield '${candSubfieldAsString}'\\n with field '${fieldToString(targetField)}'?`, debugDev);\n if (mergeOrAddSubfieldNotRequired(targetField, candSubfieldData)) {\n nvdebug(` A: No. No need to merge nor to add the subfield '${candSubfieldAsString}'`, debugDev);\n return;\n }\n\n const candSubfield = {'code': candSubfieldData.code, 'value': candSubfieldData.punctuationlessValue};\n\n // Currently only for X00$d 1984- => 1984-2000 type of changes, where source version is better that what base has.\n // It all other cases the original subfield is kept.\n const original = fieldToString(targetField);\n\n if (mergeSubfield(targetField, candSubfield)) { // We might need the normalizedCandSubfield later on\n mergeSubfieldPostprocessor();\n return;\n }\n\n // Subfield codes missing from the original record can be added by default:\n if (addSubfieldWithPreviouslyUnseenSubfieldCode()) {\n return;\n }\n\n // melindaCustomMergeFields.json tells us whether the subfield is repeatable or not:\n if (subfieldIsRepeatable(targetField.tag, candSubfield.code)) {\n // We don't want to add multiple, say, 260$c\n if (['260', '264'].includes(targetField.tag)) {\n nvdebug(` A: Exceptionally skip repeatable existing subfield '${subfieldToString(candSubfield)}'`, debugDev);\n return;\n }\n nvdebug(` A: Yes. Add repeatable subfield '${subfieldToString(candSubfield)}'`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n addSubfield(targetField, candSubfield);\n return;\n }\n\n nvdebug(` A: No. Non-repeatable subfield '${subfieldToString(candSubfield)}'`, debugDev);\n return;\n\n function mergeSubfieldPostprocessor() {\n if (original !== fieldToString(targetField)) {\n nvdebug(` A: Merge. Subfield '${candSubfieldAsString}' replaces the original subfield.`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n return;\n }\n nvdebug(` A: No. Field ${original} already had the same or a synonymous or a better merge candidate than our subfield '${candSubfieldAsString}'.`, debugDev);\n return;\n }\n\n function addSubfieldWithPreviouslyUnseenSubfieldCode() {\n if (!fieldHasSubfield(targetField, candSubfield.code)) {\n nvdebug(` A: Yes. Add previously unseen subfield '${subfieldToString(candSubfield)}'`, debugDev);\n targetField.merged = 1;\n setPunctuationFlag(targetField, candSubfield);\n candFieldPairs880.forEach(pair => resetPaired880(pair, targetField, candSubfield));\n addSubfield(targetField, candSubfield);\n return true;\n }\n return false;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import createDebugLogger from "debug";
2
2
  import { partsAgree, subfieldContainsPartData } from "../normalizeSubfieldValueForComparison.js";
3
- import { valueCarriesMeaning } from "./worldKnowledge.js";
3
+ import { getSynonyms, valueCarriesMeaning } from "./worldKnowledge.js";
4
4
  import { nvdebug } from "../utils.js";
5
5
  import { tagAndSubfieldCodeReferToIsbn } from "../normalizeFieldForComparison.js";
6
6
  import { canContainOptionalQualifier, splitToNameAndQualifier } from "./counterpartField.js";
@@ -115,6 +115,10 @@ function pairHttpAndHttps(candSubfield, relevantSubfields) {
115
115
  return bs.includes(a);
116
116
  }
117
117
  function isSynonym(field, candSubfield, relevantSubfields) {
118
+ const finnishForm = getSynonyms(candSubfield.value, field.tag, candSubfield.code, "fin");
119
+ if (finnishForm && finnishForm === relevantSubfields.some((sf) => finnishForm === getSynonyms(sf.value, field.tag, candSubfield.code, "fin"))) {
120
+ return true;
121
+ }
118
122
  if (candSubfield.code === "q" && ["015", "020", "024", "028"].includes(field.tag)) {
119
123
  return coverTypesMatch(candSubfield, relevantSubfields);
120
124
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/merge-fields/mergeSubfield.js"],
4
- "sourcesContent": ["import createDebugLogger from 'debug';\nimport {partsAgree, subfieldContainsPartData} from '../normalizeSubfieldValueForComparison.js';\nimport {valueCarriesMeaning} from './worldKnowledge.js';\nimport {nvdebug} from '../utils.js';\nimport {tagAndSubfieldCodeReferToIsbn} from '../normalizeFieldForComparison.js';\nimport {canContainOptionalQualifier, splitToNameAndQualifier} from './counterpartField.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeSubfield');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n// NB! These are X00 specific. Should we somehow parametrize them?\nconst onlyBirthYear = /^[1-9][0-9]*-[,.]?$/u;\nconst onlyDeathYear = /^-[1-9][0-9]*[,.]?$/u;\nconst birthYearAndDeathYear = /^[1-9][0-9]*-[1-9][0-9]*[,.]?$/u;\n\nfunction getDeathYear(str) {\n return parseInt(str.substring(str.indexOf('-') + 1), 10);\n}\n\nfunction isValidBirthYearAndDeathYear(str) {\n if (!birthYearAndDeathYear.test(str)) {\n return false;\n }\n // We have two years\n const b = parseInt(str, 10);\n const d = getDeathYear(str);\n if (b > d) { // died before birth! Rather unlikely.\n return false;\n }\n if (d - b > 125) { // Over 125 years old. Rather unlikely.\n return false;\n }\n // Possible sanity check: Died after current year?\n return true;\n}\n\nfunction anyYear(str) {\n if (onlyBirthYear.test(str) || onlyDeathYear.test(str) || isValidBirthYearAndDeathYear(str)) {\n return true;\n }\n return false;\n}\n\nfunction replaceEntrysBirthAndDeathYear(targetField, candSubfield, relevantSubfields) {\n if (birthYearAndDeathYear.test(candSubfield.value)) {\n if (onlyBirthYear.test(relevantSubfields[0].value) && parseInt(relevantSubfields[0].value, 10) === parseInt(candSubfield.value, 10)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n\n if (onlyDeathYear.test(relevantSubfields[0].value) && getDeathYear(relevantSubfields[0].value) === getDeathYear(candSubfield.value)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n }\n return false;\n}\n\nfunction replaceDatesAssociatedWithName(targetField, candSubfield, relevantSubfields) {\n // Add also the death year, if the original value only contains birth year.\n // This function treats only with X00$d subfields:\n if (candSubfield.code !== 'd' || !(/^[1678]00$/u).test(targetField.tag)) { // njsscan-ignore: regex_dos\n return false;\n }\n\n if (!anyYear(relevantSubfields[0].value) && anyYear(candSubfield.value)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n\n if (replaceEntrysBirthAndDeathYear(targetField, candSubfield, relevantSubfields)) {\n return true;\n }\n return false;\n}\n\n// use array.includes(value) for easy extendability (Swedish, other languages, abbrs, etc.()\nfunction isKierreselka(value) {\n return ['kierreselk\u00E4', 'spiral bound', 'spiral-bound', 'spiralrygg'].includes(value);\n}\n\nfunction isKovakantinen(value) {\n return ['hardback', 'hardcover', 'h\u00E5rda p\u00E4rmar', 'kovakantinen'].includes(value);\n}\n\nfunction isPehmeakantinen(value) {\n return ['mjuka p\u00E4rmar', 'paperback', 'pehme\u00E4kantinen', 'softcover'].includes(value);\n}\n\nfunction isItsenainenJatkoOsa(value) {\n if (value.match(/^Frist\u00E5ende forts\u00E4ttning p\u00E5 verket[^a-z]*$/ui)) {\n return true;\n }\n if (value.match(/^Itsen\u00E4inen jatko-osa teokselle[^a-z]*$/ui)) {\n return true;\n }\n return false;\n}\n\nfunction isSisaltaaTeos(value) {\n if (value.match(/^Inneh\u00E5ller \\(verk\\)[^a-z]*$/ui)) {\n return true;\n }\n if (value.match(/^Sis\u00E4lt\u00E4\u00E4 \\(teos\\)[^a-z]*$/ui)) {\n return true;\n }\n return false;\n}\nfunction relationInformationMatches(candSubfield, relevantSubfields) {\n if (isSisaltaaTeos(candSubfield.value) && relevantSubfields.some(sf => isSisaltaaTeos(sf.value))) {\n return true;\n }\n if (isItsenainenJatkoOsa(candSubfield.value) && relevantSubfields.some(sf => isItsenainenJatkoOsa(sf.value))) {\n return true;\n }\n\n return false;\n}\n\nfunction coverTypesMatch(candSubfield, relevantSubfields) {\n if (isPehmeakantinen(candSubfield.value) && relevantSubfields.some(sf => isPehmeakantinen(sf.value))) {\n return true;\n }\n if (isKovakantinen(candSubfield.value) && relevantSubfields.some(sf => isKovakantinen(sf.value))) {\n return true;\n }\n if (isKierreselka(candSubfield.value) && relevantSubfields.some(sf => isKierreselka(sf.value))) {\n return true;\n }\n return false;\n}\n\nfunction httpToHttps(val) {\n return val.replace(/http:\\/\\//ug, 'https://');\n}\n\nfunction pairHttpAndHttps(candSubfield, relevantSubfields) {\n const a = httpToHttps(candSubfield.value);\n const bs = relevantSubfields.map(sf => httpToHttps(sf.value));\n return bs.includes(a);\n}\n\nfunction isSynonym(field, candSubfield, relevantSubfields) {\n if (candSubfield.code === 'q' && ['015', '020', '024', '028'].includes(field.tag)) {\n return coverTypesMatch(candSubfield, relevantSubfields);\n }\n\n //nvdebug(`Looking for synonyms for '${subfieldToString(candSubfield)}'...`, debugDev);\n\n if (relationInformationMatches(candSubfield, relevantSubfields)) {\n return true;\n }\n\n if (pairHttpAndHttps(candSubfield, relevantSubfields)) {\n return true;\n }\n\n return false;\n}\n\nfunction preferHyphenatedISBN(field, candSubfield, relevantSubfields) {\n if (!tagAndSubfieldCodeReferToIsbn(field.tag, candSubfield.code) || candSubfield.value.includes('-') === -1) {\n return false;\n }\n\n // Must not already exist:\n if (relevantSubfields.some(sf => sf.value === candSubfield.value)) {\n return false;\n }\n\n const hyphenlessSubfields = relevantSubfields.filter(sf => sf.value.includes('-') > -1);\n const pair = hyphenlessSubfields.find(sf => sf.value === candSubfield.value.replace(/-/gu, ''));\n if (!pair) {\n return false;\n }\n pair.value = candSubfield.value;\n return true;\n}\n\nfunction preferHttpsOverHttp(candSubfield, relevantSubfields) {\n if (candSubfield.value.substring(0, 8) !== 'https://') {\n return false;\n }\n\n const httpVersion = `http://${candSubfield.value.substring(8)}`;\n const pair = relevantSubfields.find(sf => sf.value === httpVersion);\n\n if (!pair) {\n return false;\n }\n pair.value = candSubfield.value;\n return true;\n}\n\n\nfunction preferQualifierVersion(field, candSubfield, relevantSubfields) {\n if (!canContainOptionalQualifier(field.tag, candSubfield.code)) { // currently only 300$a and 776$i can prefer source...\n return false;\n }\n\n const [name1, qualifier1] = splitToNameAndQualifier(candSubfield.value);\n const pair = relevantSubfields.find(sf => subfieldQualifierCheck(sf, name1, qualifier1));\n if (!pair) {\n return false;\n }\n // SN: \"Kuvailuohjeiden n\u00E4k\u00F6kulmasta epubille ei pit\u00E4isi koskaan merkit\u00E4 sivum\u00E4\u00E4r\u00E4\u00E4\"\n if (field.tag === '300' && candSubfield.code === 'a' && candSubfield.value.match(/(?:online|verkko)/iu)) {\n return true; // True, but don't prefer the source value\n }\n\n pair.value = candSubfield.value;\n return true;\n\n function subfieldQualifierCheck(subfield, name, qualifier) {\n const [name2, qualifier2] = splitToNameAndQualifier(candSubfield.value);\n if (name !== name2) {\n return false;\n }\n if (!qualifier || !qualifier2 || qualifier === qualifier2) {\n return true;\n }\n return false;\n }\n\n}\n\nfunction preferSourceCorporateName(field, candSubfield, pair) {\n if (candSubfield.code !== 'a' || !['110', '610', '710', '810'].includes(field.tag)) {\n return false;\n }\n nvdebug(`CORP base '${pair.value}' vs '${candSubfield.value}'`, debugDev);\n const prefer = actualPrefenceCheck();\n if (prefer) {\n pair.value = candSubfield.value;\n return true;\n }\n return false;\n\n function actualPrefenceCheck() {\n if (candSubfield.value.match(/^Werner S\u00F6derstr\u00F6m/u) && pair.value.match(/^WSOY/ui)) {\n return true;\n }\n if (candSubfield.value.match(/^ntamo/u) && pair.value.match(/^N(?:tamo|TAMO)/u)) {\n return true;\n }\n // Prefer (qualifier):\n const [sourceName, sourceQualifier] = splitToNameAndQualifier(candSubfield.value);\n const [baseName, baseQualifier] = splitToNameAndQualifier(pair.value);\n if (sourceName === baseName && baseQualifier === undefined && sourceQualifier !== undefined) {\n return true;\n }\n // Not taking prefix and suffix into account here...\n return false;\n }\n\n}\n\nexport function mergeSubfield(targetField, candSubfield) {\n // Replace existing subfield with the incoming field. These replacements are by name rather hacky...\n // Currenty we only select the better X00$d.\n // In future we might do more things here. Examples:\n // - \"FOO\" gets replaced by \"Foo\" in certain fields.\n // - \"Etunimi Sukunimi\" might lose to \"Sukunimi, Etunimi\" in X00 fields.\n // - [put your ideas here]\n // Return true, if replace is done.\n // However, replacing/succeeding requires a sanity check, that the new value is a better one...\n // Thus, typically this function fails...\n\n const relevantSubfields = targetField.subfields.filter(subfield => subfield.code === candSubfield.code);\n\n // There's nothing to replace the incoming subfield with. Thus abort:\n if (relevantSubfields.length === 0) {\n return false;\n }\n\n nvdebug(`Got ${relevantSubfields.length} sf-cand(s) for field ${targetField.tag}\u2021${candSubfield.code}`, debugDev);\n\n\n if (replaceDatesAssociatedWithName(targetField, candSubfield, relevantSubfields) ||\n preferHyphenatedISBN(targetField, candSubfield, relevantSubfields) ||\n preferHttpsOverHttp(candSubfield, relevantSubfields) ||\n preferSourceCorporateName(targetField, candSubfield, relevantSubfields[0]) || // SF is non-repeat\n preferQualifierVersion(targetField, candSubfield, relevantSubfields) ||\n isSynonym(targetField, candSubfield, relevantSubfields)) {\n return true;\n }\n\n // We found a crappy empty subfield: replace that with a meaningful one.\n // 260 $a value \"[S.l]\" is the main type for this.\n const meaninglessSubfields = relevantSubfields.filter(sf => !valueCarriesMeaning(targetField.tag, sf.code, sf.value));\n if (meaninglessSubfields.length > 0) {\n meaninglessSubfields[0].value = candSubfield.value;\n return true;\n }\n\n // Mark 490$v \"osa 1\" vs \"1\" as merged (2nd part of MET-53).\n // NB! Keeps the original value and drops the incoming value. (Just preventing it from going to add-part...)\n // NB! We could improve this and choose the longer value later on.\n if (subfieldContainsPartData(targetField.tag, candSubfield.code)) {\n if (relevantSubfields.some(sf => partsAgree(sf.value, candSubfield.value, targetField.tag, candSubfield.code))) {\n return true;\n }\n }\n return false; // default to failure\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import createDebugLogger from 'debug';\nimport {partsAgree, subfieldContainsPartData} from '../normalizeSubfieldValueForComparison.js';\nimport {getSynonyms, valueCarriesMeaning} from './worldKnowledge.js';\nimport {nvdebug} from '../utils.js';\nimport {tagAndSubfieldCodeReferToIsbn} from '../normalizeFieldForComparison.js';\nimport {canContainOptionalQualifier, splitToNameAndQualifier} from './counterpartField.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeSubfield');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n// NB! These are X00 specific. Should we somehow parametrize them?\nconst onlyBirthYear = /^[1-9][0-9]*-[,.]?$/u;\nconst onlyDeathYear = /^-[1-9][0-9]*[,.]?$/u;\nconst birthYearAndDeathYear = /^[1-9][0-9]*-[1-9][0-9]*[,.]?$/u;\n\nfunction getDeathYear(str) {\n return parseInt(str.substring(str.indexOf('-') + 1), 10);\n}\n\nfunction isValidBirthYearAndDeathYear(str) {\n if (!birthYearAndDeathYear.test(str)) {\n return false;\n }\n // We have two years\n const b = parseInt(str, 10);\n const d = getDeathYear(str);\n if (b > d) { // died before birth! Rather unlikely.\n return false;\n }\n if (d - b > 125) { // Over 125 years old. Rather unlikely.\n return false;\n }\n // Possible sanity check: Died after current year?\n return true;\n}\n\nfunction anyYear(str) {\n if (onlyBirthYear.test(str) || onlyDeathYear.test(str) || isValidBirthYearAndDeathYear(str)) {\n return true;\n }\n return false;\n}\n\nfunction replaceEntrysBirthAndDeathYear(targetField, candSubfield, relevantSubfields) {\n if (birthYearAndDeathYear.test(candSubfield.value)) {\n if (onlyBirthYear.test(relevantSubfields[0].value) && parseInt(relevantSubfields[0].value, 10) === parseInt(candSubfield.value, 10)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n\n if (onlyDeathYear.test(relevantSubfields[0].value) && getDeathYear(relevantSubfields[0].value) === getDeathYear(candSubfield.value)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n }\n return false;\n}\n\nfunction replaceDatesAssociatedWithName(targetField, candSubfield, relevantSubfields) {\n // Add also the death year, if the original value only contains birth year.\n // This function treats only with X00$d subfields:\n if (candSubfield.code !== 'd' || !(/^[1678]00$/u).test(targetField.tag)) { // njsscan-ignore: regex_dos\n return false;\n }\n\n if (!anyYear(relevantSubfields[0].value) && anyYear(candSubfield.value)) {\n relevantSubfields[0].value = candSubfield.value;\n return true;\n }\n\n if (replaceEntrysBirthAndDeathYear(targetField, candSubfield, relevantSubfields)) {\n return true;\n }\n return false;\n}\n\n// use array.includes(value) for easy extendability (Swedish, other languages, abbrs, etc.()\nfunction isKierreselka(value) {\n return ['kierreselk\u00E4', 'spiral bound', 'spiral-bound', 'spiralrygg'].includes(value);\n}\n\nfunction isKovakantinen(value) {\n return ['hardback', 'hardcover', 'h\u00E5rda p\u00E4rmar', 'kovakantinen'].includes(value);\n}\n\nfunction isPehmeakantinen(value) {\n return ['mjuka p\u00E4rmar', 'paperback', 'pehme\u00E4kantinen', 'softcover'].includes(value);\n}\n\nfunction isItsenainenJatkoOsa(value) { // Probably movable to synonyms...\n if (value.match(/^Frist\u00E5ende forts\u00E4ttning p\u00E5 verket[^a-z]*$/ui)) {\n return true;\n }\n if (value.match(/^Itsen\u00E4inen jatko-osa teokselle[^a-z]*$/ui)) {\n return true;\n }\n return false;\n}\n\nfunction isSisaltaaTeos(value) {\n if (value.match(/^Inneh\u00E5ller \\(verk\\)[^a-z]*$/ui)) {\n return true;\n }\n if (value.match(/^Sis\u00E4lt\u00E4\u00E4 \\(teos\\)[^a-z]*$/ui)) {\n return true;\n }\n return false;\n}\nfunction relationInformationMatches(candSubfield, relevantSubfields) {\n if (isSisaltaaTeos(candSubfield.value) && relevantSubfields.some(sf => isSisaltaaTeos(sf.value))) {\n return true;\n }\n if (isItsenainenJatkoOsa(candSubfield.value) && relevantSubfields.some(sf => isItsenainenJatkoOsa(sf.value))) {\n return true;\n }\n\n return false;\n}\n\nfunction coverTypesMatch(candSubfield, relevantSubfields) {\n if (isPehmeakantinen(candSubfield.value) && relevantSubfields.some(sf => isPehmeakantinen(sf.value))) {\n return true;\n }\n if (isKovakantinen(candSubfield.value) && relevantSubfields.some(sf => isKovakantinen(sf.value))) {\n return true;\n }\n if (isKierreselka(candSubfield.value) && relevantSubfields.some(sf => isKierreselka(sf.value))) {\n return true;\n }\n return false;\n}\n\nfunction httpToHttps(val) {\n return val.replace(/http:\\/\\//ug, 'https://');\n}\n\nfunction pairHttpAndHttps(candSubfield, relevantSubfields) {\n const a = httpToHttps(candSubfield.value);\n const bs = relevantSubfields.map(sf => httpToHttps(sf.value));\n return bs.includes(a);\n}\n\nfunction isSynonym(field, candSubfield, relevantSubfields) {\n\n const finnishForm = getSynonyms(candSubfield.value, field.tag, candSubfield.code, 'fin');\n if (finnishForm && finnishForm === relevantSubfields.some(sf => finnishForm === getSynonyms(sf.value, field.tag, candSubfield.code, 'fin'))) {\n // NB! There's currently no intelligence (such as checking cat language from 040$b): the preferred value is the one in base.\n // We might later on create a separate translation validator/fixer...\n return true;\n }\n\n\n if (candSubfield.code === 'q' && ['015', '020', '024', '028'].includes(field.tag)) {\n return coverTypesMatch(candSubfield, relevantSubfields);\n }\n\n //nvdebug(`Looking for synonyms for '${subfieldToString(candSubfield)}'...`, debugDev);\n\n if (relationInformationMatches(candSubfield, relevantSubfields)) {\n return true;\n }\n\n if (pairHttpAndHttps(candSubfield, relevantSubfields)) {\n return true;\n }\n\n return false;\n}\n\nfunction preferHyphenatedISBN(field, candSubfield, relevantSubfields) {\n if (!tagAndSubfieldCodeReferToIsbn(field.tag, candSubfield.code) || candSubfield.value.includes('-') === -1) {\n return false;\n }\n\n // Must not already exist:\n if (relevantSubfields.some(sf => sf.value === candSubfield.value)) {\n return false;\n }\n\n const hyphenlessSubfields = relevantSubfields.filter(sf => sf.value.includes('-') > -1);\n const pair = hyphenlessSubfields.find(sf => sf.value === candSubfield.value.replace(/-/gu, ''));\n if (!pair) {\n return false;\n }\n pair.value = candSubfield.value;\n return true;\n}\n\nfunction preferHttpsOverHttp(candSubfield, relevantSubfields) {\n if (candSubfield.value.substring(0, 8) !== 'https://') {\n return false;\n }\n\n const httpVersion = `http://${candSubfield.value.substring(8)}`;\n const pair = relevantSubfields.find(sf => sf.value === httpVersion);\n\n if (!pair) {\n return false;\n }\n pair.value = candSubfield.value;\n return true;\n}\n\n\nfunction preferQualifierVersion(field, candSubfield, relevantSubfields) {\n if (!canContainOptionalQualifier(field.tag, candSubfield.code)) { // currently only 300$a and 776$i can prefer source...\n return false;\n }\n\n const [name1, qualifier1] = splitToNameAndQualifier(candSubfield.value);\n const pair = relevantSubfields.find(sf => subfieldQualifierCheck(sf, name1, qualifier1));\n if (!pair) {\n return false;\n }\n // SN: \"Kuvailuohjeiden n\u00E4k\u00F6kulmasta epubille ei pit\u00E4isi koskaan merkit\u00E4 sivum\u00E4\u00E4r\u00E4\u00E4\"\n if (field.tag === '300' && candSubfield.code === 'a' && candSubfield.value.match(/(?:online|verkko)/iu)) {\n return true; // True, but don't prefer the source value\n }\n\n pair.value = candSubfield.value;\n return true;\n\n function subfieldQualifierCheck(subfield, name, qualifier) {\n const [name2, qualifier2] = splitToNameAndQualifier(candSubfield.value);\n if (name !== name2) {\n return false;\n }\n if (!qualifier || !qualifier2 || qualifier === qualifier2) {\n return true;\n }\n return false;\n }\n\n}\n\nfunction preferSourceCorporateName(field, candSubfield, pair) {\n if (candSubfield.code !== 'a' || !['110', '610', '710', '810'].includes(field.tag)) {\n return false;\n }\n nvdebug(`CORP base '${pair.value}' vs '${candSubfield.value}'`, debugDev);\n const prefer = actualPrefenceCheck();\n if (prefer) {\n pair.value = candSubfield.value;\n return true;\n }\n return false;\n\n function actualPrefenceCheck() {\n if (candSubfield.value.match(/^Werner S\u00F6derstr\u00F6m/u) && pair.value.match(/^WSOY/ui)) {\n return true;\n }\n if (candSubfield.value.match(/^ntamo/u) && pair.value.match(/^N(?:tamo|TAMO)/u)) {\n return true;\n }\n // Prefer (qualifier):\n const [sourceName, sourceQualifier] = splitToNameAndQualifier(candSubfield.value);\n const [baseName, baseQualifier] = splitToNameAndQualifier(pair.value);\n if (sourceName === baseName && baseQualifier === undefined && sourceQualifier !== undefined) {\n return true;\n }\n // Not taking prefix and suffix into account here...\n return false;\n }\n\n}\n\nexport function mergeSubfield(targetField, candSubfield) {\n // Replace existing subfield with the incoming field. These replacements are by name rather hacky...\n // Currenty we only select the better X00$d.\n // In future we might do more things here. Examples:\n // - \"FOO\" gets replaced by \"Foo\" in certain fields.\n // - \"Etunimi Sukunimi\" might lose to \"Sukunimi, Etunimi\" in X00 fields.\n // - [put your ideas here]\n // Return true, if replace is done.\n // However, replacing/succeeding requires a sanity check, that the new value is a better one...\n // Thus, typically this function fails...\n\n const relevantSubfields = targetField.subfields.filter(subfield => subfield.code === candSubfield.code);\n\n // There's nothing to replace the incoming subfield with. Thus abort:\n if (relevantSubfields.length === 0) {\n return false;\n }\n\n nvdebug(`Got ${relevantSubfields.length} sf-cand(s) for field ${targetField.tag}\u2021${candSubfield.code}`, debugDev);\n\n\n if (replaceDatesAssociatedWithName(targetField, candSubfield, relevantSubfields) ||\n preferHyphenatedISBN(targetField, candSubfield, relevantSubfields) ||\n preferHttpsOverHttp(candSubfield, relevantSubfields) ||\n preferSourceCorporateName(targetField, candSubfield, relevantSubfields[0]) || // SF is non-repeat\n preferQualifierVersion(targetField, candSubfield, relevantSubfields) ||\n isSynonym(targetField, candSubfield, relevantSubfields)) {\n return true;\n }\n\n // We found a crappy empty subfield: replace that with a meaningful one.\n // 260 $a value \"[S.l]\" is the main type for this.\n const meaninglessSubfields = relevantSubfields.filter(sf => !valueCarriesMeaning(targetField.tag, sf.code, sf.value));\n if (meaninglessSubfields.length > 0) {\n meaninglessSubfields[0].value = candSubfield.value;\n return true;\n }\n\n // Mark 490$v \"osa 1\" vs \"1\" as merged (2nd part of MET-53).\n // NB! Keeps the original value and drops the incoming value. (Just preventing it from going to add-part...)\n // NB! We could improve this and choose the longer value later on.\n if (subfieldContainsPartData(targetField.tag, candSubfield.code)) {\n if (relevantSubfields.some(sf => partsAgree(sf.value, candSubfield.value, targetField.tag, candSubfield.code))) {\n return true;\n }\n }\n return false; // default to failure\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -14,7 +14,59 @@ export function valueCarriesMeaning(tag, subfieldCode, value) {
14
14
  }
15
15
  return true;
16
16
  }
17
+ const synonyms = [
18
+ { tags: ["700", "710", "711", "730"], code: "i", "fin": "Sis\xE4lt\xE4\xE4 (ekspressio)", "swe": "Inneh\xE5ller (uttryck)" },
19
+ { tags: ["700", "710", "711", "730"], code: "i", "fin": "Sis\xE4lt\xE4\xE4 (teos)", "swe": "Inneh\xE5ller (verk)" },
20
+ { tags: ["700", "710", "711", "730"], code: "l", "fin": "Englanti", "swe": "Engelska" },
21
+ { tags: ["700", "710", "711", "730"], code: "l", "fin": "Ruotsi", "swe": "Svenska" },
22
+ { tags: ["700", "710", "711", "730"], code: "l", "fin": "Suomi", "swe": "Finska" }
23
+ // There might eventually be need for a list of terms is given language (eg. engl. paperback and softcover)
24
+ ];
25
+ export function getSynonyms(term, tag = void 0, subfieldCode = void 0, preferredLanguage = void 0, ignoreCase = true, relevantLanguagesString = "fin swe") {
26
+ if (!term) {
27
+ return [];
28
+ }
29
+ const relevantLanguges = relevantLanguagesString.split(/\s+/u);
30
+ const normalizedTerm = ignoreCase ? term.toLowerCase() : term;
31
+ const synonymsWithTag = tag ? synonyms.filter((s) => s.tags.includes(tag)) : synonyms;
32
+ if (synonymsWithTag.length === 0) {
33
+ return [];
34
+ }
35
+ const synonymsWithTagAndCode = subfieldCode ? synonymsWithTag.filter((s) => s.code === subfieldCode) : synonymsWithTag;
36
+ const matchingSynonyms = synonymsWithTagAndCode.filter((s) => termAndLangMatch(s));
37
+ if (preferredLanguage && matchingSynonyms.length > 0) {
38
+ return matchingSynonyms.map((s) => s[preferredLanguage]);
39
+ }
40
+ return matchingSynonyms;
41
+ function termAndLangMatch(synonym) {
42
+ if (relevantLanguges.includes("fin")) {
43
+ if (ignoreCase && synonym.fin.toLowerCase() === normalizedTerm) {
44
+ return true;
45
+ }
46
+ if (!ignoreCase && synonym.fin === term) {
47
+ return true;
48
+ }
49
+ }
50
+ if (relevantLanguges.includes("swe")) {
51
+ if (ignoreCase && synonym.swe.toLowerCase() === normalizedTerm) {
52
+ return true;
53
+ }
54
+ if (!ignoreCase && synonym.swe === term) {
55
+ return true;
56
+ }
57
+ }
58
+ return false;
59
+ }
60
+ }
61
+ export function getSynonym(tag, subfieldCode, originalValue) {
62
+ const finnishForm = getSynonyms(originalValue, tag, subfieldCode, "fin");
63
+ if (finnishForm.length === 1) {
64
+ return finnishForm[0];
65
+ }
66
+ return originalValue;
67
+ }
17
68
  export function normalizeForSamenessCheck(tag, subfieldCode, originalValue) {
69
+ originalValue = getSynonym(tag, subfieldCode, originalValue);
18
70
  if (subfieldCode === "a" && ["100", "600", "700", "800"].includes(tag)) {
19
71
  return normalizePersonalName(originalValue);
20
72
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/merge-fields/worldKnowledge.js"],
4
- "sourcesContent": ["//import {nvdebug} from '../utils';\n\nexport function valueCarriesMeaning(tag, subfieldCode, value) {\n // Some data is pretty meaningless and as meaningless is pretty close to nothing, this meaningless data should no prevent merge.\n // The list below is incomples (swedish translations etc)\n if (tag === '260' || tag === '264') {\n // We drop these, instead of normalizing, as KV does not put this information in place...\n if (subfieldCode === 'a') {\n if (value.match(/^[^a-z]*(?:Kustannuspaikka tuntematon|S\\.l)[^a-z]*$/ui)) {\n return false;\n }\n }\n if (subfieldCode === 'b') {\n if (value.match(/^[^a-z]*(?:Kustantaja tuntematon|S\\.n)[^a-z]*$/ui)) {\n return false;\n }\n }\n return true;\n }\n return true;\n}\n\nexport function normalizeForSamenessCheck(tag, subfieldCode, originalValue) {\n // NB! These work only for non-repeatable subfields!\n // Repeatable subfields are currently handled in mergeSubfields.js. Only non-repeatable subfields block field merge,\n // (This split is suboptiomal... Minimum fix: make this disctinction cleaner...)\n if (subfieldCode === 'a' && ['100', '600', '700', '800'].includes(tag)) {\n return normalizePersonalName(originalValue);\n }\n\n // NB! originalValue should already be lowercased, stripped on initial '[' chars and postpunctuation.\n if (tag === '250' && subfieldCode === 'a') {\n return normalizeEditionStatement(originalValue);\n }\n\n // 506 - Restrictions on Access Note (R), $a - Terms governing access (NR)\n if (tag === '506' && subfieldCode === 'a') {\n return normalize506a(originalValue);\n }\n\n if (tag === '534' && subfieldCode === 'p') {\n return normalizeOriginalVersionNoteIntroductoryPhrase(originalValue);\n }\n\n return originalValue;\n}\n\n\nfunction normalizePersonalName(originalValue) {\n // Use more readable \"Forename Surname\" format in comparisons:\n return originalValue.replace(/^([^,]+), ([^,]+)$/u, '$2 $1');\n}\n\nconst sallittu506a = ['sallittu kaikenik\u00E4isille', 'sallittu', 's']; // downcased, without punctuation\nfunction normalize506a(originalValue) {\n if (sallittu506a.includes(originalValue)) {\n return sallittu506a[0];\n }\n return originalValue;\n}\n\nconst introductoryPhrasesMeaning1 = ['alkuper\u00E4inen', 'alkuper\u00E4isen julkaisutiedot', 'alun perin julkaistu', 'alunperin julkaistu'];\nfunction normalizeOriginalVersionNoteIntroductoryPhrase(originalValue) {\n // MELKEHITYS-1935-ish:\n if (introductoryPhrasesMeaning1.includes(originalValue)) {\n return introductoryPhrasesMeaning1[0];\n }\n\n return originalValue;\n}\n\nfunction normalizeEditionStatement(originalValue) {\n const value = originalValue;\n\n // As normalization tries to translate things info Finnish, use this for similarity check only!\n if (value.match(/^[1-9][0-9]*(?:\\.|:a|nd|rd|st|th) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n const nth = value.replace(/[^0-9].*$/u, '');\n return `${nth}. painos`;\n }\n\n // Quick and dirty fix for\n if (value.match(/^[1-9][0-9]*(?:\\.|:a|nd|rd|st|th)(?: f\u00F6rnyade|,? rev\\.| uud\\.| uudistettu) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n const nth = value.replace(/[^0-9].*$/u, '');\n return `${nth}. uudistettu painos`;\n }\n\n if (value.match(/^(?:First|F\u00F6rsta|Ensimm\u00E4inen) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `1. painos`;\n }\n\n if (value.match(/^(?:Andra|Second|Toinen) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `2. painos`;\n }\n\n if (value.match(/^(?:Kolmas|Third|Tredje) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `3. painos`;\n }\n\n if (value.match(/^(?:Fourth|Fj\u00E4rde|Nelj\u00E4s) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `4. painos`;\n }\n\n return originalValue;\n}\n"],
5
- "mappings": "AAEO,gBAAS,oBAAoB,KAAK,cAAc,OAAO;AAG5D,MAAI,QAAQ,SAAS,QAAQ,OAAO;AAElC,QAAI,iBAAiB,KAAK;AACxB,UAAI,MAAM,MAAM,uDAAuD,GAAG;AACxE,eAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,iBAAiB,KAAK;AACxB,UAAI,MAAM,MAAM,kDAAkD,GAAG;AACnE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,gBAAS,0BAA0B,KAAK,cAAc,eAAe;AAI1E,MAAI,iBAAiB,OAAO,CAAC,OAAO,OAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AACtE,WAAO,sBAAsB,aAAa;AAAA,EAC5C;AAGA,MAAI,QAAQ,SAAS,iBAAiB,KAAK;AACzC,WAAO,0BAA0B,aAAa;AAAA,EAChD;AAGA,MAAI,QAAQ,SAAS,iBAAiB,KAAK;AACzC,WAAO,cAAc,aAAa;AAAA,EACpC;AAEA,MAAI,QAAQ,SAAS,iBAAiB,KAAK;AACzC,WAAO,+CAA+C,aAAa;AAAA,EACrE;AAEA,SAAO;AACT;AAGA,SAAS,sBAAsB,eAAe;AAE5C,SAAO,cAAc,QAAQ,uBAAuB,OAAO;AAC7D;AAEA,MAAM,eAAe,CAAC,+BAA4B,YAAY,GAAG;AACjE,SAAS,cAAc,eAAe;AACpC,MAAI,aAAa,SAAS,aAAa,GAAG;AACxC,WAAO,aAAa,CAAC;AAAA,EACvB;AACA,SAAO;AACT;AAEA,MAAM,8BAA8B,CAAC,mBAAgB,kCAA+B,wBAAwB,qBAAqB;AACjI,SAAS,+CAA+C,eAAe;AAErE,MAAI,4BAA4B,SAAS,aAAa,GAAG;AACvD,WAAO,4BAA4B,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,SAAS,0BAA0B,eAAe;AAChD,QAAM,QAAQ;AAGd,MAAI,MAAM,MAAM,2FAA2F,GAAG;AAC5G,UAAM,MAAM,MAAM,QAAQ,cAAc,EAAE;AAC1C,WAAO,GAAG,GAAG;AAAA,EACf;AAGA,MAAI,MAAM,MAAM,oIAAoI,GAAG;AACrJ,UAAM,MAAM,MAAM,QAAQ,cAAc,EAAE;AAC1C,WAAO,GAAG,GAAG;AAAA,EACf;AAEA,MAAI,MAAM,MAAM,uFAAuF,GAAG;AACxG,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,MAAM,kFAAkF,GAAG;AACnG,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,MAAM,kFAAkF,GAAG;AACnG,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,MAAM,mFAAmF,GAAG;AACpG,WAAO;AAAA,EACT;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["//import {nvdebug} from '../utils.js';\n//import createDebugLogger from 'debug';\n\n// NB! This file (or at least synonyms) should eventually be moved away from merge to '..'.\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:worldKnowledge');\n//const debugData = debug.extend('data');\n//const debugDev = debug.extend('dev');\n\n\nexport function valueCarriesMeaning(tag, subfieldCode, value) {\n // Some data is pretty meaningless and as meaningless is pretty close to nothing, this meaningless data should no prevent merge.\n // The list below is incomples (swedish translations etc)\n if (tag === '260' || tag === '264') {\n // We drop these, instead of normalizing, as KV does not put this information in place...\n if (subfieldCode === 'a') {\n if (value.match(/^[^a-z]*(?:Kustannuspaikka tuntematon|S\\.l)[^a-z]*$/ui)) {\n return false;\n }\n }\n if (subfieldCode === 'b') {\n if (value.match(/^[^a-z]*(?:Kustantaja tuntematon|S\\.n)[^a-z]*$/ui)) {\n return false;\n }\n }\n return true;\n }\n return true;\n}\n\nconst synonyms = [\n {tags: ['700', '710', '711', '730'], code: 'i', 'fin': 'Sis\u00E4lt\u00E4\u00E4 (ekspressio)', 'swe': 'Inneh\u00E5ller (uttryck)'},\n {tags: ['700', '710', '711', '730'], code: 'i', 'fin': 'Sis\u00E4lt\u00E4\u00E4 (teos)', 'swe': 'Inneh\u00E5ller (verk)'},\n {tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Englanti', 'swe': 'Engelska'},\n {tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Ruotsi', 'swe': 'Svenska'},\n {tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Suomi', 'swe': 'Finska'}\n // There might eventually be need for a list of terms is given language (eg. engl. paperback and softcover)\n];\n\nexport function getSynonyms(term, tag = undefined, subfieldCode = undefined, preferredLanguage = undefined, ignoreCase = true, relevantLanguagesString = 'fin swe',) {\n if (!term) {\n return [];\n }\n //nvdebug(`WP1 CANDS: ${synonyms.length} FOR '${term}'`, debugDev);\n const relevantLanguges = relevantLanguagesString.split(/\\s+/u);\n const normalizedTerm = ignoreCase ? term.toLowerCase() : term;\n const synonymsWithTag = tag ? synonyms.filter(s => s.tags.includes(tag)) : synonyms;\n if (synonymsWithTag.length === 0) {\n return [];\n }\n //nvdebug(`WP2 (FILTER ${tag}) CANDS: ${synonymsWithTag.length}`, debugDev);\n const synonymsWithTagAndCode = subfieldCode ? synonymsWithTag.filter(s => s.code === subfieldCode) : synonymsWithTag;\n //nvdebug(`WP3 (FILTER $${subfieldCode}) CANDS: ${synonymsWithTagAndCode.length}:\\n${JSON.stringify(synonymsWithTagAndCode)}`, debugDev);\n const matchingSynonyms = synonymsWithTagAndCode.filter(s => termAndLangMatch(s));\n\n if (preferredLanguage && matchingSynonyms.length > 0) {\n //console.log(`USING PREFERRED LANG '${preferredLanguage}' for TERM '${term}':\\n${JSON.stringify(matchingSynonyms)}`, debugDev);\n return matchingSynonyms.map(s => s[preferredLanguage]);\n }\n return matchingSynonyms;\n\n function termAndLangMatch(synonym) {\n if (relevantLanguges.includes('fin')) {\n if (ignoreCase && synonym.fin.toLowerCase() === normalizedTerm ) {\n return true;\n }\n if (!ignoreCase && synonym.fin === term) {\n return true;\n }\n }\n\n if (relevantLanguges.includes('swe')) {\n if (ignoreCase && synonym.swe.toLowerCase() === normalizedTerm ) {\n return true;\n }\n if (!ignoreCase && synonym.swe === term) {\n return true;\n }\n }\n return false;\n }\n}\n\nexport function getSynonym(tag, subfieldCode, originalValue) {\n const finnishForm = getSynonyms(originalValue, tag, subfieldCode, 'fin');\n if (finnishForm.length === 1) {\n //nvdebug(`FINNISH FORM FOR ${tag}$${subfieldCode}: '${finnishForm[0]}'`, debugDev);\n return finnishForm[0];\n }\n return originalValue;\n}\n\nexport function normalizeForSamenessCheck(tag, subfieldCode, originalValue) {\n // NB! These work only for non-repeatable subfields!\n // Repeatable subfields are currently handled in mergeSubfields.js. Only non-repeatable subfields block field merge,\n // (This split is suboptiomal... Minimum fix: make this distinction cleaner...)\n\n //nvdebug(`TRYING TO DO ${tag}$${subfieldCode} '${originalValue}'`, debugDev);\n originalValue = getSynonym(tag, subfieldCode, originalValue);\n\n if (subfieldCode === 'a' && ['100', '600', '700', '800'].includes(tag)) { // \"Etunimi Sukunimi\"...\n return normalizePersonalName(originalValue);\n }\n\n // NB! originalValue should already be lowercased, stripped on initial '[' chars and postpunctuation.\n if (tag === '250' && subfieldCode === 'a') {\n return normalizeEditionStatement(originalValue);\n }\n\n // 506 - Restrictions on Access Note (R), $a - Terms governing access (NR)\n if (tag === '506' && subfieldCode === 'a') {\n return normalize506a(originalValue);\n }\n\n if (tag === '534' && subfieldCode === 'p') {\n return normalizeOriginalVersionNoteIntroductoryPhrase(originalValue);\n }\n\n return originalValue;\n}\n\n\nfunction normalizePersonalName(originalValue) {\n // Use more readable \"Forename Surname\" format in comparisons:\n return originalValue.replace(/^([^,]+), ([^,]+)$/u, '$2 $1');\n}\n\nconst sallittu506a = ['sallittu kaikenik\u00E4isille', 'sallittu', 's']; // downcased, without punctuation\nfunction normalize506a(originalValue) {\n if (sallittu506a.includes(originalValue)) {\n return sallittu506a[0];\n }\n return originalValue;\n}\n\nconst introductoryPhrasesMeaning1 = ['alkuper\u00E4inen', 'alkuper\u00E4isen julkaisutiedot', 'alun perin julkaistu', 'alunperin julkaistu'];\nfunction normalizeOriginalVersionNoteIntroductoryPhrase(originalValue) {\n // MELKEHITYS-1935-ish:\n if (introductoryPhrasesMeaning1.includes(originalValue)) {\n return introductoryPhrasesMeaning1[0];\n }\n\n return originalValue;\n}\n\nfunction normalizeEditionStatement(originalValue) {\n const value = originalValue;\n\n // As normalization tries to translate things info Finnish, use this for similarity check only!\n if (value.match(/^[1-9][0-9]*(?:\\.|:a|nd|rd|st|th) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n const nth = value.replace(/[^0-9].*$/u, '');\n return `${nth}. painos`;\n }\n\n // Quick and dirty fix for\n if (value.match(/^[1-9][0-9]*(?:\\.|:a|nd|rd|st|th)(?: f\u00F6rnyade|,? rev\\.| uud\\.| uudistettu) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n const nth = value.replace(/[^0-9].*$/u, '');\n return `${nth}. uudistettu painos`;\n }\n\n if (value.match(/^(?:First|F\u00F6rsta|Ensimm\u00E4inen) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `1. painos`;\n }\n\n if (value.match(/^(?:Andra|Second|Toinen) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `2. painos`;\n }\n\n if (value.match(/^(?:Kolmas|Third|Tredje) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `3. painos`;\n }\n\n if (value.match(/^(?:Fourth|Fj\u00E4rde|Nelj\u00E4s) (?:ed\\.?|edition|p\\.?|painos|uppl\\.?|upplagan)[.\\]]*$/ui)) {\n return `4. painos`;\n }\n\n return originalValue;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,9 @@
1
- import assert from "node:assert";
1
+ import assert from "node:assert/strict";
2
2
  import { MarcRecord } from "@natlibfi/marc-record";
3
3
  import validatorFactory from "./merge-fields/index.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
6
  import createDebugLogger from "debug";
7
- import { nvdebug } from "./utils.js";
8
7
  generateTests({
9
8
  callback,
10
9
  path: [import.meta.dirname, "..", "test-fixtures", "merge-fields"],
@@ -26,12 +25,8 @@ async function testValidatorFactory() {
26
25
  assert.equal(typeof validator.description, "string");
27
26
  assert.equal(typeof validator.validate, "function");
28
27
  }
29
- async function callback({ getFixture, enabled = true, fix = false, tagPattern = false }) {
30
- if (enabled === false) {
31
- debug("TEST SKIPPED!");
32
- return;
33
- }
34
- nvdebug(`TAG PATTERN: ${tagPattern}`);
28
+ async function callback({ getFixture, fix = false, tagPattern = false }) {
29
+ debug(`Run test using tag pattern ${tagPattern}`);
35
30
  const validator = await validatorFactory(tagPattern);
36
31
  const record = new MarcRecord(getFixture("record.json"));
37
32
  const expectedResult = getFixture("expectedResult.json");
@@ -41,6 +36,6 @@ async function callback({ getFixture, enabled = true, fix = false, tagPattern =
41
36
  return;
42
37
  }
43
38
  await validator.fix(record);
44
- assert.deepEqual(record, expectedResult);
39
+ assert.deepEqual(record, new MarcRecord(expectedResult));
45
40
  }
46
41
  //# sourceMappingURL=merge-fields.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/merge-fields.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './merge-fields/index.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\nimport { nvdebug } from './utils.js';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'merge-fields'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/merge-fields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false, tagPattern = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n nvdebug(`TAG PATTERN: ${tagPattern}`);\n\n const validator = await validatorFactory(tagPattern);\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n // NB! This validator will only use tags matching /^[1678](?:00|10|11|30)$/ unless tagPattern is specified!\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAC9B,SAAS,eAAe;AAExB,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,cAAc;AAAA,EACjE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,4DAA4D;AAE5F,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,OAAO,aAAa,MAAK,GAAG;AACrF,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,UAAQ,gBAAgB,UAAU,EAAE;AAEpC,QAAM,YAAY,MAAM,iBAAiB,UAAU;AACnD,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAIvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
4
+ "sourcesContent": ["import assert from 'node:assert/strict';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './merge-fields/index.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'merge-fields'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/merge-fields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false, tagPattern = false}) {\n debug(`Run test using tag pattern ${tagPattern}`);\n\n const validator = await validatorFactory(tagPattern);\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n // NB! This validator will only use tags matching /^[1678](?:00|10|11|30)$/ unless tagPattern is specified!\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, new MarcRecord(expectedResult));\n}\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAG9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,cAAc;AAAA,EACjE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,4DAA4D;AAE5F,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,OAAO,aAAa,MAAK,GAAG;AACrE,QAAM,8BAA8B,UAAU,EAAE;AAEhD,QAAM,YAAY,MAAM,iBAAiB,UAAU;AACnD,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAIvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,IAAI,WAAW,cAAc,CAAC;AACzD;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
3
3
  import validatorFactory from "./mergeField500Lisapainokset.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
- import createDebugLogger from "debug";
7
6
  generateTests({
8
7
  callback,
9
8
  path: [import.meta.dirname, "..", "test-fixtures", "lisapainokset"],
@@ -18,18 +17,13 @@ generateTests({
18
17
  }
19
18
  }
20
19
  });
21
- const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/mergeField500Lisapainokset:test");
22
20
  async function testValidatorFactory() {
23
21
  const validator = await validatorFactory();
24
22
  assert.equal(typeof validator, "object");
25
23
  assert.equal(typeof validator.description, "string");
26
24
  assert.equal(typeof validator.validate, "function");
27
25
  }
28
- async function callback({ getFixture, enabled = true, fix = false }) {
29
- if (enabled === false) {
30
- debug("TEST SKIPPED!");
31
- return;
32
- }
26
+ async function callback({ getFixture, fix = false }) {
33
27
  const validator = await validatorFactory();
34
28
  const record = new MarcRecord(getFixture("record.json"));
35
29
  const expectedResult = getFixture("expectedResult.json");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/mergeField500Lisapainokset.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './mergeField500Lisapainokset.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'lisapainokset'],\n useMetadataFile: true,\n recurse: true,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeField500Lisapainokset:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAE9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,eAAe;AAAA,EAClE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,0EAA0E;AAE1G,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAK,GAAG;AACjE,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './mergeField500Lisapainokset.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'lisapainokset'],\n useMetadataFile: true,\n recurse: true,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeField500Lisapainokset:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,eAAe;AAAA,EAClE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAGD,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
6
6
  "names": []
7
7
  }
@@ -3,6 +3,9 @@ import { fieldFixPunctuation, fieldStripPunctuation } from "./punctuation2.js";
3
3
  import { fieldToString, nvdebug } from "./utils.js";
4
4
  import { sortAdjacentSubfields } from "./sortSubfields.js";
5
5
  import { sortAdjacentRelatorTerms, tagToRelatorTermSubfieldCode } from "./sortRelatorTerms.js";
6
+ import createDebugLogger from "debug";
7
+ const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields");
8
+ const debugDev = debug.extend("dev");
6
9
  export default function() {
7
10
  return {
8
11
  description: "Merge author fields that only differ in $e relator terms",
@@ -52,26 +55,26 @@ function mergeRelatorTermFields(record, fix = false) {
52
55
  let fields = record.get("(?:[17][01]0|720)");
53
56
  let result = [];
54
57
  const comparisonFieldsAsString = fields.map((f) => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));
55
- nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`);
58
+ nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`, debugDev);
56
59
  for (let i = 0; i < fields.length - 1; i++) {
57
60
  let currField = fields[i];
58
61
  if (currField.deleted) {
59
62
  continue;
60
63
  }
61
- nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`);
64
+ nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`, debugDev);
62
65
  for (let j = i + 1; j < fields.length; j++) {
63
- nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`);
66
+ nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`, debugDev);
64
67
  let mergableField = fields[j];
65
68
  if (comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {
66
- nvdebug(" NOT PAIR");
69
+ nvdebug(" NOT PAIR", debugDev);
67
70
  continue;
68
71
  }
69
72
  if (mergableField.deleted) {
70
- nvdebug(" DELETED");
73
+ nvdebug(" DELETED", debugDev);
71
74
  continue;
72
75
  }
73
76
  const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;
74
- nvdebug(str);
77
+ nvdebug(str, debugDev);
75
78
  if (!result.includes(str)) {
76
79
  result.push(str);
77
80
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/mergeRelatorTermFields.js"],
4
- "sourcesContent": ["// Merge author/agent fields\n//\n// Rationale: Same author can appear in one 1XX and multiple 7XX fields having only different $e subfields.\n// These fields can be merged (and $e-subfields can then be sorted)...\n//\n// Author(s): Nicholas Volk\n\n\nimport clone from 'clone';\nimport {fieldFixPunctuation, fieldStripPunctuation} from './punctuation2.js';\nimport {fieldToString, nvdebug} from './utils.js';\nimport {sortAdjacentSubfields} from './sortSubfields.js';\nimport {sortAdjacentRelatorTerms, tagToRelatorTermSubfieldCode} from './sortRelatorTerms.js';\n//import createDebugLogger from 'debug';\n/*\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');\n//const debugData = debug.extend('data');\n*/\n\nexport default function () {\n\n return {\n description: 'Merge author fields that only differ in $e relator terms',\n validate, fix\n };\n\n function fix(record) {\n const msg = mergeRelatorTermFields(record, true);\n const res = {message: msg, fix: msg, valid: true};\n return res;\n }\n\n function validate(record) {\n const msg = mergeRelatorTermFields(record, false);\n const res = {message: msg};\n\n res.valid = !(res.message.length >= 1);\n return res;\n }\n}\n\nfunction createNormalizedClone(field) {\n const clonedField = clone(field);\n // Normalize\n fieldStripPunctuation(clonedField);\n return clonedField;\n}\n\nfunction createNormalizedCloneWithoutRelatorTerms(field) {\n const clonedField = createNormalizedClone(field);\n // Remove relator terms $e subfi:\n clonedField.subfields = clonedField.subfields.filter(sf => sf.code !== 'e');\n return clonedField;\n}\n\nfunction getRelatorTermStrings(relatorTermSubfieldCode, field) {\n return field.subfields.filter(sf => sf.code === relatorTermSubfieldCode).map(sf => sf.value);\n\n}\n\nfunction extractAddableRelatorTerms(fromField, toField) {\n const relatorTermSubfieldCode = tagToRelatorTermSubfieldCode(fromField.tag);\n const normalizedFromFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, fromField);\n if (normalizedFromFieldRelatorTerms.length === 0) {\n return [];\n }\n // Remove values that already exist:\n const normalizedToFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, toField);\n return normalizedFromFieldRelatorTerms.filter(str => !normalizedToFieldRelatorTerms.includes(str));\n}\n\n\nfunction copyRelatorSubfields(fromField, toField) {\n const relatorTermSubfieldCode = tagToRelatorTermSubfieldCode(fromField.tag);\n const newRelatorTerms = extractAddableRelatorTerms(fromField, toField);\n\n newRelatorTerms.forEach(term => toField.subfields.push({code: relatorTermSubfieldCode, value: term}));\n\n}\n\nfunction mergeRelatorTermFields(record, fix = false) {\n // NV: 111/711, 751 and 752 where so rare that I did not add them here. Can't remember why I skipped 6XX and 8XX...\n let fields = record.get('(?:[17][01]0|720)'); \n let result = [];\n const comparisonFieldsAsString = fields.map(f => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));\n\n nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`);\n for(let i=0; i < fields.length-1; i++) {\n let currField = fields[i];\n if (currField.deleted) {\n continue;\n }\n nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`);\n for (let j=i+1; j < fields.length; j++) {\n nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`);\n let mergableField = fields[j];\n // Skip 1/7 from 1XX/7XX for similarity check:\n if ( comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {\n nvdebug(\" NOT PAIR\");\n continue;\n }\n if (mergableField.deleted) {\n nvdebug(\" DELETED\");\n continue;\n }\n const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;\n nvdebug(str);\n\n if(!result.includes(str)) {\n result.push(str)\n }\n\n if (fix) {\n mergableField.deleted = 1;\n copyRelatorSubfields(mergableField, currField);\n fieldFixPunctuation(currField);\n sortAdjacentSubfields(currField); // Put the added $e subfield to proper places.\n sortAdjacentRelatorTerms(currField); // Sort $e subfields with each other\n fieldFixPunctuation(currField);\n\n }\n }\n }\n\n if(!fix) {\n fields.forEach(f => delete f.deleted);\n }\n\n record.fields = record.fields.filter(f => !f.deleted);\n return result;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Merge author/agent fields\n//\n// Rationale: Same author can appear in one 1XX and multiple 7XX fields having only different $e subfields.\n// These fields can be merged (and $e-subfields can then be sorted)...\n//\n// Author(s): Nicholas Volk\n\n\nimport clone from 'clone';\nimport {fieldFixPunctuation, fieldStripPunctuation} from './punctuation2.js';\nimport {fieldToString, nvdebug} from './utils.js';\nimport {sortAdjacentSubfields} from './sortSubfields.js';\nimport {sortAdjacentRelatorTerms, tagToRelatorTermSubfieldCode} from './sortRelatorTerms.js';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n\nexport default function () {\n\n return {\n description: 'Merge author fields that only differ in $e relator terms',\n validate, fix\n };\n\n function fix(record) {\n const msg = mergeRelatorTermFields(record, true);\n const res = {message: msg, fix: msg, valid: true};\n return res;\n }\n\n function validate(record) {\n const msg = mergeRelatorTermFields(record, false);\n const res = {message: msg};\n\n res.valid = !(res.message.length >= 1);\n return res;\n }\n}\n\nfunction createNormalizedClone(field) {\n const clonedField = clone(field);\n // Normalize\n fieldStripPunctuation(clonedField);\n return clonedField;\n}\n\nfunction createNormalizedCloneWithoutRelatorTerms(field) {\n const clonedField = createNormalizedClone(field);\n // Remove relator terms $e subfi:\n clonedField.subfields = clonedField.subfields.filter(sf => sf.code !== 'e');\n return clonedField;\n}\n\nfunction getRelatorTermStrings(relatorTermSubfieldCode, field) {\n return field.subfields.filter(sf => sf.code === relatorTermSubfieldCode).map(sf => sf.value);\n\n}\n\nfunction extractAddableRelatorTerms(fromField, toField) {\n const relatorTermSubfieldCode = tagToRelatorTermSubfieldCode(fromField.tag);\n const normalizedFromFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, fromField);\n if (normalizedFromFieldRelatorTerms.length === 0) {\n return [];\n }\n // Remove values that already exist:\n const normalizedToFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, toField);\n return normalizedFromFieldRelatorTerms.filter(str => !normalizedToFieldRelatorTerms.includes(str));\n}\n\n\nfunction copyRelatorSubfields(fromField, toField) {\n const relatorTermSubfieldCode = tagToRelatorTermSubfieldCode(fromField.tag);\n const newRelatorTerms = extractAddableRelatorTerms(fromField, toField);\n\n newRelatorTerms.forEach(term => toField.subfields.push({code: relatorTermSubfieldCode, value: term}));\n\n}\n\nfunction mergeRelatorTermFields(record, fix = false) {\n // NV: 111/711, 751 and 752 where so rare that I did not add them here. Can't remember why I skipped 6XX and 8XX...\n let fields = record.get('(?:[17][01]0|720)');\n let result = [];\n const comparisonFieldsAsString = fields.map(f => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));\n\n nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`, debugDev);\n for(let i=0; i < fields.length-1; i++) {\n let currField = fields[i];\n if (currField.deleted) {\n continue;\n }\n nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`, debugDev);\n for (let j=i+1; j < fields.length; j++) {\n nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`, debugDev);\n let mergableField = fields[j];\n // Skip 1/7 from 1XX/7XX for similarity check:\n if ( comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {\n nvdebug(\" NOT PAIR\", debugDev);\n continue;\n }\n if (mergableField.deleted) {\n nvdebug(\" DELETED\", debugDev);\n continue;\n }\n const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;\n nvdebug(str, debugDev);\n\n if(!result.includes(str)) {\n result.push(str)\n }\n\n if (fix) {\n mergableField.deleted = 1;\n copyRelatorSubfields(mergableField, currField);\n fieldFixPunctuation(currField);\n sortAdjacentSubfields(currField); // Put the added $e subfield to proper places.\n sortAdjacentRelatorTerms(currField); // Sort $e subfields with each other\n fieldFixPunctuation(currField);\n\n }\n }\n }\n\n if(!fix) {\n fields.forEach(f => delete f.deleted);\n }\n\n record.fields = record.fields.filter(f => !f.deleted);\n return result;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
3
3
  import validatorFactory from "./mergeRelatorTermFields.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
- import createDebugLogger from "debug";
7
6
  generateTests({
8
7
  callback,
9
8
  path: [import.meta.dirname, "..", "test-fixtures", "mergeRelatorTermFields"],
@@ -18,18 +17,13 @@ generateTests({
18
17
  }
19
18
  }
20
19
  });
21
- const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test");
22
20
  async function testValidatorFactory() {
23
21
  const validator = await validatorFactory();
24
22
  assert.equal(typeof validator, "object");
25
23
  assert.equal(typeof validator.description, "string");
26
24
  assert.equal(typeof validator.validate, "function");
27
25
  }
28
- async function callback({ getFixture, enabled = true, fix = false }) {
29
- if (enabled === false) {
30
- debug("TEST SKIPPED!");
31
- return;
32
- }
26
+ async function callback({ getFixture, fix = false }) {
33
27
  const validator = await validatorFactory();
34
28
  const record = new MarcRecord(getFixture("record.json"));
35
29
  const expectedResult = getFixture("expectedResult.json");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/mergeRelatorTermFields.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './mergeRelatorTermFields.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'mergeRelatorTermFields'],\n useMetadataFile: true,\n recurse: true,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAE9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,wBAAwB;AAAA,EAC3E,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,sEAAsE;AAEtG,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAK,GAAG;AACjE,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './mergeRelatorTermFields.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'mergeRelatorTermFields'],\n useMetadataFile: true,\n recurse: true,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,wBAAwB;AAAA,EAC3E,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAGD,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
3
3
  import validatorFactory from "./multiple-subfield-0.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
- import createDebugLogger from "debug";
7
6
  generateTests({
8
7
  callback,
9
8
  path: [import.meta.dirname, "..", "test-fixtures", "subfield0"],
@@ -18,18 +17,13 @@ generateTests({
18
17
  }
19
18
  }
20
19
  });
21
- const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/multiple-subfield-0:test");
22
20
  async function testValidatorFactory() {
23
21
  const validator = await validatorFactory();
24
22
  assert.equal(typeof validator, "object");
25
23
  assert.equal(typeof validator.description, "string");
26
24
  assert.equal(typeof validator.validate, "function");
27
25
  }
28
- async function callback({ getFixture, enabled = true, fix = false }) {
29
- if (enabled === false) {
30
- debug("TEST SKIPPED!");
31
- return;
32
- }
26
+ async function callback({ getFixture, fix = false }) {
33
27
  const validator = await validatorFactory();
34
28
  const record = new MarcRecord(getFixture("record.json"));
35
29
  const expectedResult = getFixture("expectedResult.json");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/multiple-subfield-0.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './multiple-subfield-0.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'subfield0'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/multiple-subfield-0:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAE9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,WAAW;AAAA,EAC9D,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAED,MAAM,QAAQ,kBAAkB,mEAAmE;AAEnG,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAK,GAAG;AACjE,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './multiple-subfield-0.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'subfield0'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/multiple-subfield-0:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,WAAW;AAAA,EAC9D,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
6
6
  "names": []
7
7
  }