@natlibfi/marc-record-validators-melinda 3.2.0 → 3.3.14-alpha.3

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 (593) hide show
  1. package/.github/CODEOWNERS +2 -0
  2. package/.github/dependabot.yml +40 -0
  3. package/.github/workflows/melinda-node-tests.yml +61 -0
  4. package/LICENSE.txt +21 -661
  5. package/README.md +4 -5
  6. package/dist/access-rights.js +94 -0
  7. package/dist/access-rights.js.map +1 -0
  8. package/dist/access-rights.spec.js +150 -0
  9. package/dist/access-rights.spec.js.map +1 -0
  10. package/dist/double-commas.js +17 -27
  11. package/dist/double-commas.js.map +1 -1
  12. package/dist/double-commas.spec.js +72 -27
  13. package/dist/double-commas.spec.js.map +1 -1
  14. package/dist/duplicates-ind1.js +47 -27
  15. package/dist/duplicates-ind1.js.map +1 -1
  16. package/dist/duplicates-ind1.spec.js +44 -27
  17. package/dist/duplicates-ind1.spec.js.map +1 -1
  18. package/dist/empty-fields.js +79 -29
  19. package/dist/empty-fields.js.map +1 -1
  20. package/dist/empty-fields.spec.js +113 -27
  21. package/dist/empty-fields.spec.js.map +1 -1
  22. package/dist/ending-punctuation-conf.js +772 -129
  23. package/dist/ending-punctuation-conf.js.map +1 -1
  24. package/dist/ending-punctuation.js +291 -72
  25. package/dist/ending-punctuation.js.map +1 -1
  26. package/dist/ending-punctuation.spec.js +2638 -118
  27. package/dist/ending-punctuation.spec.js.map +1 -1
  28. package/dist/ending-whitespace.js +58 -0
  29. package/dist/ending-whitespace.js.map +1 -0
  30. package/dist/ending-whitespace.spec.js +42 -0
  31. package/dist/ending-whitespace.spec.js.map +1 -0
  32. package/dist/field-521-fix.js +96 -0
  33. package/dist/field-521-fix.js.map +1 -0
  34. package/dist/field-521-fix.spec.js +51 -0
  35. package/dist/field-521-fix.spec.js.map +1 -0
  36. package/dist/field-exclusion.js +214 -63
  37. package/dist/field-exclusion.js.map +1 -1
  38. package/dist/field-exclusion.spec.js +1057 -31
  39. package/dist/field-exclusion.spec.js.map +1 -1
  40. package/dist/field-structure.js +249 -78
  41. package/dist/field-structure.js.map +1 -1
  42. package/dist/field-structure.spec.js +534 -31
  43. package/dist/field-structure.spec.js.map +1 -1
  44. package/dist/fields-present.js +31 -27
  45. package/dist/fields-present.js.map +1 -1
  46. package/dist/fields-present.spec.js +120 -27
  47. package/dist/fields-present.spec.js.map +1 -1
  48. package/dist/fixed-fields.js +72 -27
  49. package/dist/fixed-fields.js.map +1 -1
  50. package/dist/fixed-fields.spec.js +139 -27
  51. package/dist/fixed-fields.spec.js.map +1 -1
  52. package/dist/identical-fields.js +42 -28
  53. package/dist/identical-fields.js.map +1 -1
  54. package/dist/identical-fields.spec.js +98 -27
  55. package/dist/identical-fields.spec.js.map +1 -1
  56. package/dist/index.js +202 -27
  57. package/dist/index.js.map +1 -1
  58. package/dist/indicator-fixes.js +191 -0
  59. package/dist/indicator-fixes.js.map +1 -0
  60. package/dist/indicator-fixes.spec.js +51 -0
  61. package/dist/indicator-fixes.spec.js.map +1 -0
  62. package/dist/isbn-issn.js +266 -27
  63. package/dist/isbn-issn.js.map +1 -1
  64. package/dist/isbn-issn.spec.js +594 -27
  65. package/dist/isbn-issn.spec.js.map +1 -1
  66. package/dist/item-language.js +171 -27
  67. package/dist/item-language.js.map +1 -1
  68. package/dist/item-language.spec.js +305 -27
  69. package/dist/item-language.spec.js.map +1 -1
  70. package/dist/mergeField500Lisapainokset.js +155 -0
  71. package/dist/mergeField500Lisapainokset.js.map +1 -0
  72. package/dist/mergeField500Lisapainokset.spec.js +51 -0
  73. package/dist/mergeField500Lisapainokset.spec.js.map +1 -0
  74. package/dist/mergeRelatorTermFields.js +140 -0
  75. package/dist/mergeRelatorTermFields.js.map +1 -0
  76. package/dist/mergeRelatorTermFields.spec.js +51 -0
  77. package/dist/mergeRelatorTermFields.spec.js.map +1 -0
  78. package/dist/multiple-subfield-0.js +120 -0
  79. package/dist/multiple-subfield-0.js.map +1 -0
  80. package/dist/multiple-subfield-0.spec.js +51 -0
  81. package/dist/multiple-subfield-0.spec.js.map +1 -0
  82. package/dist/non-breaking-space.js +61 -0
  83. package/dist/non-breaking-space.js.map +1 -0
  84. package/dist/non-breaking-space.spec.js +42 -0
  85. package/dist/non-breaking-space.spec.js.map +1 -0
  86. package/dist/normalize-identifiers.js +210 -0
  87. package/dist/normalize-identifiers.js.map +1 -0
  88. package/dist/normalize-identifiers.spec.js +51 -0
  89. package/dist/normalize-identifiers.spec.js.map +1 -0
  90. package/dist/normalize-utf8-diacritics.js +140 -0
  91. package/dist/normalize-utf8-diacritics.js.map +1 -0
  92. package/dist/normalize-utf8-diacritics.spec.js +51 -0
  93. package/dist/normalize-utf8-diacritics.spec.js.map +1 -0
  94. package/dist/punctuation/index.js +281 -0
  95. package/dist/punctuation/index.js.map +1 -0
  96. package/dist/punctuation/rules/aut.js +332 -0
  97. package/dist/punctuation/rules/aut.js.map +1 -0
  98. package/dist/punctuation/rules/bib.js +374 -0
  99. package/dist/punctuation/rules/bib.js.map +1 -0
  100. package/dist/punctuation/rules/index.js +21 -0
  101. package/dist/punctuation/rules/index.js.map +1 -0
  102. package/dist/punctuation.spec.js +51 -0
  103. package/dist/punctuation.spec.js.map +1 -0
  104. package/dist/punctuation2.js +726 -0
  105. package/dist/punctuation2.js.map +1 -0
  106. package/dist/punctuation2.spec.js +51 -0
  107. package/dist/punctuation2.spec.js.map +1 -0
  108. package/dist/reindexSubfield6OccurenceNumbers.js +199 -0
  109. package/dist/reindexSubfield6OccurenceNumbers.js.map +1 -0
  110. package/dist/reindexSubfield6OccurenceNumbers.spec.js +51 -0
  111. package/dist/reindexSubfield6OccurenceNumbers.spec.js.map +1 -0
  112. package/dist/removeDuplicateDataFields.js +405 -0
  113. package/dist/removeDuplicateDataFields.js.map +1 -0
  114. package/dist/removeDuplicateDataFields.spec.js +51 -0
  115. package/dist/removeDuplicateDataFields.spec.js.map +1 -0
  116. package/dist/removeInferiorDataFields.js +245 -0
  117. package/dist/removeInferiorDataFields.js.map +1 -0
  118. package/dist/removeInferiorDataFields.spec.js +51 -0
  119. package/dist/removeInferiorDataFields.spec.js.map +1 -0
  120. package/dist/resolvable-ext-references-melinda.js +112 -31
  121. package/dist/resolvable-ext-references-melinda.js.map +1 -1
  122. package/dist/resolvable-ext-references-melinda.spec.js +166 -27
  123. package/dist/resolvable-ext-references-melinda.spec.js.map +1 -1
  124. package/dist/resolveOrphanedSubfield6s.js +116 -0
  125. package/dist/resolveOrphanedSubfield6s.js.map +1 -0
  126. package/dist/resolveOrphanedSubfield6s.spec.js +51 -0
  127. package/dist/resolveOrphanedSubfield6s.spec.js.map +1 -0
  128. package/dist/sanitize-vocabulary-source-codes.js +93 -0
  129. package/dist/sanitize-vocabulary-source-codes.js.map +1 -0
  130. package/dist/sanitize-vocabulary-source-codes.spec.js +51 -0
  131. package/dist/sanitize-vocabulary-source-codes.spec.js.map +1 -0
  132. package/dist/sort-tags.js +53 -27
  133. package/dist/sort-tags.js.map +1 -1
  134. package/dist/sort-tags.spec.js +206 -27
  135. package/dist/sort-tags.spec.js.map +1 -1
  136. package/dist/sortRelatorTerms.js +135 -0
  137. package/dist/sortRelatorTerms.js.map +1 -0
  138. package/dist/sortRelatorTerms.spec.js +51 -0
  139. package/dist/sortRelatorTerms.spec.js.map +1 -0
  140. package/dist/sortSubfields.js +279 -0
  141. package/dist/sortSubfields.js.map +1 -0
  142. package/dist/sortSubfields.spec.js +51 -0
  143. package/dist/sortSubfields.spec.js.map +1 -0
  144. package/dist/stripPunctuation.js +49 -0
  145. package/dist/stripPunctuation.js.map +1 -0
  146. package/dist/stripPunctuation.spec.js +51 -0
  147. package/dist/stripPunctuation.spec.js.map +1 -0
  148. package/dist/subfield-exclusion.js +174 -57
  149. package/dist/subfield-exclusion.js.map +1 -1
  150. package/dist/subfield-exclusion.spec.js +521 -31
  151. package/dist/subfield-exclusion.spec.js.map +1 -1
  152. package/dist/subfield6Utils.js +457 -0
  153. package/dist/subfield6Utils.js.map +1 -0
  154. package/dist/subfield8Utils.js +99 -0
  155. package/dist/subfield8Utils.js.map +1 -0
  156. package/dist/typeOfDate-008.js +48 -0
  157. package/dist/typeOfDate-008.js.map +1 -0
  158. package/dist/typeOfDate-008.spec.js +47 -0
  159. package/dist/typeOfDate-008.spec.js.map +1 -0
  160. package/dist/unicode-decomposition.js +139 -30
  161. package/dist/unicode-decomposition.js.map +1 -1
  162. package/dist/unicode-decomposition.spec.js +90 -27
  163. package/dist/unicode-decomposition.spec.js.map +1 -1
  164. package/dist/update-field-540.js +119 -0
  165. package/dist/update-field-540.js.map +1 -0
  166. package/dist/update-field-540.spec.js +51 -0
  167. package/dist/update-field-540.spec.js.map +1 -0
  168. package/dist/urn.js +185 -0
  169. package/dist/urn.js.map +1 -0
  170. package/dist/urn.spec.js +238 -0
  171. package/dist/urn.spec.js.map +1 -0
  172. package/dist/utils.js +58 -0
  173. package/dist/utils.js.map +1 -0
  174. package/package.json +114 -124
  175. package/src/access-rights.js +84 -0
  176. package/src/access-rights.spec.js +126 -0
  177. package/src/double-commas.js +12 -49
  178. package/src/double-commas.spec.js +50 -82
  179. package/src/duplicates-ind1.js +34 -74
  180. package/src/duplicates-ind1.spec.js +39 -117
  181. package/src/empty-fields.js +62 -74
  182. package/src/empty-fields.spec.js +134 -207
  183. package/src/ending-punctuation-conf.js +679 -644
  184. package/src/ending-punctuation.js +260 -250
  185. package/src/ending-punctuation.spec.js +2545 -2322
  186. package/src/ending-whitespace.js +40 -0
  187. package/src/ending-whitespace.spec.js +44 -0
  188. package/src/field-521-fix.js +92 -0
  189. package/src/field-521-fix.spec.js +52 -0
  190. package/src/field-exclusion.js +197 -215
  191. package/src/field-exclusion.spec.js +883 -481
  192. package/src/field-structure.js +213 -271
  193. package/src/field-structure.spec.js +597 -474
  194. package/src/fields-present.js +19 -49
  195. package/src/fields-present.spec.js +90 -91
  196. package/src/fixed-fields.js +61 -94
  197. package/src/fixed-fields.spec.js +81 -125
  198. package/src/identical-fields.js +29 -48
  199. package/src/identical-fields.spec.js +114 -146
  200. package/src/index.js +41 -46
  201. package/src/indicator-fixes.js +211 -0
  202. package/src/indicator-fixes.spec.js +52 -0
  203. package/src/isbn-issn.js +254 -106
  204. package/src/isbn-issn.spec.js +399 -172
  205. package/src/item-language.js +158 -195
  206. package/src/item-language.spec.js +314 -306
  207. package/src/mergeField500Lisapainokset.js +153 -0
  208. package/src/mergeField500Lisapainokset.spec.js +52 -0
  209. package/src/mergeRelatorTermFields.js +143 -0
  210. package/src/mergeRelatorTermFields.spec.js +52 -0
  211. package/src/multiple-subfield-0.js +129 -0
  212. package/src/multiple-subfield-0.spec.js +52 -0
  213. package/src/non-breaking-space.js +49 -0
  214. package/src/non-breaking-space.spec.js +44 -0
  215. package/src/normalize-identifiers.js +197 -0
  216. package/src/normalize-identifiers.spec.js +52 -0
  217. package/src/normalize-utf8-diacritics.js +141 -0
  218. package/src/normalize-utf8-diacritics.spec.js +52 -0
  219. package/src/punctuation/index.js +292 -0
  220. package/src/punctuation/rules/aut.js +372 -0
  221. package/src/punctuation/rules/bib.js +420 -0
  222. package/src/punctuation/rules/index.js +7 -0
  223. package/src/punctuation.spec.js +52 -0
  224. package/src/punctuation2.js +441 -0
  225. package/src/punctuation2.spec.js +52 -0
  226. package/src/reindexSubfield6OccurenceNumbers.js +210 -0
  227. package/src/reindexSubfield6OccurenceNumbers.spec.js +52 -0
  228. package/src/removeDuplicateDataFields.js +447 -0
  229. package/src/removeDuplicateDataFields.spec.js +52 -0
  230. package/src/removeInferiorDataFields.js +259 -0
  231. package/src/removeInferiorDataFields.spec.js +52 -0
  232. package/src/resolvable-ext-references-melinda.js +89 -122
  233. package/src/resolvable-ext-references-melinda.spec.js +168 -198
  234. package/src/resolveOrphanedSubfield6s.js +115 -0
  235. package/src/resolveOrphanedSubfield6s.spec.js +52 -0
  236. package/src/sanitize-vocabulary-source-codes.js +99 -0
  237. package/src/sanitize-vocabulary-source-codes.spec.js +52 -0
  238. package/src/sort-tags.js +34 -60
  239. package/src/sort-tags.spec.js +256 -290
  240. package/src/sortRelatorTerms.js +142 -0
  241. package/src/sortRelatorTerms.spec.js +52 -0
  242. package/src/sortSubfields.js +176 -0
  243. package/src/sortSubfields.spec.js +52 -0
  244. package/src/stripPunctuation.js +42 -0
  245. package/src/stripPunctuation.spec.js +52 -0
  246. package/src/subfield-exclusion.js +157 -180
  247. package/src/subfield-exclusion.spec.js +507 -453
  248. package/src/subfield6Utils.js +485 -0
  249. package/src/subfield8Utils.js +102 -0
  250. package/src/typeOfDate-008.js +40 -0
  251. package/src/typeOfDate-008.spec.js +47 -0
  252. package/src/unicode-decomposition.js +130 -145
  253. package/src/unicode-decomposition.spec.js +89 -115
  254. package/src/update-field-540.js +99 -0
  255. package/src/update-field-540.spec.js +52 -0
  256. package/src/urn.js +164 -0
  257. package/src/urn.spec.js +231 -0
  258. package/src/utils.js +52 -0
  259. package/test-fixtures/duplicates-ind1/01/expectedResult.json +4 -0
  260. package/test-fixtures/duplicates-ind1/01/metadata.json +4 -0
  261. package/test-fixtures/duplicates-ind1/01/record.json +16 -0
  262. package/test-fixtures/duplicates-ind1/02/expectedResult.json +6 -0
  263. package/test-fixtures/duplicates-ind1/02/metadata.json +4 -0
  264. package/test-fixtures/duplicates-ind1/02/record.json +16 -0
  265. package/test-fixtures/duplicates-ind1/03/expectedResult.json +13 -0
  266. package/test-fixtures/duplicates-ind1/03/metadata.json +6 -0
  267. package/test-fixtures/duplicates-ind1/03/record.json +16 -0
  268. package/test-fixtures/ending-whitespace/01/expectedResult.json +4 -0
  269. package/test-fixtures/ending-whitespace/01/metadata.json +6 -0
  270. package/test-fixtures/ending-whitespace/01/record.json +15 -0
  271. package/test-fixtures/ending-whitespace/02/expectedResult.json +4 -0
  272. package/test-fixtures/ending-whitespace/02/metadata.json +6 -0
  273. package/test-fixtures/ending-whitespace/02/record.json +15 -0
  274. package/test-fixtures/ending-whitespace/03/expectedResult.json +17 -0
  275. package/test-fixtures/ending-whitespace/03/metadata.json +6 -0
  276. package/test-fixtures/ending-whitespace/03/record.json +15 -0
  277. package/test-fixtures/ending-whitespace/04/expectedResult.json +10 -0
  278. package/test-fixtures/ending-whitespace/04/metadata.json +6 -0
  279. package/test-fixtures/ending-whitespace/04/record.json +8 -0
  280. package/test-fixtures/fix521/01/expectedResult.json +6 -0
  281. package/test-fixtures/fix521/01/metadata.json +5 -0
  282. package/test-fixtures/fix521/01/record.json +13 -0
  283. package/test-fixtures/fix521/02/expectedResult.json +15 -0
  284. package/test-fixtures/fix521/02/metadata.json +5 -0
  285. package/test-fixtures/fix521/02/record.json +13 -0
  286. package/test-fixtures/fix521/03/expectedResult.json +5 -0
  287. package/test-fixtures/fix521/03/metadata.json +5 -0
  288. package/test-fixtures/fix521/03/record.json +13 -0
  289. package/test-fixtures/indicator-fixes/01/expectedResult.json +9 -0
  290. package/test-fixtures/indicator-fixes/01/metadata.json +5 -0
  291. package/test-fixtures/indicator-fixes/01/record.json +64 -0
  292. package/test-fixtures/indicator-fixes/02/expectedResult.json +66 -0
  293. package/test-fixtures/indicator-fixes/02/metadata.json +5 -0
  294. package/test-fixtures/indicator-fixes/02/record.json +64 -0
  295. package/test-fixtures/indicator-fixes/03/expectedResult.json +55 -0
  296. package/test-fixtures/indicator-fixes/03/metadata.json +5 -0
  297. package/test-fixtures/indicator-fixes/03/record.json +54 -0
  298. package/test-fixtures/indicator-fixes/04/expectedResult.json +66 -0
  299. package/test-fixtures/indicator-fixes/04/metadata.json +5 -0
  300. package/test-fixtures/indicator-fixes/04/record.json +65 -0
  301. package/test-fixtures/indicator-fixes/05/expectedResult.json +66 -0
  302. package/test-fixtures/indicator-fixes/05/metadata.json +5 -0
  303. package/test-fixtures/indicator-fixes/05/record.json +65 -0
  304. package/test-fixtures/indicator-fixes/06/expectedResult.json +75 -0
  305. package/test-fixtures/indicator-fixes/06/metadata.json +5 -0
  306. package/test-fixtures/indicator-fixes/06/record.json +74 -0
  307. package/test-fixtures/lisapainokset/fixer/01/expectedResult.json +37 -0
  308. package/test-fixtures/lisapainokset/fixer/01/metadata.json +6 -0
  309. package/test-fixtures/lisapainokset/fixer/01/record.json +61 -0
  310. package/test-fixtures/lisapainokset/fixer/02/expectedResult.json +44 -0
  311. package/test-fixtures/lisapainokset/fixer/02/metadata.json +6 -0
  312. package/test-fixtures/lisapainokset/fixer/02/record.json +45 -0
  313. package/test-fixtures/lisapainokset/fixer/03/expectedResult.json +21 -0
  314. package/test-fixtures/lisapainokset/fixer/03/metadata.json +6 -0
  315. package/test-fixtures/lisapainokset/fixer/03/record.json +45 -0
  316. package/test-fixtures/lisapainokset/validator/01/expectedResult.json +7 -0
  317. package/test-fixtures/lisapainokset/validator/01/metadata.json +6 -0
  318. package/test-fixtures/lisapainokset/validator/01/record.json +45 -0
  319. package/test-fixtures/lisapainokset/validator/02/expectedResult.json +6 -0
  320. package/test-fixtures/lisapainokset/validator/02/metadata.json +6 -0
  321. package/test-fixtures/lisapainokset/validator/02/record.json +61 -0
  322. package/test-fixtures/lisapainokset/validator/03/expectedResult.json +4 -0
  323. package/test-fixtures/lisapainokset/validator/03/metadata.json +6 -0
  324. package/test-fixtures/lisapainokset/validator/03/record.json +37 -0
  325. package/test-fixtures/mergeRelatorTermFields/fixer/01/expectedResult.json +14 -0
  326. package/test-fixtures/mergeRelatorTermFields/fixer/01/metadata.json +6 -0
  327. package/test-fixtures/mergeRelatorTermFields/fixer/01/record.json +16 -0
  328. package/test-fixtures/mergeRelatorTermFields/fixer/02/expectedResult.json +17 -0
  329. package/test-fixtures/mergeRelatorTermFields/fixer/02/metadata.json +6 -0
  330. package/test-fixtures/mergeRelatorTermFields/fixer/02/record.json +23 -0
  331. package/test-fixtures/mergeRelatorTermFields/validator/01/expectedResult.json +6 -0
  332. package/test-fixtures/mergeRelatorTermFields/validator/01/metadata.json +6 -0
  333. package/test-fixtures/mergeRelatorTermFields/validator/01/record.json +16 -0
  334. package/test-fixtures/mergeRelatorTermFields/validator/02/expectedResult.json +4 -0
  335. package/test-fixtures/mergeRelatorTermFields/validator/02/metadata.json +6 -0
  336. package/test-fixtures/mergeRelatorTermFields/validator/02/record.json +16 -0
  337. package/test-fixtures/non-breaking-space/01/expectedResult.json +4 -0
  338. package/test-fixtures/non-breaking-space/01/metadata.json +6 -0
  339. package/test-fixtures/non-breaking-space/01/record.json +15 -0
  340. package/test-fixtures/non-breaking-space/02/expectedResult.json +4 -0
  341. package/test-fixtures/non-breaking-space/02/metadata.json +6 -0
  342. package/test-fixtures/non-breaking-space/02/record.json +15 -0
  343. package/test-fixtures/non-breaking-space/03/expectedResult.json +17 -0
  344. package/test-fixtures/non-breaking-space/03/metadata.json +6 -0
  345. package/test-fixtures/non-breaking-space/03/record.json +15 -0
  346. package/test-fixtures/non-breaking-space/04/expectedResult.json +21 -0
  347. package/test-fixtures/non-breaking-space/04/metadata.json +6 -0
  348. package/test-fixtures/non-breaking-space/04/record.json +19 -0
  349. package/test-fixtures/normalize-identifiers/01/expectedResult.json +8 -0
  350. package/test-fixtures/normalize-identifiers/01/metadata.json +5 -0
  351. package/test-fixtures/normalize-identifiers/01/record.json +81 -0
  352. package/test-fixtures/normalize-identifiers/02/expectedResult.json +92 -0
  353. package/test-fixtures/normalize-identifiers/02/metadata.json +5 -0
  354. package/test-fixtures/normalize-identifiers/02/record.json +92 -0
  355. package/test-fixtures/normalize-identifiers/03/expectedResult.json +63 -0
  356. package/test-fixtures/normalize-identifiers/03/metadata.json +5 -0
  357. package/test-fixtures/normalize-identifiers/03/record.json +61 -0
  358. package/test-fixtures/normalize-identifiers/04/expectedResult.json +79 -0
  359. package/test-fixtures/normalize-identifiers/04/metadata.json +5 -0
  360. package/test-fixtures/normalize-identifiers/04/record.json +77 -0
  361. package/test-fixtures/normalize-utf8-diacritics/01/expectedResult.json +7 -0
  362. package/test-fixtures/normalize-utf8-diacritics/01/metadata.json +5 -0
  363. package/test-fixtures/normalize-utf8-diacritics/01/record.json +39 -0
  364. package/test-fixtures/normalize-utf8-diacritics/02/expectedResult.json +41 -0
  365. package/test-fixtures/normalize-utf8-diacritics/02/metadata.json +5 -0
  366. package/test-fixtures/normalize-utf8-diacritics/02/record.json +39 -0
  367. package/test-fixtures/normalize-utf8-diacritics/03/expectedResult.json +5 -0
  368. package/test-fixtures/normalize-utf8-diacritics/03/metadata.json +5 -0
  369. package/test-fixtures/normalize-utf8-diacritics/03/record.json +37 -0
  370. package/test-fixtures/normalize-utf8-diacritics/04/expectedResult.json +41 -0
  371. package/test-fixtures/normalize-utf8-diacritics/04/metadata.json +5 -0
  372. package/test-fixtures/normalize-utf8-diacritics/04/record.json +39 -0
  373. package/test-fixtures/normalize-utf8-diacritics/05/expectedResult.json +41 -0
  374. package/test-fixtures/normalize-utf8-diacritics/05/metadata.json +5 -0
  375. package/test-fixtures/normalize-utf8-diacritics/05/record.json +41 -0
  376. package/test-fixtures/punctuation/01/expectedResult.json +3 -0
  377. package/test-fixtures/punctuation/01/metadata.json +4 -0
  378. package/test-fixtures/punctuation/01/record.json +18 -0
  379. package/test-fixtures/punctuation/02/expectedResult.json +3 -0
  380. package/test-fixtures/punctuation/02/metadata.json +4 -0
  381. package/test-fixtures/punctuation/02/record.json +18 -0
  382. package/test-fixtures/punctuation/03/expectedResult.json +21 -0
  383. package/test-fixtures/punctuation/03/metadata.json +5 -0
  384. package/test-fixtures/punctuation/03/record.json +19 -0
  385. package/test-fixtures/punctuation/04/expectedResult.json +21 -0
  386. package/test-fixtures/punctuation/04/metadata.json +5 -0
  387. package/test-fixtures/punctuation/04/record.json +19 -0
  388. package/test-fixtures/punctuation/05/expectedResult.json +44 -0
  389. package/test-fixtures/punctuation/05/metadata.json +5 -0
  390. package/test-fixtures/punctuation/05/record.json +42 -0
  391. package/test-fixtures/punctuation2/01/expectedResult.json +12 -0
  392. package/test-fixtures/punctuation2/01/metadata.json +6 -0
  393. package/test-fixtures/punctuation2/01/record.json +37 -0
  394. package/test-fixtures/punctuation2/02/expectedResult.json +4 -0
  395. package/test-fixtures/punctuation2/02/metadata.json +6 -0
  396. package/test-fixtures/punctuation2/02/record.json +14 -0
  397. package/test-fixtures/punctuation2/04/expectedResult.json +7 -0
  398. package/test-fixtures/punctuation2/04/metadata.json +6 -0
  399. package/test-fixtures/punctuation2/04/record.json +22 -0
  400. package/test-fixtures/punctuation2/05/expectedResult.json +6 -0
  401. package/test-fixtures/punctuation2/05/metadata.json +6 -0
  402. package/test-fixtures/punctuation2/05/record.json +12 -0
  403. package/test-fixtures/punctuation2/98/expectedResult.json +45 -0
  404. package/test-fixtures/punctuation2/98/metadata.json +6 -0
  405. package/test-fixtures/punctuation2/98/record.json +43 -0
  406. package/test-fixtures/punctuation2/99/expectedResult.json +15 -0
  407. package/test-fixtures/punctuation2/99/metadata.json +6 -0
  408. package/test-fixtures/punctuation2/99/record.json +14 -0
  409. package/test-fixtures/reindex-sf6-occurence-numbers/f01/expectedResult.json +35 -0
  410. package/test-fixtures/reindex-sf6-occurence-numbers/f01/metadata.json +6 -0
  411. package/test-fixtures/reindex-sf6-occurence-numbers/f01/record.json +34 -0
  412. package/test-fixtures/reindex-sf6-occurence-numbers/f02/expectedResult.json +53 -0
  413. package/test-fixtures/reindex-sf6-occurence-numbers/f02/metadata.json +6 -0
  414. package/test-fixtures/reindex-sf6-occurence-numbers/f02/record.json +51 -0
  415. package/test-fixtures/reindex-sf6-occurence-numbers/f03/expectedResult.json +46 -0
  416. package/test-fixtures/reindex-sf6-occurence-numbers/f03/metadata.json +7 -0
  417. package/test-fixtures/reindex-sf6-occurence-numbers/f03/record.json +44 -0
  418. package/test-fixtures/reindex-sf6-occurence-numbers/v01/expectedResult.json +6 -0
  419. package/test-fixtures/reindex-sf6-occurence-numbers/v01/metadata.json +5 -0
  420. package/test-fixtures/reindex-sf6-occurence-numbers/v01/record.json +31 -0
  421. package/test-fixtures/reindex-sf6-occurence-numbers/v02/expectedResult.json +6 -0
  422. package/test-fixtures/reindex-sf6-occurence-numbers/v02/metadata.json +6 -0
  423. package/test-fixtures/reindex-sf6-occurence-numbers/v02/record.json +38 -0
  424. package/test-fixtures/reindex-sf6-occurence-numbers/v03/expectedResult.json +6 -0
  425. package/test-fixtures/reindex-sf6-occurence-numbers/v03/metadata.json +6 -0
  426. package/test-fixtures/reindex-sf6-occurence-numbers/v03/record.json +30 -0
  427. package/test-fixtures/remove-duplicate-datafields/f01/expectedResult.json +35 -0
  428. package/test-fixtures/remove-duplicate-datafields/f01/metadata.json +6 -0
  429. package/test-fixtures/remove-duplicate-datafields/f01/record.json +34 -0
  430. package/test-fixtures/remove-duplicate-datafields/f03/expectedResult.json +20 -0
  431. package/test-fixtures/remove-duplicate-datafields/f03/metadata.json +6 -0
  432. package/test-fixtures/remove-duplicate-datafields/f03/record.json +33 -0
  433. package/test-fixtures/remove-duplicate-datafields/f03b/expectedResult.json +20 -0
  434. package/test-fixtures/remove-duplicate-datafields/f03b/metadata.json +6 -0
  435. package/test-fixtures/remove-duplicate-datafields/f03b/record.json +35 -0
  436. package/test-fixtures/remove-duplicate-datafields/f03c/expectedResult.json +25 -0
  437. package/test-fixtures/remove-duplicate-datafields/f03c/metadata.json +6 -0
  438. package/test-fixtures/remove-duplicate-datafields/f03c/record.json +43 -0
  439. package/test-fixtures/remove-duplicate-datafields/f04/expectedResult.json +31 -0
  440. package/test-fixtures/remove-duplicate-datafields/f04/metadata.json +6 -0
  441. package/test-fixtures/remove-duplicate-datafields/f04/record.json +41 -0
  442. package/test-fixtures/remove-duplicate-datafields/f05/expectedResult.json +23 -0
  443. package/test-fixtures/remove-duplicate-datafields/f05/metadata.json +6 -0
  444. package/test-fixtures/remove-duplicate-datafields/f05/record.json +29 -0
  445. package/test-fixtures/remove-duplicate-datafields/f06/expectedResult.json +24 -0
  446. package/test-fixtures/remove-duplicate-datafields/f06/metadata.json +6 -0
  447. package/test-fixtures/remove-duplicate-datafields/f06/record.json +41 -0
  448. package/test-fixtures/remove-duplicate-datafields/f07/expectedResult.json +15 -0
  449. package/test-fixtures/remove-duplicate-datafields/f07/metadata.json +6 -0
  450. package/test-fixtures/remove-duplicate-datafields/f07/record.json +21 -0
  451. package/test-fixtures/remove-duplicate-datafields/f08/expectedResult.json +21 -0
  452. package/test-fixtures/remove-duplicate-datafields/f08/metadata.json +6 -0
  453. package/test-fixtures/remove-duplicate-datafields/f08/record.json +33 -0
  454. package/test-fixtures/remove-duplicate-datafields/f09/expectedResult.json +6 -0
  455. package/test-fixtures/remove-duplicate-datafields/f09/metadata.json +6 -0
  456. package/test-fixtures/remove-duplicate-datafields/f09/record.json +9 -0
  457. package/test-fixtures/remove-duplicate-datafields/f10/expectedResult.json +15 -0
  458. package/test-fixtures/remove-duplicate-datafields/f10/metadata.json +6 -0
  459. package/test-fixtures/remove-duplicate-datafields/f10/record.json +24 -0
  460. package/test-fixtures/remove-duplicate-datafields/f11/expectedResult.json +30 -0
  461. package/test-fixtures/remove-duplicate-datafields/f11/metadata.json +6 -0
  462. package/test-fixtures/remove-duplicate-datafields/f11/record.json +53 -0
  463. package/test-fixtures/remove-duplicate-datafields/v01/expectedResult.json +6 -0
  464. package/test-fixtures/remove-duplicate-datafields/v01/metadata.json +6 -0
  465. package/test-fixtures/remove-duplicate-datafields/v01/record.json +31 -0
  466. package/test-fixtures/remove-duplicate-datafields/v02/expectedResult.json +10 -0
  467. package/test-fixtures/remove-duplicate-datafields/v02/metadata.json +6 -0
  468. package/test-fixtures/remove-duplicate-datafields/v02/record.json +45 -0
  469. package/test-fixtures/remove-duplicate-datafields/v03/expectedResult.json +6 -0
  470. package/test-fixtures/remove-duplicate-datafields/v03/metadata.json +7 -0
  471. package/test-fixtures/remove-duplicate-datafields/v03/record.json +37 -0
  472. package/test-fixtures/remove-duplicate-datafields/v04/expectedResult.json +8 -0
  473. package/test-fixtures/remove-duplicate-datafields/v04/metadata.json +6 -0
  474. package/test-fixtures/remove-duplicate-datafields/v04/record.json +41 -0
  475. package/test-fixtures/remove-inferior-datafields/f01/expectedResult.json +21 -0
  476. package/test-fixtures/remove-inferior-datafields/f01/metadata.json +6 -0
  477. package/test-fixtures/remove-inferior-datafields/f01/record.json +31 -0
  478. package/test-fixtures/remove-inferior-datafields/f03/expectedResult.json +16 -0
  479. package/test-fixtures/remove-inferior-datafields/f03/metadata.json +6 -0
  480. package/test-fixtures/remove-inferior-datafields/f03/record.json +27 -0
  481. package/test-fixtures/remove-inferior-datafields/f04/expectedResult.json +31 -0
  482. package/test-fixtures/remove-inferior-datafields/f04/metadata.json +6 -0
  483. package/test-fixtures/remove-inferior-datafields/f04/record.json +38 -0
  484. package/test-fixtures/remove-inferior-datafields/f05/expectedResult.json +34 -0
  485. package/test-fixtures/remove-inferior-datafields/f05/metadata.json +6 -0
  486. package/test-fixtures/remove-inferior-datafields/f05/record.json +41 -0
  487. package/test-fixtures/remove-inferior-datafields/f06/expectedResult.json +16 -0
  488. package/test-fixtures/remove-inferior-datafields/f06/metadata.json +6 -0
  489. package/test-fixtures/remove-inferior-datafields/f06/record.json +20 -0
  490. package/test-fixtures/remove-inferior-datafields/v01/expectedResult.json +6 -0
  491. package/test-fixtures/remove-inferior-datafields/v01/metadata.json +6 -0
  492. package/test-fixtures/remove-inferior-datafields/v01/record.json +31 -0
  493. package/test-fixtures/remove-inferior-datafields/v02/expectedResult.json +6 -0
  494. package/test-fixtures/remove-inferior-datafields/v02/metadata.json +6 -0
  495. package/test-fixtures/remove-inferior-datafields/v02/record.json +21 -0
  496. package/test-fixtures/remove-orphanded-sf6s/f01/expectedResult.json +35 -0
  497. package/test-fixtures/remove-orphanded-sf6s/f01/metadata.json +6 -0
  498. package/test-fixtures/remove-orphanded-sf6s/f01/record.json +34 -0
  499. package/test-fixtures/remove-orphanded-sf6s/f02/expectedResult.json +40 -0
  500. package/test-fixtures/remove-orphanded-sf6s/f02/metadata.json +6 -0
  501. package/test-fixtures/remove-orphanded-sf6s/f02/record.json +43 -0
  502. package/test-fixtures/remove-orphanded-sf6s/v01/expectedResult.json +6 -0
  503. package/test-fixtures/remove-orphanded-sf6s/v01/metadata.json +6 -0
  504. package/test-fixtures/remove-orphanded-sf6s/v01/record.json +31 -0
  505. package/test-fixtures/remove-orphanded-sf6s/v02/expectedResult.json +6 -0
  506. package/test-fixtures/remove-orphanded-sf6s/v02/metadata.json +6 -0
  507. package/test-fixtures/remove-orphanded-sf6s/v02/record.json +31 -0
  508. package/test-fixtures/resolvable-ext-references-melinda.js +0 -27
  509. package/test-fixtures/sanitize-vocabulary-source-codes/f01/expectedResult.json +32 -0
  510. package/test-fixtures/sanitize-vocabulary-source-codes/f01/metadata.json +6 -0
  511. package/test-fixtures/sanitize-vocabulary-source-codes/f01/record.json +32 -0
  512. package/test-fixtures/sanitize-vocabulary-source-codes/f02/expectedResult.json +24 -0
  513. package/test-fixtures/sanitize-vocabulary-source-codes/f02/metadata.json +6 -0
  514. package/test-fixtures/sanitize-vocabulary-source-codes/f02/record.json +24 -0
  515. package/test-fixtures/sanitize-vocabulary-source-codes/v01/expectedResult.json +12 -0
  516. package/test-fixtures/sanitize-vocabulary-source-codes/v01/metadata.json +6 -0
  517. package/test-fixtures/sanitize-vocabulary-source-codes/v01/record.json +24 -0
  518. package/test-fixtures/sort-relator-terms/f01/expectedResult.json +23 -0
  519. package/test-fixtures/sort-relator-terms/f01/metadata.json +6 -0
  520. package/test-fixtures/sort-relator-terms/f01/record.json +22 -0
  521. package/test-fixtures/sort-relator-terms/f02/expectedResult.json +26 -0
  522. package/test-fixtures/sort-relator-terms/f02/metadata.json +6 -0
  523. package/test-fixtures/sort-relator-terms/f02/record.json +22 -0
  524. package/test-fixtures/sort-relator-terms/v01/expectedResult.json +5 -0
  525. package/test-fixtures/sort-relator-terms/v01/metadata.json +6 -0
  526. package/test-fixtures/sort-relator-terms/v01/record.json +22 -0
  527. package/test-fixtures/sort-relator-terms/v02/expectedResult.json +6 -0
  528. package/test-fixtures/sort-relator-terms/v02/metadata.json +6 -0
  529. package/test-fixtures/sort-relator-terms/v02/record.json +14 -0
  530. package/test-fixtures/sort-subfields/f01/expectedResult.json +24 -0
  531. package/test-fixtures/sort-subfields/f01/metadata.json +6 -0
  532. package/test-fixtures/sort-subfields/f01/record.json +20 -0
  533. package/test-fixtures/sort-subfields/v01/expectedResult.json +5 -0
  534. package/test-fixtures/sort-subfields/v01/metadata.json +6 -0
  535. package/test-fixtures/sort-subfields/v01/record.json +24 -0
  536. package/test-fixtures/sort-subfields/v02/expectedResult.json +6 -0
  537. package/test-fixtures/sort-subfields/v02/metadata.json +6 -0
  538. package/test-fixtures/sort-subfields/v02/record.json +8 -0
  539. package/test-fixtures/strip-punctuation/01/expectedResult.json +12 -0
  540. package/test-fixtures/strip-punctuation/01/metadata.json +6 -0
  541. package/test-fixtures/strip-punctuation/01/record.json +37 -0
  542. package/test-fixtures/strip-punctuation/02/expectedResult.json +4 -0
  543. package/test-fixtures/strip-punctuation/02/metadata.json +6 -0
  544. package/test-fixtures/strip-punctuation/02/record.json +14 -0
  545. package/test-fixtures/strip-punctuation/04/expectedResult.json +6 -0
  546. package/test-fixtures/strip-punctuation/04/metadata.json +6 -0
  547. package/test-fixtures/strip-punctuation/04/record.json +22 -0
  548. package/test-fixtures/strip-punctuation/05/expectedResult.json +6 -0
  549. package/test-fixtures/strip-punctuation/05/metadata.json +6 -0
  550. package/test-fixtures/strip-punctuation/05/record.json +12 -0
  551. package/test-fixtures/strip-punctuation/98/expectedResult.json +44 -0
  552. package/test-fixtures/strip-punctuation/98/metadata.json +6 -0
  553. package/test-fixtures/strip-punctuation/98/record.json +45 -0
  554. package/test-fixtures/strip-punctuation/99/expectedResult.json +16 -0
  555. package/test-fixtures/strip-punctuation/99/metadata.json +6 -0
  556. package/test-fixtures/strip-punctuation/99/record.json +16 -0
  557. package/test-fixtures/subfield0/f01/expectedResult.json +25 -0
  558. package/test-fixtures/subfield0/f01/metadata.json +6 -0
  559. package/test-fixtures/subfield0/f01/record.json +23 -0
  560. package/test-fixtures/subfield0/f02/expectedResult.json +35 -0
  561. package/test-fixtures/subfield0/f02/metadata.json +6 -0
  562. package/test-fixtures/subfield0/f02/record.json +41 -0
  563. package/test-fixtures/subfield0/f03/expectedResult.json +21 -0
  564. package/test-fixtures/subfield0/f03/metadata.json +7 -0
  565. package/test-fixtures/subfield0/f03/record.json +24 -0
  566. package/test-fixtures/subfield0/v01/expectedResult.json +4 -0
  567. package/test-fixtures/subfield0/v01/metadata.json +6 -0
  568. package/test-fixtures/subfield0/v01/record.json +23 -0
  569. package/test-fixtures/subfield0/v02/expectedResult.json +9 -0
  570. package/test-fixtures/subfield0/v02/metadata.json +6 -0
  571. package/test-fixtures/subfield0/v02/record.json +38 -0
  572. package/test-fixtures/typeOfDate-008/01/expectedResult.json +3 -0
  573. package/test-fixtures/typeOfDate-008/01/metadata.json +4 -0
  574. package/test-fixtures/typeOfDate-008/01/record.json +14 -0
  575. package/test-fixtures/typeOfDate-008/02/expectedResult.json +4 -0
  576. package/test-fixtures/typeOfDate-008/02/metadata.json +4 -0
  577. package/test-fixtures/typeOfDate-008/02/record.json +14 -0
  578. package/test-fixtures/typeOfDate-008/03/expectedResult.json +14 -0
  579. package/test-fixtures/typeOfDate-008/03/metadata.json +5 -0
  580. package/test-fixtures/typeOfDate-008/03/record.json +14 -0
  581. package/test-fixtures/typeOfDate-008/04/expectedResult.json +14 -0
  582. package/test-fixtures/typeOfDate-008/04/metadata.json +5 -0
  583. package/test-fixtures/typeOfDate-008/04/record.json +14 -0
  584. package/test-fixtures/typeOfDate-008/05/expectedResult.json +14 -0
  585. package/test-fixtures/typeOfDate-008/05/metadata.json +5 -0
  586. package/test-fixtures/typeOfDate-008/05/record.json +14 -0
  587. package/test-fixtures/update-field-540/f01/expectedResult.json +23 -0
  588. package/test-fixtures/update-field-540/f01/metadata.json +6 -0
  589. package/test-fixtures/update-field-540/f01/record.json +23 -0
  590. package/test-fixtures/update-field-540/v01/expectedResult.json +7 -0
  591. package/test-fixtures/update-field-540/v01/metadata.json +6 -0
  592. package/test-fixtures/update-field-540/v01/record.json +23 -0
  593. package/.travis.yml +0 -10
