@natlibfi/marc-record-validators-melinda 3.2.0 → 3.3.14-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CODEOWNERS +2 -0
- package/.github/dependabot.yml +40 -0
- package/.github/workflows/melinda-node-tests.yml +61 -0
- package/LICENSE.txt +21 -661
- package/README.md +4 -5
- package/dist/access-rights.js +94 -0
- package/dist/access-rights.js.map +1 -0
- package/dist/access-rights.spec.js +150 -0
- package/dist/access-rights.spec.js.map +1 -0
- package/dist/double-commas.js +17 -27
- package/dist/double-commas.js.map +1 -1
- package/dist/double-commas.spec.js +72 -27
- package/dist/double-commas.spec.js.map +1 -1
- package/dist/duplicates-ind1.js +47 -27
- package/dist/duplicates-ind1.js.map +1 -1
- package/dist/duplicates-ind1.spec.js +44 -27
- package/dist/duplicates-ind1.spec.js.map +1 -1
- package/dist/empty-fields.js +79 -29
- package/dist/empty-fields.js.map +1 -1
- package/dist/empty-fields.spec.js +113 -27
- package/dist/empty-fields.spec.js.map +1 -1
- package/dist/ending-punctuation-conf.js +772 -129
- package/dist/ending-punctuation-conf.js.map +1 -1
- package/dist/ending-punctuation.js +291 -72
- package/dist/ending-punctuation.js.map +1 -1
- package/dist/ending-punctuation.spec.js +2638 -118
- package/dist/ending-punctuation.spec.js.map +1 -1
- package/dist/ending-whitespace.js +58 -0
- package/dist/ending-whitespace.js.map +1 -0
- package/dist/ending-whitespace.spec.js +42 -0
- package/dist/ending-whitespace.spec.js.map +1 -0
- package/dist/field-521-fix.js +96 -0
- package/dist/field-521-fix.js.map +1 -0
- package/dist/field-521-fix.spec.js +51 -0
- package/dist/field-521-fix.spec.js.map +1 -0
- package/dist/field-exclusion.js +214 -63
- package/dist/field-exclusion.js.map +1 -1
- package/dist/field-exclusion.spec.js +1057 -31
- package/dist/field-exclusion.spec.js.map +1 -1
- package/dist/field-structure.js +249 -78
- package/dist/field-structure.js.map +1 -1
- package/dist/field-structure.spec.js +534 -31
- package/dist/field-structure.spec.js.map +1 -1
- package/dist/fields-present.js +31 -27
- package/dist/fields-present.js.map +1 -1
- package/dist/fields-present.spec.js +120 -27
- package/dist/fields-present.spec.js.map +1 -1
- package/dist/fixed-fields.js +72 -27
- package/dist/fixed-fields.js.map +1 -1
- package/dist/fixed-fields.spec.js +139 -27
- package/dist/fixed-fields.spec.js.map +1 -1
- package/dist/identical-fields.js +42 -28
- package/dist/identical-fields.js.map +1 -1
- package/dist/identical-fields.spec.js +98 -27
- package/dist/identical-fields.spec.js.map +1 -1
- package/dist/index.js +202 -27
- package/dist/index.js.map +1 -1
- package/dist/indicator-fixes.js +191 -0
- package/dist/indicator-fixes.js.map +1 -0
- package/dist/indicator-fixes.spec.js +51 -0
- package/dist/indicator-fixes.spec.js.map +1 -0
- package/dist/isbn-issn.js +266 -27
- package/dist/isbn-issn.js.map +1 -1
- package/dist/isbn-issn.spec.js +594 -27
- package/dist/isbn-issn.spec.js.map +1 -1
- package/dist/item-language.js +171 -27
- package/dist/item-language.js.map +1 -1
- package/dist/item-language.spec.js +305 -27
- package/dist/item-language.spec.js.map +1 -1
- package/dist/mergeField500Lisapainokset.js +155 -0
- package/dist/mergeField500Lisapainokset.js.map +1 -0
- package/dist/mergeField500Lisapainokset.spec.js +51 -0
- package/dist/mergeField500Lisapainokset.spec.js.map +1 -0
- package/dist/mergeRelatorTermFields.js +140 -0
- package/dist/mergeRelatorTermFields.js.map +1 -0
- package/dist/mergeRelatorTermFields.spec.js +51 -0
- package/dist/mergeRelatorTermFields.spec.js.map +1 -0
- package/dist/multiple-subfield-0.js +120 -0
- package/dist/multiple-subfield-0.js.map +1 -0
- package/dist/multiple-subfield-0.spec.js +51 -0
- package/dist/multiple-subfield-0.spec.js.map +1 -0
- package/dist/non-breaking-space.js +61 -0
- package/dist/non-breaking-space.js.map +1 -0
- package/dist/non-breaking-space.spec.js +42 -0
- package/dist/non-breaking-space.spec.js.map +1 -0
- package/dist/normalize-identifiers.js +210 -0
- package/dist/normalize-identifiers.js.map +1 -0
- package/dist/normalize-identifiers.spec.js +51 -0
- package/dist/normalize-identifiers.spec.js.map +1 -0
- package/dist/normalize-utf8-diacritics.js +140 -0
- package/dist/normalize-utf8-diacritics.js.map +1 -0
- package/dist/normalize-utf8-diacritics.spec.js +51 -0
- package/dist/normalize-utf8-diacritics.spec.js.map +1 -0
- package/dist/punctuation/index.js +281 -0
- package/dist/punctuation/index.js.map +1 -0
- package/dist/punctuation/rules/aut.js +332 -0
- package/dist/punctuation/rules/aut.js.map +1 -0
- package/dist/punctuation/rules/bib.js +374 -0
- package/dist/punctuation/rules/bib.js.map +1 -0
- package/dist/punctuation/rules/index.js +21 -0
- package/dist/punctuation/rules/index.js.map +1 -0
- package/dist/punctuation.spec.js +51 -0
- package/dist/punctuation.spec.js.map +1 -0
- package/dist/punctuation2.js +726 -0
- package/dist/punctuation2.js.map +1 -0
- package/dist/punctuation2.spec.js +51 -0
- package/dist/punctuation2.spec.js.map +1 -0
- package/dist/reindexSubfield6OccurenceNumbers.js +199 -0
- package/dist/reindexSubfield6OccurenceNumbers.js.map +1 -0
- package/dist/reindexSubfield6OccurenceNumbers.spec.js +51 -0
- package/dist/reindexSubfield6OccurenceNumbers.spec.js.map +1 -0
- package/dist/removeDuplicateDataFields.js +405 -0
- package/dist/removeDuplicateDataFields.js.map +1 -0
- package/dist/removeDuplicateDataFields.spec.js +51 -0
- package/dist/removeDuplicateDataFields.spec.js.map +1 -0
- package/dist/removeInferiorDataFields.js +245 -0
- package/dist/removeInferiorDataFields.js.map +1 -0
- package/dist/removeInferiorDataFields.spec.js +51 -0
- package/dist/removeInferiorDataFields.spec.js.map +1 -0
- package/dist/resolvable-ext-references-melinda.js +112 -31
- package/dist/resolvable-ext-references-melinda.js.map +1 -1
- package/dist/resolvable-ext-references-melinda.spec.js +166 -27
- package/dist/resolvable-ext-references-melinda.spec.js.map +1 -1
- package/dist/resolveOrphanedSubfield6s.js +116 -0
- package/dist/resolveOrphanedSubfield6s.js.map +1 -0
- package/dist/resolveOrphanedSubfield6s.spec.js +51 -0
- package/dist/resolveOrphanedSubfield6s.spec.js.map +1 -0
- package/dist/sanitize-vocabulary-source-codes.js +93 -0
- package/dist/sanitize-vocabulary-source-codes.js.map +1 -0
- package/dist/sanitize-vocabulary-source-codes.spec.js +51 -0
- package/dist/sanitize-vocabulary-source-codes.spec.js.map +1 -0
- package/dist/sort-tags.js +53 -27
- package/dist/sort-tags.js.map +1 -1
- package/dist/sort-tags.spec.js +206 -27
- package/dist/sort-tags.spec.js.map +1 -1
- package/dist/sortRelatorTerms.js +135 -0
- package/dist/sortRelatorTerms.js.map +1 -0
- package/dist/sortRelatorTerms.spec.js +51 -0
- package/dist/sortRelatorTerms.spec.js.map +1 -0
- package/dist/sortSubfields.js +279 -0
- package/dist/sortSubfields.js.map +1 -0
- package/dist/sortSubfields.spec.js +51 -0
- package/dist/sortSubfields.spec.js.map +1 -0
- package/dist/stripPunctuation.js +49 -0
- package/dist/stripPunctuation.js.map +1 -0
- package/dist/stripPunctuation.spec.js +51 -0
- package/dist/stripPunctuation.spec.js.map +1 -0
- package/dist/subfield-exclusion.js +174 -57
- package/dist/subfield-exclusion.js.map +1 -1
- package/dist/subfield-exclusion.spec.js +521 -31
- package/dist/subfield-exclusion.spec.js.map +1 -1
- package/dist/subfield6Utils.js +457 -0
- package/dist/subfield6Utils.js.map +1 -0
- package/dist/subfield8Utils.js +99 -0
- package/dist/subfield8Utils.js.map +1 -0
- package/dist/typeOfDate-008.js +48 -0
- package/dist/typeOfDate-008.js.map +1 -0
- package/dist/typeOfDate-008.spec.js +47 -0
- package/dist/typeOfDate-008.spec.js.map +1 -0
- package/dist/unicode-decomposition.js +139 -30
- package/dist/unicode-decomposition.js.map +1 -1
- package/dist/unicode-decomposition.spec.js +90 -27
- package/dist/unicode-decomposition.spec.js.map +1 -1
- package/dist/update-field-540.js +119 -0
- package/dist/update-field-540.js.map +1 -0
- package/dist/update-field-540.spec.js +51 -0
- package/dist/update-field-540.spec.js.map +1 -0
- package/dist/urn.js +185 -0
- package/dist/urn.js.map +1 -0
- package/dist/urn.spec.js +238 -0
- package/dist/urn.spec.js.map +1 -0
- package/dist/utils.js +58 -0
- package/dist/utils.js.map +1 -0
- package/package.json +114 -124
- package/src/access-rights.js +84 -0
- package/src/access-rights.spec.js +126 -0
- package/src/double-commas.js +12 -49
- package/src/double-commas.spec.js +50 -82
- package/src/duplicates-ind1.js +34 -74
- package/src/duplicates-ind1.spec.js +39 -117
- package/src/empty-fields.js +62 -74
- package/src/empty-fields.spec.js +134 -207
- package/src/ending-punctuation-conf.js +679 -644
- package/src/ending-punctuation.js +260 -250
- package/src/ending-punctuation.spec.js +2545 -2322
- package/src/ending-whitespace.js +40 -0
- package/src/ending-whitespace.spec.js +44 -0
- package/src/field-521-fix.js +92 -0
- package/src/field-521-fix.spec.js +52 -0
- package/src/field-exclusion.js +197 -215
- package/src/field-exclusion.spec.js +883 -481
- package/src/field-structure.js +213 -271
- package/src/field-structure.spec.js +597 -474
- package/src/fields-present.js +19 -49
- package/src/fields-present.spec.js +90 -91
- package/src/fixed-fields.js +61 -94
- package/src/fixed-fields.spec.js +81 -125
- package/src/identical-fields.js +29 -48
- package/src/identical-fields.spec.js +114 -146
- package/src/index.js +41 -46
- package/src/indicator-fixes.js +211 -0
- package/src/indicator-fixes.spec.js +52 -0
- package/src/isbn-issn.js +254 -106
- package/src/isbn-issn.spec.js +399 -172
- package/src/item-language.js +158 -195
- package/src/item-language.spec.js +314 -306
- package/src/mergeField500Lisapainokset.js +153 -0
- package/src/mergeField500Lisapainokset.spec.js +52 -0
- package/src/mergeRelatorTermFields.js +143 -0
- package/src/mergeRelatorTermFields.spec.js +52 -0
- package/src/multiple-subfield-0.js +129 -0
- package/src/multiple-subfield-0.spec.js +52 -0
- package/src/non-breaking-space.js +49 -0
- package/src/non-breaking-space.spec.js +44 -0
- package/src/normalize-identifiers.js +197 -0
- package/src/normalize-identifiers.spec.js +52 -0
- package/src/normalize-utf8-diacritics.js +141 -0
- package/src/normalize-utf8-diacritics.spec.js +52 -0
- package/src/punctuation/index.js +292 -0
- package/src/punctuation/rules/aut.js +372 -0
- package/src/punctuation/rules/bib.js +420 -0
- package/src/punctuation/rules/index.js +7 -0
- package/src/punctuation.spec.js +52 -0
- package/src/punctuation2.js +441 -0
- package/src/punctuation2.spec.js +52 -0
- package/src/reindexSubfield6OccurenceNumbers.js +210 -0
- package/src/reindexSubfield6OccurenceNumbers.spec.js +52 -0
- package/src/removeDuplicateDataFields.js +447 -0
- package/src/removeDuplicateDataFields.spec.js +52 -0
- package/src/removeInferiorDataFields.js +259 -0
- package/src/removeInferiorDataFields.spec.js +52 -0
- package/src/resolvable-ext-references-melinda.js +89 -122
- package/src/resolvable-ext-references-melinda.spec.js +168 -198
- package/src/resolveOrphanedSubfield6s.js +115 -0
- package/src/resolveOrphanedSubfield6s.spec.js +52 -0
- package/src/sanitize-vocabulary-source-codes.js +99 -0
- package/src/sanitize-vocabulary-source-codes.spec.js +52 -0
- package/src/sort-tags.js +34 -60
- package/src/sort-tags.spec.js +256 -290
- package/src/sortRelatorTerms.js +142 -0
- package/src/sortRelatorTerms.spec.js +52 -0
- package/src/sortSubfields.js +176 -0
- package/src/sortSubfields.spec.js +52 -0
- package/src/stripPunctuation.js +42 -0
- package/src/stripPunctuation.spec.js +52 -0
- package/src/subfield-exclusion.js +157 -180
- package/src/subfield-exclusion.spec.js +507 -453
- package/src/subfield6Utils.js +485 -0
- package/src/subfield8Utils.js +102 -0
- package/src/typeOfDate-008.js +40 -0
- package/src/typeOfDate-008.spec.js +47 -0
- package/src/unicode-decomposition.js +130 -145
- package/src/unicode-decomposition.spec.js +89 -115
- package/src/update-field-540.js +99 -0
- package/src/update-field-540.spec.js +52 -0
- package/src/urn.js +164 -0
- package/src/urn.spec.js +231 -0
- package/src/utils.js +52 -0
- package/test-fixtures/duplicates-ind1/01/expectedResult.json +4 -0
- package/test-fixtures/duplicates-ind1/01/metadata.json +4 -0
- package/test-fixtures/duplicates-ind1/01/record.json +16 -0
- package/test-fixtures/duplicates-ind1/02/expectedResult.json +6 -0
- package/test-fixtures/duplicates-ind1/02/metadata.json +4 -0
- package/test-fixtures/duplicates-ind1/02/record.json +16 -0
- package/test-fixtures/duplicates-ind1/03/expectedResult.json +13 -0
- package/test-fixtures/duplicates-ind1/03/metadata.json +6 -0
- package/test-fixtures/duplicates-ind1/03/record.json +16 -0
- package/test-fixtures/ending-whitespace/01/expectedResult.json +4 -0
- package/test-fixtures/ending-whitespace/01/metadata.json +6 -0
- package/test-fixtures/ending-whitespace/01/record.json +15 -0
- package/test-fixtures/ending-whitespace/02/expectedResult.json +4 -0
- package/test-fixtures/ending-whitespace/02/metadata.json +6 -0
- package/test-fixtures/ending-whitespace/02/record.json +15 -0
- package/test-fixtures/ending-whitespace/03/expectedResult.json +17 -0
- package/test-fixtures/ending-whitespace/03/metadata.json +6 -0
- package/test-fixtures/ending-whitespace/03/record.json +15 -0
- package/test-fixtures/ending-whitespace/04/expectedResult.json +10 -0
- package/test-fixtures/ending-whitespace/04/metadata.json +6 -0
- package/test-fixtures/ending-whitespace/04/record.json +8 -0
- package/test-fixtures/fix521/01/expectedResult.json +6 -0
- package/test-fixtures/fix521/01/metadata.json +5 -0
- package/test-fixtures/fix521/01/record.json +13 -0
- package/test-fixtures/fix521/02/expectedResult.json +15 -0
- package/test-fixtures/fix521/02/metadata.json +5 -0
- package/test-fixtures/fix521/02/record.json +13 -0
- package/test-fixtures/fix521/03/expectedResult.json +5 -0
- package/test-fixtures/fix521/03/metadata.json +5 -0
- package/test-fixtures/fix521/03/record.json +13 -0
- package/test-fixtures/indicator-fixes/01/expectedResult.json +9 -0
- package/test-fixtures/indicator-fixes/01/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/01/record.json +64 -0
- package/test-fixtures/indicator-fixes/02/expectedResult.json +66 -0
- package/test-fixtures/indicator-fixes/02/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/02/record.json +64 -0
- package/test-fixtures/indicator-fixes/03/expectedResult.json +55 -0
- package/test-fixtures/indicator-fixes/03/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/03/record.json +54 -0
- package/test-fixtures/indicator-fixes/04/expectedResult.json +66 -0
- package/test-fixtures/indicator-fixes/04/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/04/record.json +65 -0
- package/test-fixtures/indicator-fixes/05/expectedResult.json +66 -0
- package/test-fixtures/indicator-fixes/05/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/05/record.json +65 -0
- package/test-fixtures/indicator-fixes/06/expectedResult.json +75 -0
- package/test-fixtures/indicator-fixes/06/metadata.json +5 -0
- package/test-fixtures/indicator-fixes/06/record.json +74 -0
- package/test-fixtures/lisapainokset/fixer/01/expectedResult.json +37 -0
- package/test-fixtures/lisapainokset/fixer/01/metadata.json +6 -0
- package/test-fixtures/lisapainokset/fixer/01/record.json +61 -0
- package/test-fixtures/lisapainokset/fixer/02/expectedResult.json +44 -0
- package/test-fixtures/lisapainokset/fixer/02/metadata.json +6 -0
- package/test-fixtures/lisapainokset/fixer/02/record.json +45 -0
- package/test-fixtures/lisapainokset/fixer/03/expectedResult.json +21 -0
- package/test-fixtures/lisapainokset/fixer/03/metadata.json +6 -0
- package/test-fixtures/lisapainokset/fixer/03/record.json +45 -0
- package/test-fixtures/lisapainokset/validator/01/expectedResult.json +7 -0
- package/test-fixtures/lisapainokset/validator/01/metadata.json +6 -0
- package/test-fixtures/lisapainokset/validator/01/record.json +45 -0
- package/test-fixtures/lisapainokset/validator/02/expectedResult.json +6 -0
- package/test-fixtures/lisapainokset/validator/02/metadata.json +6 -0
- package/test-fixtures/lisapainokset/validator/02/record.json +61 -0
- package/test-fixtures/lisapainokset/validator/03/expectedResult.json +4 -0
- package/test-fixtures/lisapainokset/validator/03/metadata.json +6 -0
- package/test-fixtures/lisapainokset/validator/03/record.json +37 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/01/expectedResult.json +14 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/01/metadata.json +6 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/01/record.json +16 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/02/expectedResult.json +17 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/02/metadata.json +6 -0
- package/test-fixtures/mergeRelatorTermFields/fixer/02/record.json +23 -0
- package/test-fixtures/mergeRelatorTermFields/validator/01/expectedResult.json +6 -0
- package/test-fixtures/mergeRelatorTermFields/validator/01/metadata.json +6 -0
- package/test-fixtures/mergeRelatorTermFields/validator/01/record.json +16 -0
- package/test-fixtures/mergeRelatorTermFields/validator/02/expectedResult.json +4 -0
- package/test-fixtures/mergeRelatorTermFields/validator/02/metadata.json +6 -0
- package/test-fixtures/mergeRelatorTermFields/validator/02/record.json +16 -0
- package/test-fixtures/non-breaking-space/01/expectedResult.json +4 -0
- package/test-fixtures/non-breaking-space/01/metadata.json +6 -0
- package/test-fixtures/non-breaking-space/01/record.json +15 -0
- package/test-fixtures/non-breaking-space/02/expectedResult.json +4 -0
- package/test-fixtures/non-breaking-space/02/metadata.json +6 -0
- package/test-fixtures/non-breaking-space/02/record.json +15 -0
- package/test-fixtures/non-breaking-space/03/expectedResult.json +17 -0
- package/test-fixtures/non-breaking-space/03/metadata.json +6 -0
- package/test-fixtures/non-breaking-space/03/record.json +15 -0
- package/test-fixtures/non-breaking-space/04/expectedResult.json +21 -0
- package/test-fixtures/non-breaking-space/04/metadata.json +6 -0
- package/test-fixtures/non-breaking-space/04/record.json +19 -0
- package/test-fixtures/normalize-identifiers/01/expectedResult.json +8 -0
- package/test-fixtures/normalize-identifiers/01/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/01/record.json +81 -0
- package/test-fixtures/normalize-identifiers/02/expectedResult.json +92 -0
- package/test-fixtures/normalize-identifiers/02/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/02/record.json +92 -0
- package/test-fixtures/normalize-identifiers/03/expectedResult.json +63 -0
- package/test-fixtures/normalize-identifiers/03/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/03/record.json +61 -0
- package/test-fixtures/normalize-identifiers/04/expectedResult.json +79 -0
- package/test-fixtures/normalize-identifiers/04/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/04/record.json +77 -0
- package/test-fixtures/normalize-utf8-diacritics/01/expectedResult.json +7 -0
- package/test-fixtures/normalize-utf8-diacritics/01/metadata.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/01/record.json +39 -0
- package/test-fixtures/normalize-utf8-diacritics/02/expectedResult.json +41 -0
- package/test-fixtures/normalize-utf8-diacritics/02/metadata.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/02/record.json +39 -0
- package/test-fixtures/normalize-utf8-diacritics/03/expectedResult.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/03/metadata.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/03/record.json +37 -0
- package/test-fixtures/normalize-utf8-diacritics/04/expectedResult.json +41 -0
- package/test-fixtures/normalize-utf8-diacritics/04/metadata.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/04/record.json +39 -0
- package/test-fixtures/normalize-utf8-diacritics/05/expectedResult.json +41 -0
- package/test-fixtures/normalize-utf8-diacritics/05/metadata.json +5 -0
- package/test-fixtures/normalize-utf8-diacritics/05/record.json +41 -0
- package/test-fixtures/punctuation/01/expectedResult.json +3 -0
- package/test-fixtures/punctuation/01/metadata.json +4 -0
- package/test-fixtures/punctuation/01/record.json +18 -0
- package/test-fixtures/punctuation/02/expectedResult.json +3 -0
- package/test-fixtures/punctuation/02/metadata.json +4 -0
- package/test-fixtures/punctuation/02/record.json +18 -0
- package/test-fixtures/punctuation/03/expectedResult.json +21 -0
- package/test-fixtures/punctuation/03/metadata.json +5 -0
- package/test-fixtures/punctuation/03/record.json +19 -0
- package/test-fixtures/punctuation/04/expectedResult.json +21 -0
- package/test-fixtures/punctuation/04/metadata.json +5 -0
- package/test-fixtures/punctuation/04/record.json +19 -0
- package/test-fixtures/punctuation/05/expectedResult.json +44 -0
- package/test-fixtures/punctuation/05/metadata.json +5 -0
- package/test-fixtures/punctuation/05/record.json +42 -0
- package/test-fixtures/punctuation2/01/expectedResult.json +12 -0
- package/test-fixtures/punctuation2/01/metadata.json +6 -0
- package/test-fixtures/punctuation2/01/record.json +37 -0
- package/test-fixtures/punctuation2/02/expectedResult.json +4 -0
- package/test-fixtures/punctuation2/02/metadata.json +6 -0
- package/test-fixtures/punctuation2/02/record.json +14 -0
- package/test-fixtures/punctuation2/04/expectedResult.json +7 -0
- package/test-fixtures/punctuation2/04/metadata.json +6 -0
- package/test-fixtures/punctuation2/04/record.json +22 -0
- package/test-fixtures/punctuation2/05/expectedResult.json +6 -0
- package/test-fixtures/punctuation2/05/metadata.json +6 -0
- package/test-fixtures/punctuation2/05/record.json +12 -0
- package/test-fixtures/punctuation2/98/expectedResult.json +45 -0
- package/test-fixtures/punctuation2/98/metadata.json +6 -0
- package/test-fixtures/punctuation2/98/record.json +43 -0
- package/test-fixtures/punctuation2/99/expectedResult.json +15 -0
- package/test-fixtures/punctuation2/99/metadata.json +6 -0
- package/test-fixtures/punctuation2/99/record.json +14 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f01/expectedResult.json +35 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f01/metadata.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f01/record.json +34 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f02/expectedResult.json +53 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f02/metadata.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f02/record.json +51 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f03/expectedResult.json +46 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f03/metadata.json +7 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/f03/record.json +44 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v01/expectedResult.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v01/metadata.json +5 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v01/record.json +31 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v02/expectedResult.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v02/metadata.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v02/record.json +38 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v03/expectedResult.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v03/metadata.json +6 -0
- package/test-fixtures/reindex-sf6-occurence-numbers/v03/record.json +30 -0
- package/test-fixtures/remove-duplicate-datafields/f01/expectedResult.json +35 -0
- package/test-fixtures/remove-duplicate-datafields/f01/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f01/record.json +34 -0
- package/test-fixtures/remove-duplicate-datafields/f03/expectedResult.json +20 -0
- package/test-fixtures/remove-duplicate-datafields/f03/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f03/record.json +33 -0
- package/test-fixtures/remove-duplicate-datafields/f03b/expectedResult.json +20 -0
- package/test-fixtures/remove-duplicate-datafields/f03b/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f03b/record.json +35 -0
- package/test-fixtures/remove-duplicate-datafields/f03c/expectedResult.json +25 -0
- package/test-fixtures/remove-duplicate-datafields/f03c/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f03c/record.json +43 -0
- package/test-fixtures/remove-duplicate-datafields/f04/expectedResult.json +31 -0
- package/test-fixtures/remove-duplicate-datafields/f04/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f04/record.json +41 -0
- package/test-fixtures/remove-duplicate-datafields/f05/expectedResult.json +23 -0
- package/test-fixtures/remove-duplicate-datafields/f05/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f05/record.json +29 -0
- package/test-fixtures/remove-duplicate-datafields/f06/expectedResult.json +24 -0
- package/test-fixtures/remove-duplicate-datafields/f06/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f06/record.json +41 -0
- package/test-fixtures/remove-duplicate-datafields/f07/expectedResult.json +15 -0
- package/test-fixtures/remove-duplicate-datafields/f07/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f07/record.json +21 -0
- package/test-fixtures/remove-duplicate-datafields/f08/expectedResult.json +21 -0
- package/test-fixtures/remove-duplicate-datafields/f08/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f08/record.json +33 -0
- package/test-fixtures/remove-duplicate-datafields/f09/expectedResult.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f09/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f09/record.json +9 -0
- package/test-fixtures/remove-duplicate-datafields/f10/expectedResult.json +15 -0
- package/test-fixtures/remove-duplicate-datafields/f10/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f10/record.json +24 -0
- package/test-fixtures/remove-duplicate-datafields/f11/expectedResult.json +30 -0
- package/test-fixtures/remove-duplicate-datafields/f11/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/f11/record.json +53 -0
- package/test-fixtures/remove-duplicate-datafields/v01/expectedResult.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/v01/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/v01/record.json +31 -0
- package/test-fixtures/remove-duplicate-datafields/v02/expectedResult.json +10 -0
- package/test-fixtures/remove-duplicate-datafields/v02/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/v02/record.json +45 -0
- package/test-fixtures/remove-duplicate-datafields/v03/expectedResult.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/v03/metadata.json +7 -0
- package/test-fixtures/remove-duplicate-datafields/v03/record.json +37 -0
- package/test-fixtures/remove-duplicate-datafields/v04/expectedResult.json +8 -0
- package/test-fixtures/remove-duplicate-datafields/v04/metadata.json +6 -0
- package/test-fixtures/remove-duplicate-datafields/v04/record.json +41 -0
- package/test-fixtures/remove-inferior-datafields/f01/expectedResult.json +21 -0
- package/test-fixtures/remove-inferior-datafields/f01/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/f01/record.json +31 -0
- package/test-fixtures/remove-inferior-datafields/f03/expectedResult.json +16 -0
- package/test-fixtures/remove-inferior-datafields/f03/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/f03/record.json +27 -0
- package/test-fixtures/remove-inferior-datafields/f04/expectedResult.json +31 -0
- package/test-fixtures/remove-inferior-datafields/f04/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/f04/record.json +38 -0
- package/test-fixtures/remove-inferior-datafields/f05/expectedResult.json +34 -0
- package/test-fixtures/remove-inferior-datafields/f05/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/f05/record.json +41 -0
- package/test-fixtures/remove-inferior-datafields/f06/expectedResult.json +16 -0
- package/test-fixtures/remove-inferior-datafields/f06/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/f06/record.json +20 -0
- package/test-fixtures/remove-inferior-datafields/v01/expectedResult.json +6 -0
- package/test-fixtures/remove-inferior-datafields/v01/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/v01/record.json +31 -0
- package/test-fixtures/remove-inferior-datafields/v02/expectedResult.json +6 -0
- package/test-fixtures/remove-inferior-datafields/v02/metadata.json +6 -0
- package/test-fixtures/remove-inferior-datafields/v02/record.json +21 -0
- package/test-fixtures/remove-orphanded-sf6s/f01/expectedResult.json +35 -0
- package/test-fixtures/remove-orphanded-sf6s/f01/metadata.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/f01/record.json +34 -0
- package/test-fixtures/remove-orphanded-sf6s/f02/expectedResult.json +40 -0
- package/test-fixtures/remove-orphanded-sf6s/f02/metadata.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/f02/record.json +43 -0
- package/test-fixtures/remove-orphanded-sf6s/v01/expectedResult.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/v01/metadata.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/v01/record.json +31 -0
- package/test-fixtures/remove-orphanded-sf6s/v02/expectedResult.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/v02/metadata.json +6 -0
- package/test-fixtures/remove-orphanded-sf6s/v02/record.json +31 -0
- package/test-fixtures/resolvable-ext-references-melinda.js +0 -27
- package/test-fixtures/sanitize-vocabulary-source-codes/f01/expectedResult.json +32 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f01/metadata.json +6 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f01/record.json +32 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f02/expectedResult.json +24 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f02/metadata.json +6 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f02/record.json +24 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/v01/expectedResult.json +12 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/v01/metadata.json +6 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/v01/record.json +24 -0
- package/test-fixtures/sort-relator-terms/f01/expectedResult.json +23 -0
- package/test-fixtures/sort-relator-terms/f01/metadata.json +6 -0
- package/test-fixtures/sort-relator-terms/f01/record.json +22 -0
- package/test-fixtures/sort-relator-terms/f02/expectedResult.json +26 -0
- package/test-fixtures/sort-relator-terms/f02/metadata.json +6 -0
- package/test-fixtures/sort-relator-terms/f02/record.json +22 -0
- package/test-fixtures/sort-relator-terms/v01/expectedResult.json +5 -0
- package/test-fixtures/sort-relator-terms/v01/metadata.json +6 -0
- package/test-fixtures/sort-relator-terms/v01/record.json +22 -0
- package/test-fixtures/sort-relator-terms/v02/expectedResult.json +6 -0
- package/test-fixtures/sort-relator-terms/v02/metadata.json +6 -0
- package/test-fixtures/sort-relator-terms/v02/record.json +14 -0
- package/test-fixtures/sort-subfields/f01/expectedResult.json +24 -0
- package/test-fixtures/sort-subfields/f01/metadata.json +6 -0
- package/test-fixtures/sort-subfields/f01/record.json +20 -0
- package/test-fixtures/sort-subfields/v01/expectedResult.json +5 -0
- package/test-fixtures/sort-subfields/v01/metadata.json +6 -0
- package/test-fixtures/sort-subfields/v01/record.json +24 -0
- package/test-fixtures/sort-subfields/v02/expectedResult.json +6 -0
- package/test-fixtures/sort-subfields/v02/metadata.json +6 -0
- package/test-fixtures/sort-subfields/v02/record.json +8 -0
- package/test-fixtures/strip-punctuation/01/expectedResult.json +12 -0
- package/test-fixtures/strip-punctuation/01/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/01/record.json +37 -0
- package/test-fixtures/strip-punctuation/02/expectedResult.json +4 -0
- package/test-fixtures/strip-punctuation/02/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/02/record.json +14 -0
- package/test-fixtures/strip-punctuation/04/expectedResult.json +6 -0
- package/test-fixtures/strip-punctuation/04/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/04/record.json +22 -0
- package/test-fixtures/strip-punctuation/05/expectedResult.json +6 -0
- package/test-fixtures/strip-punctuation/05/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/05/record.json +12 -0
- package/test-fixtures/strip-punctuation/98/expectedResult.json +44 -0
- package/test-fixtures/strip-punctuation/98/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/98/record.json +45 -0
- package/test-fixtures/strip-punctuation/99/expectedResult.json +16 -0
- package/test-fixtures/strip-punctuation/99/metadata.json +6 -0
- package/test-fixtures/strip-punctuation/99/record.json +16 -0
- package/test-fixtures/subfield0/f01/expectedResult.json +25 -0
- package/test-fixtures/subfield0/f01/metadata.json +6 -0
- package/test-fixtures/subfield0/f01/record.json +23 -0
- package/test-fixtures/subfield0/f02/expectedResult.json +35 -0
- package/test-fixtures/subfield0/f02/metadata.json +6 -0
- package/test-fixtures/subfield0/f02/record.json +41 -0
- package/test-fixtures/subfield0/f03/expectedResult.json +21 -0
- package/test-fixtures/subfield0/f03/metadata.json +7 -0
- package/test-fixtures/subfield0/f03/record.json +24 -0
- package/test-fixtures/subfield0/v01/expectedResult.json +4 -0
- package/test-fixtures/subfield0/v01/metadata.json +6 -0
- package/test-fixtures/subfield0/v01/record.json +23 -0
- package/test-fixtures/subfield0/v02/expectedResult.json +9 -0
- package/test-fixtures/subfield0/v02/metadata.json +6 -0
- package/test-fixtures/subfield0/v02/record.json +38 -0
- package/test-fixtures/typeOfDate-008/01/expectedResult.json +3 -0
- package/test-fixtures/typeOfDate-008/01/metadata.json +4 -0
- package/test-fixtures/typeOfDate-008/01/record.json +14 -0
- package/test-fixtures/typeOfDate-008/02/expectedResult.json +4 -0
- package/test-fixtures/typeOfDate-008/02/metadata.json +4 -0
- package/test-fixtures/typeOfDate-008/02/record.json +14 -0
- package/test-fixtures/typeOfDate-008/03/expectedResult.json +14 -0
- package/test-fixtures/typeOfDate-008/03/metadata.json +5 -0
- package/test-fixtures/typeOfDate-008/03/record.json +14 -0
- package/test-fixtures/typeOfDate-008/04/expectedResult.json +14 -0
- package/test-fixtures/typeOfDate-008/04/metadata.json +5 -0
- package/test-fixtures/typeOfDate-008/04/record.json +14 -0
- package/test-fixtures/typeOfDate-008/05/expectedResult.json +14 -0
- package/test-fixtures/typeOfDate-008/05/metadata.json +5 -0
- package/test-fixtures/typeOfDate-008/05/record.json +14 -0
- package/test-fixtures/update-field-540/f01/expectedResult.json +23 -0
- package/test-fixtures/update-field-540/f01/metadata.json +6 -0
- package/test-fixtures/update-field-540/f01/record.json +23 -0
- package/test-fixtures/update-field-540/v01/expectedResult.json +7 -0
- package/test-fixtures/update-field-540/v01/metadata.json +6 -0
- package/test-fixtures/update-field-540/v01/record.json +23 -0
- package/.travis.yml +0 -10
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
// import createDebugLogger from 'debug';
|
|
2
|
+
// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');
|
|
3
|
+
|
|
4
|
+
import {add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils';
|
|
5
|
+
import {fieldHasSubfield, fieldToString, fieldsToString, nvdebug, subfieldToString} from './utils';
|
|
6
|
+
|
|
7
|
+
// NB! Subfield 6 is non-repeatable and it should always comes first!
|
|
8
|
+
// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.
|
|
9
|
+
// NB! Index value '00' are left as they are (is not paired/indexed/whatever.
|
|
10
|
+
const sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;
|
|
11
|
+
|
|
12
|
+
export function isValidSubfield6(subfield) {
|
|
13
|
+
if (subfield.code !== '6') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return subfield.value.match(sf6Regexp);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function subfield6GetTag(subfield) {
|
|
20
|
+
if (isValidSubfield6(subfield)) {
|
|
21
|
+
return subfield.value.substring(0, 3);
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function subfield6GetOccurrenceNumber(subfield) {
|
|
27
|
+
if (isValidSubfield6(subfield)) {
|
|
28
|
+
// Skip "TAG-" prefix. 2023-02-20: removed 2-digit requirement from here...
|
|
29
|
+
return subfield.value.substring(4).replace(/\D.*$/u, '');
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function subfield6GetOccurrenceNumberAsInteger(subfield) {
|
|
35
|
+
const index = subfield6GetOccurrenceNumber(subfield);
|
|
36
|
+
if (index === undefined || index === '00') {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
const result = parseInt(index, 10);
|
|
40
|
+
//nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debug);
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function subfield6ResetOccurrenceNumber(subfield, occurrenceNumber) {
|
|
45
|
+
if (!isValidSubfield6(subfield)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;
|
|
49
|
+
|
|
50
|
+
const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield); // eslint-disable-line functional/immutable-data
|
|
51
|
+
//nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);
|
|
52
|
+
subfield.value = newValue; // eslint-disable-line functional/immutable-data
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
function subfield6GetTail(subfield) {
|
|
57
|
+
if (isValidSubfield6(subfield)) {
|
|
58
|
+
// Skip "TAG-" prefix. 2023-02-20: removed 2-digit requirement from here...
|
|
59
|
+
return subfield.value.replace(/^\d+-\d+/u, '');
|
|
60
|
+
}
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurrenceNumber) {
|
|
65
|
+
if (subfield.code !== '6') {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
// We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...
|
|
69
|
+
const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1'); // eslint-disable-line prefer-named-capture-group
|
|
70
|
+
nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);
|
|
71
|
+
return key === tagAndOccurrenceNumber;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// <= SUBFIELD, FIELD =>
|
|
75
|
+
|
|
76
|
+
export function fieldGetUnambiguousTag(field) {
|
|
77
|
+
const tags = field.subfields.filter(sf => subfield6GetTag(sf));
|
|
78
|
+
if (tags.length === 1) {
|
|
79
|
+
nvdebug(` GOT ${tags.length} tag(s): ${subfieldToString(tags[0])}`);
|
|
80
|
+
return subfield6GetTag(tags[0]);
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function fieldGetUnambiguousOccurrenceNumber(field) {
|
|
86
|
+
const occurrenceNumbers = field.subfields.filter(sf => subfield6GetOccurrenceNumber(sf));
|
|
87
|
+
if (occurrenceNumbers.length === 1) {
|
|
88
|
+
return subfield6GetOccurrenceNumber(occurrenceNumbers[0]);
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function fieldHasOccurrenceNumber(field, occurrenceNumber) {
|
|
94
|
+
//nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`);
|
|
95
|
+
return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function fieldResetOccurrenceNumber(field, newOccurrenceNumber, oldOccurrenceNumber = undefined) {
|
|
99
|
+
field.subfields.forEach(subfield => innerReset(subfield));
|
|
100
|
+
|
|
101
|
+
function innerReset(subfield) {
|
|
102
|
+
// (Optional) Check that this is really the occurrence number we wan't to reseot
|
|
103
|
+
if (oldOccurrenceNumber !== undefined) {
|
|
104
|
+
const currOccurrenceNumber = subfield6GetOccurrenceNumber(subfield);
|
|
105
|
+
if (currOccurrenceNumber !== oldOccurrenceNumber) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
subfield6ResetOccurrenceNumber(subfield, newOccurrenceNumber);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function intToOccurrenceNumberString(i) {
|
|
114
|
+
return i < 10 ? `0${i}` : `${i}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {
|
|
118
|
+
// used by reducer!
|
|
119
|
+
//nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`);
|
|
120
|
+
const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];
|
|
121
|
+
if (sf6s.length === 0) {
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
// There should always be one, but here we check every subfield.
|
|
125
|
+
//nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debug);
|
|
126
|
+
const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));
|
|
127
|
+
return Math.max(...vals);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
export function fieldHasWantedTagAndOccurrenceNumber(field, tagAndOccurrenceNumber) {
|
|
132
|
+
return field.subfields && field.subfields.some(sf => subfield6HasWantedTagAndOccurrenceNumber(sf, tagAndOccurrenceNumber));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/*
|
|
137
|
+
export function getFieldsWithGivenOccurrenceNumberSubfield6(record, occurrenceNumberAsString) {
|
|
138
|
+
const record.fields.filter(field => field
|
|
139
|
+
|
|
140
|
+
function fieldHasIndex(field, index) {
|
|
141
|
+
if (!field.subfields) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return field.subfields.find(sf => isValidSubfield6(sf) && subfieldGetOccurrenceNumber6(sf) === index);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export function fieldHasValidSubfield6(field) {
|
|
151
|
+
return field.subfields && field.subfields.some(sf => isValidSubfield6(sf));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
function isSubfield6Pair(field, otherField) {
|
|
156
|
+
// No need to log this:
|
|
157
|
+
//nvdebug(`LOOK for $6-pair:\n ${fieldToString(field)}\n ${fieldToString(otherField)}`);
|
|
158
|
+
if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!tagsArePairable6(field.tag, otherField.tag)) {
|
|
163
|
+
//nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`);
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);
|
|
169
|
+
if (fieldIndex === undefined || fieldIndex === '00') {
|
|
170
|
+
//nvdebug(` FAILED. REASON: NO INDEX FOUND`);
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const otherFieldIndex = fieldGetUnambiguousOccurrenceNumber(otherField);
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
if (fieldIndex !== otherFieldIndex) {
|
|
178
|
+
//nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`);
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {
|
|
183
|
+
//nvdebug(` FAILURE: TAG vs $6 TAG`);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
|
|
188
|
+
function tagsArePairable6(tag1, tag2) {
|
|
189
|
+
// How to do XOR operation in one line? Well, this is probably more readable...
|
|
190
|
+
if (tag1 === '880' && tag2 === '880') {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
if (tag1 !== '880' && tag2 !== '880') {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
function subfieldSevenToOneOccurrenceNumber(subfield) {
|
|
202
|
+
if (subfield.code !== '6' || subfield.value.substring(0, 1) !== '7') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
subfield.value = `1${subfield.value.substring(1)}`; // eslint-disable-line functional/immutable-data
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function fieldSevenToOneOccurrenceNumber(field) {
|
|
209
|
+
if (field.tag !== '880') {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
field.subfields.forEach(sf => subfieldSevenToOneOccurrenceNumber(sf));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
export function fieldGetOccurrenceNumberPairs(field, candFields) {
|
|
217
|
+
// NB! TAG!=880 returns 880 fields, TAG==880 returns non-880 field
|
|
218
|
+
//nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);
|
|
219
|
+
const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));
|
|
220
|
+
if (pairs.length === 0) {
|
|
221
|
+
nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);
|
|
222
|
+
return pairs;
|
|
223
|
+
}
|
|
224
|
+
nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);
|
|
225
|
+
pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));
|
|
226
|
+
return pairs;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function fieldGetOccurrenceNumbers(field) {
|
|
230
|
+
/* eslint-disable */
|
|
231
|
+
let occurrenceNumbers = [];
|
|
232
|
+
field.subfields?.forEach(sf => subfieldExtractOccurrenceNumber(sf));
|
|
233
|
+
|
|
234
|
+
function subfieldExtractOccurrenceNumber(sf) {
|
|
235
|
+
if (!isValidSubfield6(sf)) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const occurrenceNumber = subfield6GetOccurrenceNumber(sf);
|
|
239
|
+
if (occurrenceNumber === '00' || occurrenceNumbers.includes(occurrenceNumber)) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
occurrenceNumbers.push(occurrenceNumber);
|
|
243
|
+
}
|
|
244
|
+
/* eslint-enable */
|
|
245
|
+
return occurrenceNumbers;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function fieldsGetOccurrenceNumbers(fields) {
|
|
249
|
+
/* eslint-disable */
|
|
250
|
+
let occurrenceNumbers = [];
|
|
251
|
+
|
|
252
|
+
fields.forEach(f => fieldProcessOccurrenceNumbers(f));
|
|
253
|
+
|
|
254
|
+
function fieldProcessOccurrenceNumbers(f) {
|
|
255
|
+
const newOccurrenceNumbers = fieldGetOccurrenceNumbers(f);
|
|
256
|
+
newOccurrenceNumbers.forEach(occurrenceNumber => {
|
|
257
|
+
if (!occurrenceNumbers.includes(occurrenceNumber)) {
|
|
258
|
+
occurrenceNumbers.push(occurrenceNumber);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/* eslint-enable */
|
|
264
|
+
return occurrenceNumbers;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/*
|
|
268
|
+
export function fieldGetSubfield6Pair(field, record) {
|
|
269
|
+
const pairedFields = record.fields.filter(otherField => isSubfield6Pair(field, otherField));
|
|
270
|
+
if (pairedFields.length !== 1) {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
// NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)
|
|
274
|
+
nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`);
|
|
275
|
+
return pairedFields[0];
|
|
276
|
+
}
|
|
277
|
+
*/
|
|
278
|
+
|
|
279
|
+
/*
|
|
280
|
+
export function pairAndStringify6(field, record) {
|
|
281
|
+
const pair6 = fieldGetSubfield6Pair(field, record);
|
|
282
|
+
if (!pair6) {
|
|
283
|
+
return fieldToNormalizedString(field);
|
|
284
|
+
}
|
|
285
|
+
return fieldsToNormalizedString([field, pair6]);
|
|
286
|
+
}
|
|
287
|
+
*/
|
|
288
|
+
|
|
289
|
+
// Frequencly list for $6 subfields in 1XX/7XX fields:
|
|
290
|
+
// 231115 100
|
|
291
|
+
// 183832 700
|
|
292
|
+
// 28773 710
|
|
293
|
+
// 2047 711
|
|
294
|
+
// 661 110
|
|
295
|
+
// 341 111
|
|
296
|
+
// 284 130
|
|
297
|
+
// 63 730
|
|
298
|
+
// Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.
|
|
299
|
+
// Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:
|
|
300
|
+
|
|
301
|
+
export function is7XX(tag) {
|
|
302
|
+
return ['700', '710', '711', '730'].includes(tag);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
function normalizeEntryTag(tag) {
|
|
307
|
+
if (tag.match(/^[17](?:00|10|11|30)$/u)) {
|
|
308
|
+
return `X${tag.substring(1)}`;
|
|
309
|
+
}
|
|
310
|
+
return tag;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function subfieldToNormalizedString(sf, tag, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {
|
|
314
|
+
// targetLinkingNumber refers to $8.
|
|
315
|
+
// normalizeEntryTagBoolean refers to 1XX/7XX tag values in subfield $6 value.
|
|
316
|
+
if (isValidSubfield6(sf)) { // && targetLinkingNumber === 0) {
|
|
317
|
+
// 1XX/7XX (entry tag) normalization:
|
|
318
|
+
const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(tag) : tag;
|
|
319
|
+
|
|
320
|
+
const occurrenceNumber = normalizeOccurrenceNumber ? 'XX' : subfield6GetOccurrenceNumber(sf);
|
|
321
|
+
// If we are normalizing a $8 chain, don't normalize $6 occurrence number!
|
|
322
|
+
// Replace $6 occurrence number with XX:
|
|
323
|
+
return ` ‡${sf.code} ${tag2}-${occurrenceNumber}${subfield6GetTail(sf)}`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (isValidSubfield8(sf)) {
|
|
327
|
+
const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);
|
|
328
|
+
if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {
|
|
329
|
+
// For $8 we should only XX the index we are looking at...
|
|
330
|
+
const normVal = sf.value.replace(/^[0-9]+/u, 'XX');
|
|
331
|
+
return ` ‡${sf.code} ${normVal}`;
|
|
332
|
+
}
|
|
333
|
+
return ''; // Other $8 subfields are meaningless in this context
|
|
334
|
+
}
|
|
335
|
+
return ` ${subfieldToString(sf)}`; // `‡${sf.code} ${sf.value}`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function fieldToNormalizedString(field, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {
|
|
339
|
+
if ('subfields' in field) {
|
|
340
|
+
const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(field.tag) : field.tag;
|
|
341
|
+
return `${tag2} ${field.ind1}${field.ind2}${formatAndNormalizeSubfields(field)}`;
|
|
342
|
+
}
|
|
343
|
+
return `${field.tag} ${field.value}`;
|
|
344
|
+
|
|
345
|
+
function formatAndNormalizeSubfields(field) {
|
|
346
|
+
return field.subfields.map(sf => subfieldToNormalizedString(sf, field.tag, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTagBoolean)).join('');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
function guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {
|
|
353
|
+
if (defaultTargetLinkingNumber !== 0) {
|
|
354
|
+
return defaultTargetLinkingNumber;
|
|
355
|
+
}
|
|
356
|
+
const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);
|
|
357
|
+
return linkingNumbers.length === 1 ? linkingNumbers[0] : 0; // eslint-disable-line no-param-reassign
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag = false) {
|
|
361
|
+
const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);
|
|
362
|
+
|
|
363
|
+
nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);
|
|
364
|
+
const strings = fields.map(field => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag));
|
|
365
|
+
strings.sort(); // eslint-disable-line functional/immutable-data
|
|
366
|
+
return strings.join('\t__SEPARATOR__\t');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
/*
|
|
371
|
+
|
|
372
|
+
export function removeField6IfNeeded(field, record, fieldsAsString) {
|
|
373
|
+
const pairField = fieldGetSubfield6Pair(field, record);
|
|
374
|
+
const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);
|
|
375
|
+
nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`);
|
|
376
|
+
const tmp = pairField ? fieldToString(pairField) : 'HUTI';
|
|
377
|
+
nvdebug(`PAIR: ${tmp}`);
|
|
378
|
+
nvdebug(`BASE:\n ${fieldsAsString.join('\n ')}`);
|
|
379
|
+
if (!fieldsAsString.includes(asString)) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`);
|
|
383
|
+
record.removeField(field);
|
|
384
|
+
|
|
385
|
+
if (pairField === undefined) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`);
|
|
389
|
+
record.removeField(pairField);
|
|
390
|
+
}
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
function getFirstField(record, fields) {
|
|
394
|
+
const fieldsAsStrings = fields.map(field => fieldToString(field));
|
|
395
|
+
//record.fields.forEach((field, i) => nvdebug(`${i}:\t${fieldToString(field)}`));
|
|
396
|
+
//nvdebug(`getFirstField: ${fieldsAsStrings.join('\t')}`);
|
|
397
|
+
const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));
|
|
398
|
+
if (i > -1) {
|
|
399
|
+
const field = record.fields[i];
|
|
400
|
+
//nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`);
|
|
401
|
+
return field;
|
|
402
|
+
}
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function isRelevantSubfield6Chain(fields) {
|
|
407
|
+
if (fields.length < 2) { // 1 non-880-field and 1+ 880 fields
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
const non880 = fields.filter(f => f.tag !== '880');
|
|
411
|
+
if (non880.length !== 1) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);
|
|
416
|
+
if (linkingNumbers.length !== 0) {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return fields.every(f => fieldHasSubfield(f, '6'));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export function fieldIsFirstFieldInChain(field, chain, record) {
|
|
424
|
+
// Interpretation of first: position of field in record (however, we might have a duplicate field. See tests...)
|
|
425
|
+
const firstField = getFirstField(record, chain);
|
|
426
|
+
if (firstField) {
|
|
427
|
+
return fieldToString(field) === fieldToString(firstField);
|
|
428
|
+
}
|
|
429
|
+
return false;
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
export function getAllLinkedSubfield6Fields(field, record) {
|
|
435
|
+
const fields = get6s(field, record);
|
|
436
|
+
const moreFields = add8s(fields, record);
|
|
437
|
+
|
|
438
|
+
// Currently we don't handle fields with more than one $6 and/or $8 subfield.
|
|
439
|
+
if (moreFields.length > fields.length) {
|
|
440
|
+
return []; // Don't fix!
|
|
441
|
+
}
|
|
442
|
+
return moreFields;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function isFirstLinkedSubfield6Field(field, record) {
|
|
446
|
+
if (!field.subfields) { // Is not a datafield
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
const chain = getAllLinkedSubfield6Fields(field, record);
|
|
450
|
+
if (!isRelevantSubfield6Chain(chain)) {
|
|
451
|
+
nvdebug(`Rejected 6: ${fieldsToString(chain)}`);
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return fieldIsFirstFieldInChain(field, chain, record);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export function recordGetSubfield6ChainHeads(record) {
|
|
459
|
+
return record.fields.filter(field => isFirstLinkedSubfield6Field(field, record));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export function recordGetMaxSubfield6OccurrenceNumberAsInteger(record) {
|
|
463
|
+
// Should we cache the value here?
|
|
464
|
+
const vals = record.fields.map((field) => fieldGetMaxSubfield6OccurrenceNumberAsInteger(field));
|
|
465
|
+
return Math.max(...vals);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
export function get6s(field, candidateFields) { // NB! Convert field to fields!!!
|
|
470
|
+
// Get all fields with given occurence number
|
|
471
|
+
const sixes = field.subfields.filter(sf => isValidSubfield6(sf));
|
|
472
|
+
|
|
473
|
+
if (sixes.length === 0) {
|
|
474
|
+
return [field];
|
|
475
|
+
}
|
|
476
|
+
nvdebug(`SIXES: ${sixes.length}`);
|
|
477
|
+
const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');
|
|
478
|
+
nvdebug(occurrenceNumbers.join(' -- '));
|
|
479
|
+
|
|
480
|
+
const relevantFields = candidateFields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));
|
|
481
|
+
nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);
|
|
482
|
+
relevantFields.forEach(f => nvdebug(fieldToString(f)));
|
|
483
|
+
return relevantFields;
|
|
484
|
+
}
|
|
485
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// import createDebugLogger from 'debug';
|
|
2
|
+
// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield8Utils');
|
|
3
|
+
|
|
4
|
+
import {fieldToString, nvdebug} from './utils';
|
|
5
|
+
|
|
6
|
+
const sf8Regexp = /^([1-9][0-9]*)(?:\.[0-9]+)?(?:\\[acprux])?$/u; // eslint-disable-line prefer-named-capture-group
|
|
7
|
+
|
|
8
|
+
export function isValidSubfield8(subfield) {
|
|
9
|
+
if (subfield.code !== '8') {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}'`);
|
|
14
|
+
const match = subfield.value.match(sf8Regexp);
|
|
15
|
+
//nvdebug(` IS VALID $8? '${subfieldToString(subfield)}' vs ${match.length}}`);
|
|
16
|
+
return match && match.length > 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getSubfield8Value(subfield) {
|
|
20
|
+
if (!isValidSubfield8(subfield)) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return subfield.value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getSubfield8LinkingNumber(subfield) {
|
|
27
|
+
const value = getSubfield8Value(subfield);
|
|
28
|
+
if (value === undefined) {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
return parseInt(value, 10);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export function fieldHasLinkingNumber(field, linkingNumber) {
|
|
36
|
+
if (!field.subfields) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return field.subfields.some(sf => getSubfield8LinkingNumber(sf) === linkingNumber);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function recordGetFieldsWithSubfield8LinkingNumber(record, linkingNumber) {
|
|
43
|
+
if (linkingNumber < 1) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return record.fields.filter(field => fieldHasLinkingNumber(field, linkingNumber));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export function fieldsGetAllSubfield8LinkingNumbers(fields) {
|
|
51
|
+
/* eslint-disable */
|
|
52
|
+
let subfield8LinkingNumbers = [];
|
|
53
|
+
fields.forEach(field => {
|
|
54
|
+
if (!field.subfields) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
field.subfields.forEach(sf => {
|
|
58
|
+
const linkingNumber = getSubfield8LinkingNumber(sf);
|
|
59
|
+
if (linkingNumber > 0 && !subfield8LinkingNumbers.includes(linkingNumber)) {
|
|
60
|
+
nvdebug(` LINK8: Add subfield \$8 ${linkingNumber} to seen values list`);
|
|
61
|
+
subfield8LinkingNumbers.push(linkingNumber);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return subfield8LinkingNumbers;
|
|
67
|
+
/* eslint-enable */
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function recordGetAllSubfield8LinkingNumbers(record) {
|
|
72
|
+
return fieldsGetAllSubfield8LinkingNumbers(record.fields);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
export function add8s(fields, record) {
|
|
77
|
+
const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);
|
|
78
|
+
if (linkingNumbers.length === 0) {
|
|
79
|
+
return fields;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
nvdebug(`Linking number(s): ${linkingNumbers.join(', ')}`);
|
|
83
|
+
linkingNumbers.forEach(number => collectLinkingNumberFields(number));
|
|
84
|
+
|
|
85
|
+
fields.forEach(f => nvdebug(`AFTER ADDING 8s: '${fieldToString(f)}'`));
|
|
86
|
+
|
|
87
|
+
return fields;
|
|
88
|
+
|
|
89
|
+
function collectLinkingNumberFields(linkingNumber) {
|
|
90
|
+
// Remove existing hits (to avoid field repetition):
|
|
91
|
+
fields = fields.filter(f => !fieldHasLinkingNumber(f, linkingNumber)); // eslint-disable-line functional/immutable-data, no-param-reassign
|
|
92
|
+
// Add them and their "sisters" back:
|
|
93
|
+
const addableFields = record.fields.filter(f => fieldHasLinkingNumber(f, linkingNumber));
|
|
94
|
+
addableFields.forEach(f => nvdebug(`(RE-?)ADD ${fieldToString(f)}`));
|
|
95
|
+
fields = fields.concat(addableFields); // eslint-disable-line functional/immutable-data, no-param-reassign
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function fieldHasValidSubfield8(field) {
|
|
101
|
+
return field.subfields && field.subfields.some(sf => isValidSubfield8(sf));
|
|
102
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import createDebugLogger from 'debug';
|
|
2
|
+
|
|
3
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/typeOfDate-008'); // eslint-disable-line
|
|
4
|
+
|
|
5
|
+
export default function () {
|
|
6
|
+
return {
|
|
7
|
+
description: 'Validates 008 06',
|
|
8
|
+
validate,
|
|
9
|
+
fix
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function validate(record) {
|
|
13
|
+
const [f008] = record.get(/008/u);
|
|
14
|
+
const c06 = f008.value.substring(6, 7);
|
|
15
|
+
const c1114 = f008.value.substring(11, 15);
|
|
16
|
+
// if 008 06 = s, and 11-14 = #### (not year/digits)
|
|
17
|
+
if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {
|
|
18
|
+
debug('is t and not valid 1114');
|
|
19
|
+
return {valid: false, message: 'Invalid 008 06'};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {valid: true};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function fix(record) {
|
|
26
|
+
// LDR/06=t ja 11-14=####, niin LDR/06 muutetaan s:ksi
|
|
27
|
+
const [f008] = record.pop(/008/u); // eslint-disable-line functional/immutable-data
|
|
28
|
+
const c06 = f008.value.substring(6, 7);
|
|
29
|
+
const c1114 = f008.value.substring(11, 15);
|
|
30
|
+
// if 008 06 = s, and 11-14 = #### (not year/digits)
|
|
31
|
+
if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {
|
|
32
|
+
f008.value = `${f008.value.substring(0, 6)}s${f008.value.substring(7)}`; // eslint-disable-line functional/immutable-data
|
|
33
|
+
record.insertField(f008);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
record.insertField(f008);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
|
+
import validatorFactory from './typeOfDate-008';
|
|
4
|
+
import {READERS} from '@natlibfi/fixura';
|
|
5
|
+
import generateTests from '@natlibfi/fixugen';
|
|
6
|
+
import createDebugLogger from 'debug';
|
|
7
|
+
|
|
8
|
+
generateTests({
|
|
9
|
+
callback,
|
|
10
|
+
path: [__dirname, '..', 'test-fixtures', 'typeOfDate-008'],
|
|
11
|
+
useMetadataFile: true,
|
|
12
|
+
recurse: false,
|
|
13
|
+
fixura: {
|
|
14
|
+
reader: READERS.JSON
|
|
15
|
+
},
|
|
16
|
+
mocha: {
|
|
17
|
+
before: () => testValidatorFactory()
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/typeOfDate-008:test'); // eslint-disable-line
|
|
21
|
+
|
|
22
|
+
async function testValidatorFactory() {
|
|
23
|
+
const validator = await validatorFactory();
|
|
24
|
+
|
|
25
|
+
expect(validator)
|
|
26
|
+
.to.be.an('object')
|
|
27
|
+
.that.has.any.keys('description', 'validate');
|
|
28
|
+
|
|
29
|
+
expect(validator.description).to.be.a('string');
|
|
30
|
+
expect(validator.validate).to.be.a('function');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function callback({getFixture, fix = false}) {
|
|
34
|
+
const validator = await validatorFactory();
|
|
35
|
+
const record = new MarcRecord(getFixture('record.json'));
|
|
36
|
+
const expectedResult = getFixture('expectedResult.json');
|
|
37
|
+
// console.log(expectedResult); // eslint-disable-line
|
|
38
|
+
|
|
39
|
+
if (!fix) {
|
|
40
|
+
const result = await validator.validate(record);
|
|
41
|
+
expect(result).to.eql(expectedResult);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await validator.fix(record);
|
|
46
|
+
expect(record).to.eql(expectedResult);
|
|
47
|
+
}
|