package/src/urn.js ADDED
@@ -0,0 +1,164 @@
1
+ import fetch from 'node-fetch';
2
+ import {isElectronicMaterial} from './utils';
3
+ import createDebugLogger from 'debug';
4
+
5
+ const URN_GENERATOR_URL = 'http://generator.urn.fi/cgi-bin/urn_generator.cgi?type=nbn';
6
+
7
+ export default function (isLegalDeposit = false, useMelindaTemp = true) {
8
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:urn');
9
+ const debugData = debug.extend('data');
10
+
11
+ // We should check that the f856 with URN has second indicator '0' (Resource), ' ' (No information provided) or '8' (No display constant generated)
12
+ // - if second indicator is '1' (Version of resource) or '2' (Related resource) the URN in f856 is not correct for the resource described in the record
13
+
14
+ // This checks only the existence of URNs from the Finnish urn.fi -resolver
15
+
16
+ const hasURN = f => f.tag === '856' && f.subfields.some(({code, value}) => code === 'u' && (/urn.fi/u).test(value));
17
+
18
+ return {
19
+ description: 'Adds URN for record, to 856-field (if not existing). If isLegalDeposit is active, adds legal deposit subfields to the f856s with URN.',
20
+ validate,
21
+ fix
22
+ };
23
+
24
+ async function fix(record) {
25
+ const f856sUrn = record.fields.filter(hasURN);
26
+ debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);
27
+
28
+ const ldSubfields = isLegalDeposit ? createLDSubfields() : [];
29
+ debugData(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`);
30
+
31
+ // We add the URN even if we're not getting the legalDeposit - where does this URN resolve?
32
+ // We probably should not do these additions
33
+
34
+ if (f856sUrn.length === 0) { // eslint-disable-line functional/no-conditional-statements
35
+ const {code, value, generated} = await createURNSubfield(record);
36
+
37
+ if (generated && useMelindaTemp) {
38
+ const tempSubField = {code: '9', value: 'MELINDA<TEMP>'};
39
+
40
+ record.insertField({
41
+ tag: '856',
42
+ ind1: '4',
43
+ ind2: '0',
44
+ subfields: [{code, value}, ...ldSubfields, tempSubField]
45
+ });
46
+
47
+ return true;
48
+ }
49
+
50
+ record.insertField({
51
+ tag: '856',
52
+ ind1: '4',
53
+ ind2: '0',
54
+ subfields: [{code, value}, ...ldSubfields]
55
+ });
56
+
57
+ return true;
58
+ } else if (isLegalDeposit) { // eslint-disable-line functional/no-conditional-statements
59
+
60
+ // We add here legal deposit information to all URN-f856s - we probably should not do this
61
+ // We should add extra f856 URN / URNs for legal deposits that already have a open (non-legal-deposit) URN
62
+ // How do we decide which URN to use as a template if there are several URNs
63
+ // We should check for existence of a legal deposit URN anyways
64
+
65
+ f856sUrn.forEach(f => {
66
+ ldSubfields.forEach(ldsf => {
67
+ if (!f.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value)) { // eslint-disable-line functional/no-conditional-statements
68
+ f.subfields.push(ldsf); // eslint-disable-line functional/immutable-data
69
+ }
70
+ });
71
+ });
72
+ }
73
+
74
+ return true;
75
+
76
+ // We should check existence of URN in f024 i1: '7' $2 urn/URN for this too
77
+
78
+ async function createURNSubfield(rec) {
79
+ // isbn is picked from the last 020 $a in the record
80
+ // what should we do in case of several 020 $a:s
81
+ const isbn = rec.fields.reduce((acc, f) => {
82
+ if (f.tag === '020') {
83
+ const a = f.subfields.find(sf => sf.code === 'a');
84
+ return a ? a.value : undefined;
85
+ }
86
+
87
+ return acc;
88
+ }, undefined);
89
+
90
+ debugData(`isbns: ${isbn}`);
91
+
92
+ const {generated, value} = await createURN(isbn);
93
+ return {code: 'u', value, generated};
94
+
95
+ async function createURN(isbn = false) {
96
+ if (isbn) {
97
+ return {generated: false, value: `http://urn.fi/URN:ISBN:${isbn}`};
98
+ }
99
+
100
+ const response = await fetch(URN_GENERATOR_URL);
101
+ const body = await response.text();
102
+
103
+ // If we generated URN we could also add it to the 024
104
+ // generated 024 should also have $9 MELINDA<TEMP>
105
+ return {generated: true, value: `http://urn.fi/${body}`};
106
+ }
107
+ }
108
+
109
+ }
110
+
111
+ // Later when the new subfields that have f506/f540 -type contents, we should add also them here
112
+ function createLDSubfields() {
113
+ return [
114
+ {
115
+ code: 'z',
116
+ value: 'Käytettävissä vapaakappalekirjastoissa'
117
+ },
118
+ {
119
+ code: '5',
120
+ value: 'FI-Vapaa'
121
+ }
122
+ ];
123
+ }
124
+
125
+ function fieldHasLDSubfields(field, ldSubfields) {
126
+ if (ldSubfields.every(ldsf => field.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value))) {
127
+ return true;
128
+ }
129
+ }
130
+
131
+ function validateLD(f856sUrn) {
132
+ debug(`Validating the existence of legal deposit subfields`);
133
+ const ldSubfields = createLDSubfields();
134
+ const f856sUrnWithLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, ldSubfields));
135
+ if (f856sUrnWithLdSubfields.length > 0) {
136
+ debug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`);
137
+ debugData(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`);
138
+ return true;
139
+ }
140
+ return false;
141
+ }
142
+
143
+ function validate(record) {
144
+ // if not electronic skip this validator
145
+ if (!isElectronicMaterial(record)) {
146
+ debug(`Record is not electronic - no need to validate legal deposit URNs`);
147
+ return {valid: true};
148
+ }
149
+
150
+ const f856sUrn = record.fields.filter(hasURN);
151
+
152
+ if (f856sUrn.length > 0) {
153
+ debug(`Record has ${f856sUrn.length} URN fields`);
154
+ debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);
155
+
156
+ if (!isLegalDeposit || validateLD(f856sUrn)) {
157
+ debug(`Record is valid`);
158
+ return {valid: true};
159
+ }
160
+ }
161
+ debug(`No (valid) URN fields - Record is not valid`);
162
+ return {valid: false};
163
+ }
164
+ }
@@ -0,0 +1,231 @@
1
+ import {expect} from 'chai';
2
+ import {MarcRecord} from '@natlibfi/marc-record';
3
+ import validatorFactory from '../src/urn';
4
+
5
+ describe('urn', async () => {
6
+ // Fields
7
+ const f337 = {
8
+ tag: '337',
9
+ ind1: ' ',
10
+ ind2: ' ',
11
+ subfields: [
12
+ {code: 'b', value: 'c'},
13
+ {code: '2', value: 'rdamedia'}
14
+ ]
15
+ };
16
+
17
+ const f337nonElectronic = {
18
+ tag: '337',
19
+ ind1: ' ',
20
+ ind2: ' ',
21
+ subfields: [
22
+ {code: 'b', value: 'n'},
23
+ {code: '2', value: 'rdamedia'}
24
+ ]
25
+ };
26
+
27
+ const ldf856 = {
28
+ tag: '856',
29
+ ind1: '4',
30
+ ind2: '0',
31
+ subfields: [
32
+ {code: 'u', value: 'http://urn.fi/URN:ISBN:978-951-9155-47-0'},
33
+ {code: 'z', value: 'Käytettävissä vapaakappalekirjastoissa'},
34
+ {code: '5', value: 'FI-Vapaa'}
35
+ ]
36
+ };
37
+
38
+ const ldf856partial = {
39
+ tag: '856',
40
+ ind1: '4',
41
+ ind2: '0',
42
+ subfields: [
43
+ {code: 'u', value: 'http://urn.fi/URN:ISBN:978-951-9155-47-0'},
44
+ {code: '5', value: 'FI-Vapaa'}
45
+ ]
46
+ };
47
+
48
+ const f856URN = {
49
+ tag: '856',
50
+ ind1: '4',
51
+ ind2: '0',
52
+ subfields: [{code: 'u', value: 'http://urn.fi/URN:ISBN:978-951-9155-47-0'}]
53
+ };
54
+
55
+ const f856URNnotResource = {
56
+ tag: '856',
57
+ ind1: '4',
58
+ ind2: '1',
59
+ subfields: [{code: 'u', value: 'http://urn.fi/URN:ISBN:978-951-9155-47-0'}]
60
+ };
61
+
62
+
63
+ const f856URL = {
64
+ tag: '856',
65
+ ind1: '4',
66
+ ind2: '0',
67
+ subfields: [{code: 'u', value: 'http://foo.bar/'}]
68
+ };
69
+
70
+ const f020 = {
71
+ tag: '020',
72
+ ind1: ' ',
73
+ ind2: ' ',
74
+ subfields: [{code: 'a', value: '978-951-9155-47-0'}]
75
+ };
76
+
77
+ const f020second = {
78
+ tag: '020',
79
+ ind1: ' ',
80
+ ind2: ' ',
81
+ subfields: [{code: 'a', value: '9789519155470'}]
82
+ };
83
+
84
+
85
+ it('Creates a validator', async () => {
86
+ const validator = await validatorFactory();
87
+
88
+ expect(validator)
89
+ .to.be.an('object')
90
+ .that.has.any.keys('description', 'validate');
91
+
92
+ expect(validator.description).to.be.a('string');
93
+ expect(validator.validate).to.be.a('function');
94
+ });
95
+
96
+ // Tests
97
+ const test = async isLegalDeposit => {
98
+ const validator = await validatorFactory(isLegalDeposit);
99
+ return {
100
+ validate: async (valid, ...recfields) => {
101
+ const result = await validator.validate(new MarcRecord({fields: recfields}));
102
+ expect(result).to.eql({valid});
103
+ },
104
+
105
+ fix: async (recfields, resfields) => {
106
+ const record = new MarcRecord({fields: recfields});
107
+ await validator.fix(record);
108
+ expect(record.fields).to.eql(resfields);
109
+ }
110
+ };
111
+ };
112
+
113
+ /// Non-legal and legal deposit
114
+ const nonld = await test(false);
115
+ const ld = await test(true);
116
+
117
+ describe('#validate', () => {
118
+ // Validate non-electoronic
119
+ it('Finds the record valid; non-electronic record', async () => {
120
+ await nonld.validate(true, f337nonElectronic);
121
+ });
122
+
123
+ // Validate non-legal deposit
124
+ it('Finds the record valid; 856 with urn, and is non-legal deposit', async () => {
125
+ await nonld.validate(true, f337, f856URN);
126
+ });
127
+
128
+
129
+ // we should recognize that 856 with second indicator 1 is not describing the resource itself
130
+ it.skip('Finds the record invalid; 856 ind2: 1 with urn, and is non-legal deposit', async () => {
131
+ await nonld.validate(false, f337, f856URNnotResource);
132
+ });
133
+
134
+ // should we require urn if we're not handling a legal deposit
135
+ it('Finds the record invalid; 856 without urn, and is non-legal deposit', async () => {
136
+ await nonld.validate(false, f337, f856URL);
137
+ });
138
+
139
+
140
+ // should we require urn if we're not handling a legal deposit
141
+ it('Finds the record invalid; Missing 856, and is non-legal deposit', async () => {
142
+ await nonld.validate(false, f337, f020);
143
+ });
144
+
145
+ // Validate legal deposit
146
+ it('Finds the record invalid; 856 with urn, and is legal deposit', async () => {
147
+ await ld.validate(false, f020, f337, f856URN);
148
+ });
149
+
150
+ it('Finds the record invalid; 856 without urn, and is legal deposit', async () => {
151
+ await ld.validate(false, f020, f337, f856URL);
152
+ });
153
+
154
+ it('Finds the record invalid; Missing 856, and is legal deposit', async () => {
155
+ await ld.validate(false, f337, f020);
156
+ });
157
+
158
+ it('Finds the record valid; 856 with URN and legal deposit subfields, and is legal deposit', async () => {
159
+ await ld.validate(true, f337, f020, ldf856);
160
+ });
161
+
162
+ it('Finds the record valid; 856 with URN and legal deposit subfields and other f856s, and is legal deposit', async () => {
163
+ await ld.validate(true, f337, f020, ldf856partial, ldf856, f856URL);
164
+ });
165
+
166
+ it('Finds the record invalid; 856 with URN and partial legal deposit subfields, and is legal deposit', async () => {
167
+ await ld.validate(false, f337, f020, ldf856partial);
168
+ });
169
+
170
+
171
+ });
172
+
173
+ describe('#fix', () => {
174
+ // Fix non-legal deposit
175
+ it('856 with urn, and is non-legal deposit; Nothing to add', async () => {
176
+ await nonld.fix([f020, f856URL, f856URN], [f020, f856URL, f856URN]);
177
+ });
178
+
179
+ // should we actually add non-resolvable urns?
180
+ it('856 without urn, and is non-legal deposit; Adds 856 with urn', async () => {
181
+ await nonld.fix([f020, f856URL], [f020, f856URL, f856URN]);
182
+ });
183
+
184
+ // should we actually add non-resolvable urns?
185
+ it('Missing 856, and is non-legal deposit; Adds 856 with urn', async () => {
186
+ await nonld.fix([f020], [f020, f856URN]);
187
+ });
188
+
189
+ // should we actually add non-resolvable urns?
190
+ it('Missing 856, and is non-legal deposit, two 020 fields; Adds 856 with urn from second 020', async () => {
191
+ await nonld.fix([f020second, f020], [f020second, f020, f856URN]);
192
+ });
193
+
194
+ // should we actually add non resovable urns?
195
+ // we should think about how to choose the isbn to use in case of several ISBNs
196
+ it.skip('Missing 856, and is non-legal deposit, two 020 fields; Adds 856 with urn from first 020', async () => {
197
+ await nonld.fix([f020, f020second], [f020, f020second, f856URN]);
198
+ });
199
+
200
+
201
+ // Fix legal deposit
202
+ it('856 with urn and legal deposit fields, and is legal deposit; Nothing to add', async () => {
203
+ await ld.fix([f020, f856URL, ldf856], [f020, f856URL, ldf856]);
204
+ });
205
+
206
+ it('856 without urn, and is legal deposit; Adds 856 with urn and legal deposit fields', async () => {
207
+ await ld.fix([f020, f856URL], [f020, f856URL, ldf856]);
208
+ });
209
+
210
+ // we should test generating the URN in case of no ISBN
211
+
212
+ // we should test creating Melinda-temp field
213
+
214
+ // We shouldn't lock the open URN for legal deposit use
215
+ it('Missing 856, and is legal deposit; Adds 856 with urn and legal deposit fields', async () => {
216
+ await ld.fix([f020], [f020, ldf856]);
217
+ });
218
+
219
+ // We should actually do this instead of locking the original non-legal deposit URN for legal deposit use
220
+ it.skip('856 with urn, and is legal deposit; Adds another f856 with URN and legal deposit fields', async () => {
221
+ await ld.fix([f020, f856URL, f856URN], [f020, f856URL, f856URN, ldf856]);
222
+ });
223
+
224
+ // We should actually add a new urn in case of a non-resource URN
225
+ it.skip('856 with non-resource-urn, and is legal deposit; Adds another f856 with URN and legal deposit fields', async () => {
226
+ await ld.fix([f020, f856URL, f856URNnotResource], [f020, f856URL, f856URNnotResource, ldf856]);
227
+ });
228
+
229
+
230
+ });
231
+ });
package/src/utils.js ADDED
@@ -0,0 +1,52 @@
1
+ export function isElectronicMaterial(record) {
2
+ const f337s = record.get('337');
3
+
4
+ return f337s.some(field => {
5
+ const mediaTypeIsC = field.subfields.some(sub => sub.code === 'b' && sub.value === 'c');
6
+ const sourceIsRdamedia = field.subfields.some(sub => sub.code === '2' && sub.value === 'rdamedia');
7
+ return mediaTypeIsC && sourceIsRdamedia;
8
+ });
9
+ }
10
+
11
+ export function nvdebug(message, func = undefined) {
12
+ if (func) { // eslint-disable-line functional/no-conditional-statements
13
+ func(message);
14
+ }
15
+ //console.info(message); // eslint-disable-line no-console
16
+ }
17
+
18
+ export function fieldHasSubfield(field, subfieldCode, subfieldValue = null) {
19
+ if (!field.subfields) {
20
+ return false;
21
+ }
22
+ if (subfieldValue === null) {
23
+ return field.subfields.some(sf => sf.code === subfieldCode);
24
+ }
25
+ return field.subfields.some(sf => sf.code === subfieldCode && subfieldValue === sf.value);
26
+ }
27
+
28
+ export function subfieldToString(sf) {
29
+ return `‡${sf.code} ${sf.value}`;
30
+ }
31
+
32
+ function normalizeIndicatorValue(val) {
33
+ if (val === ' ') {
34
+ return '#';
35
+ }
36
+ return val;
37
+ }
38
+
39
+ export function fieldToString(f) {
40
+ if ('subfields' in f) {
41
+ return `${f.tag} ${normalizeIndicatorValue(f.ind1)}${normalizeIndicatorValue(f.ind2)}${formatSubfields(f)}`;
42
+ }
43
+ return `${f.tag} ${f.value}`;
44
+
45
+ function formatSubfields(field) {
46
+ return field.subfields.map(sf => ` ${subfieldToString(sf)}`).join('');
47
+ }
48
+ }
49
+
50
+ export function fieldsToString(fields) {
51
+ return fields.map(f => fieldToString(f)).join('\t__SEPARATOR__\t');
52
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "valid": true,
3
+ "messages": []
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "Finds the record valid",
3
+ "fix": false
4
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": "0",
7
+ "subfields": [{"code": "a", "value": "foo"}]
8
+ },
9
+ {
10
+ "tag": "500",
11
+ "ind1": " ",
12
+ "ind2": "0",
13
+ "subfields": [{"code": "a", "value": "foo"}]
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "valid": false,
3
+ "messages": [
4
+ "Multiple 500 fields which only differ in the first indicator"
5
+ ]
6
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "Finds the record invalid",
3
+ "fix": false
4
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": "0",
7
+ "subfields": [{"code": "a", "value": "foo"}]
8
+ },
9
+ {
10
+ "tag": "500",
11
+ "ind1": "1",
12
+ "ind2": "0",
13
+ "subfields": [{"code": "a", "value": "foo"}]
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,13 @@
1
+ [
2
+ {
3
+ "tag": "500",
4
+ "ind1": " ",
5
+ "ind2": "0",
6
+ "subfields": [
7
+ {
8
+ "code": "a",
9
+ "value": "foo"
10
+ }
11
+ ]
12
+ }
13
+ ]
@@ -0,0 +1,6 @@
1
+ {
2
+ "only": false,
3
+ "description": "Removes duplicate values",
4
+ "tagPattern": "^500$",
5
+ "fix": true
6
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": "0",
7
+ "subfields": [{"code": "a", "value": "foo"}]
8
+ },
9
+ {
10
+ "tag": "500",
11
+ "ind1": "1",
12
+ "ind2": "0",
13
+ "subfields": [{"code": "a", "value": "foo"}]
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "messages": [],
3
+ "valid": true
4
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "Finds the record valid when there are no subfields that end with whitespace",
3
+ "skip": false,
4
+ "only": false,
5
+ "fix": false
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": " ",
7
+ "subfields": [
8
+ {
9
+ "code": "a",
10
+ "value": "Foo"
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "messages":["Field 500 subfield $a ends with whitespace"],
3
+ "valid": false
4
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "Finds the record not valid when there is a subfield that ends with whitespace",
3
+ "skip": false,
4
+ "only": false,
5
+ "fix": false
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": " ",
7
+ "subfields": [
8
+ {
9
+ "code": "a",
10
+ "value": "Foo "
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ {
5
+ "tag": "500",
6
+ "ind1": " ",
7
+ "ind2": " ",
8
+ "subfields": [
9
+ {
10
+ "code": "a",
11
+ "value": "Foo"
12
+ }
13
+ ]
14
+ }
15
+ ],
16
+ "leader": ""
17
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "Fixes the record subfield that ends with whitespace",
3
+ "skip": false,
4
+ "only": false,
5
+ "fix": true
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "500",
5
+ "ind1": " ",
6
+ "ind2": " ",
7
+ "subfields": [
8
+ {
9
+ "code": "a",
10
+ "value": "Foo "
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ {
5
+ "tag": "008",
6
+ "value": "Foo "
7
+ }
8
+ ],
9
+ "leader": ""
10
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "Does not handle control fields",
3
+ "skip": false,
4
+ "only": false,
5
+ "fix": true
6
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "008",
5
+ "value": "Foo "
6
+ }
7
+ ]
8
+ }