@natlibfi/marc-record-validators-melinda 12.1.0-alpha.1 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/melinda-node-tests-and-publish.yml +17 -17
- package/README.md +1 -1
- package/dist/addMissingField041.js +6 -3
- package/dist/addMissingField041.js.map +2 -2
- package/dist/addMissingField336.js +7 -4
- package/dist/addMissingField336.js.map +2 -2
- package/dist/addMissingField337.js +6 -3
- package/dist/addMissingField337.js.map +2 -2
- package/dist/addMissingField338.js +8 -5
- package/dist/addMissingField338.js.map +2 -2
- package/dist/cyrillux-usemarcon-replacement.js +5 -2
- package/dist/cyrillux-usemarcon-replacement.js.map +2 -2
- package/dist/cyrillux.js +24 -18
- package/dist/cyrillux.js.map +2 -2
- package/dist/dataProvenanceUtils.js +19 -0
- package/dist/dataProvenanceUtils.js.map +7 -0
- package/dist/disambiguateSeriesStatements.js +2 -1
- package/dist/disambiguateSeriesStatements.js.map +2 -2
- package/dist/disambiguateSeriesStatements.test.js +1 -7
- package/dist/disambiguateSeriesStatements.test.js.map +2 -2
- package/dist/drop-terms.js +123 -0
- package/dist/drop-terms.js.map +7 -0
- package/dist/drop-terms.test.js +56 -0
- package/dist/drop-terms.test.js.map +7 -0
- package/dist/field-008-18-34-character-groups.test.js +1 -7
- package/dist/field-008-18-34-character-groups.test.js.map +2 -2
- package/dist/field-505-separators.test.js +1 -7
- package/dist/field-505-separators.test.js.map +2 -2
- package/dist/field-521-fix.test.js +1 -7
- package/dist/field-521-fix.test.js.map +2 -2
- package/dist/fix-33X.js +7 -4
- package/dist/fix-33X.js.map +2 -2
- package/dist/fix-33X.test.js +1 -1
- package/dist/fix-33X.test.js.map +1 -1
- package/dist/fix-country-codes.js +5 -0
- package/dist/fix-country-codes.js.map +2 -2
- package/dist/fix-country-codes.test.js +1 -7
- package/dist/fix-country-codes.test.js.map +2 -2
- package/dist/fix-language-codes.js +5 -1
- package/dist/fix-language-codes.js.map +2 -2
- package/dist/fix-sami-041.js +109 -0
- package/dist/fix-sami-041.js.map +7 -0
- package/dist/fix-sami-041.test.js +40 -0
- package/dist/fix-sami-041.test.js.map +7 -0
- package/dist/fixRelatorTerms.js +2 -0
- package/dist/fixRelatorTerms.js.map +2 -2
- package/dist/fixRelatorTerms.test.js +1 -7
- package/dist/fixRelatorTerms.test.js.map +2 -2
- package/dist/index.js +18 -4
- package/dist/index.js.map +2 -2
- package/dist/indicator-fixes.js +15 -1
- package/dist/indicator-fixes.js.map +2 -2
- package/dist/indicator-fixes.test.js +1 -7
- package/dist/indicator-fixes.test.js.map +2 -2
- package/dist/item-language.js +41 -39
- package/dist/item-language.js.map +2 -2
- package/dist/item-language.test.js +3 -3
- package/dist/item-language.test.js.map +2 -2
- package/dist/melindaCustomMergeFields.js +31 -0
- package/dist/melindaCustomMergeFields.js.map +2 -2
- package/dist/merge-fields/controlSubfields.js.map +2 -2
- package/dist/merge-fields/counterpartField.js +149 -152
- package/dist/merge-fields/counterpartField.js.map +3 -3
- package/dist/merge-fields/dataProvenance.js +6 -20
- package/dist/merge-fields/dataProvenance.js.map +2 -2
- package/dist/merge-fields/index.js +1 -1
- package/dist/merge-fields/index.js.map +2 -2
- package/dist/merge-fields/mergableIndicator.js +1 -5
- package/dist/merge-fields/mergableIndicator.js.map +2 -2
- package/dist/merge-fields/mergableTag.js +2 -0
- package/dist/merge-fields/mergableTag.js.map +2 -2
- package/dist/merge-fields/mergeConfig.js +2 -0
- package/dist/merge-fields/mergeConfig.js.map +2 -2
- package/dist/merge-fields/mergeConstraints.js +38 -35
- package/dist/merge-fields/mergeConstraints.js.map +3 -3
- package/dist/merge-fields/mergeField.js +4 -3
- package/dist/merge-fields/mergeField.js.map +2 -2
- package/dist/merge-fields/mergeOrAddSubfield.js +8 -7
- package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
- package/dist/merge-fields/mergeSubfield.js +5 -1
- package/dist/merge-fields/mergeSubfield.js.map +2 -2
- package/dist/merge-fields/worldKnowledge.js +52 -0
- package/dist/merge-fields/worldKnowledge.js.map +2 -2
- package/dist/merge-fields.test.js +4 -9
- package/dist/merge-fields.test.js.map +2 -2
- package/dist/mergeField500Lisapainokset.test.js +1 -7
- package/dist/mergeField500Lisapainokset.test.js.map +2 -2
- package/dist/mergeRelatorTermFields.js +9 -6
- package/dist/mergeRelatorTermFields.js.map +2 -2
- package/dist/mergeRelatorTermFields.test.js +1 -7
- package/dist/mergeRelatorTermFields.test.js.map +2 -2
- package/dist/multiple-subfield-0.test.js +1 -7
- package/dist/multiple-subfield-0.test.js.map +2 -2
- package/dist/normalize-dashes.js +9 -6
- package/dist/normalize-dashes.js.map +2 -2
- package/dist/normalize-dashes.test.js +1 -7
- package/dist/normalize-dashes.test.js.map +2 -2
- package/dist/normalize-identifiers.js.map +2 -2
- package/dist/normalize-identifiers.test.js +1 -7
- package/dist/normalize-identifiers.test.js.map +2 -2
- package/dist/normalize-qualifying-information.test.js +1 -7
- package/dist/normalize-qualifying-information.test.js.map +2 -2
- package/dist/normalize-utf8-diacritics.js.map +2 -2
- package/dist/normalize-utf8-diacritics.test.js +1 -7
- package/dist/normalize-utf8-diacritics.test.js.map +2 -2
- package/dist/normalizeFieldForComparison.js +24 -14
- package/dist/normalizeFieldForComparison.js.map +2 -2
- package/dist/normalizeSubfieldValueForComparison.js.map +1 -1
- package/dist/prepublicationUtils.js +1 -1
- package/dist/prepublicationUtils.js.map +2 -2
- package/dist/punctuation.test.js +1 -7
- package/dist/punctuation.test.js.map +2 -2
- package/dist/punctuation2.js +15 -12
- package/dist/punctuation2.js.map +2 -2
- package/dist/punctuation2.test.js +1 -7
- package/dist/punctuation2.test.js.map +2 -2
- package/dist/reindexSubfield6OccurenceNumbers.js +11 -10
- package/dist/reindexSubfield6OccurenceNumbers.js.map +2 -2
- package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
- package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
- package/dist/remove-041-zxx.js +56 -0
- package/dist/remove-041-zxx.js.map +7 -0
- package/dist/remove-041-zxx.test.js +40 -0
- package/dist/remove-041-zxx.test.js.map +7 -0
- package/dist/removeDuplicateDataFields.js +4 -26
- package/dist/removeDuplicateDataFields.js.map +2 -2
- package/dist/removeDuplicateDataFields.test.js +1 -7
- package/dist/removeDuplicateDataFields.test.js.map +2 -2
- package/dist/removeInferiorDataFields.js +82 -45
- package/dist/removeInferiorDataFields.js.map +3 -3
- package/dist/removeInferiorDataFields.test.js +5 -9
- package/dist/removeInferiorDataFields.test.js.map +2 -2
- package/dist/resolveOrphanedSubfield6s.js +4 -5
- package/dist/resolveOrphanedSubfield6s.js.map +2 -2
- package/dist/resolveOrphanedSubfield6s.test.js +1 -7
- package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
- package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
- package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
- package/dist/sortFields.js +16 -1
- package/dist/sortFields.js.map +2 -2
- package/dist/sortFields.test.js +1 -7
- package/dist/sortFields.test.js.map +2 -2
- package/dist/sortRelatorTerms.test.js +1 -7
- package/dist/sortRelatorTerms.test.js.map +2 -2
- package/dist/sortSubfields.js +27 -21
- package/dist/sortSubfields.js.map +2 -2
- package/dist/sortSubfields.test.js +1 -7
- package/dist/sortSubfields.test.js.map +2 -2
- package/dist/stripPunctuation.js +7 -3
- package/dist/stripPunctuation.js.map +2 -2
- package/dist/stripPunctuation.test.js +1 -7
- package/dist/stripPunctuation.test.js.map +2 -2
- package/dist/subfield6Utils.js +2 -12
- package/dist/subfield6Utils.js.map +2 -2
- package/dist/subfield8Utils.js +0 -5
- package/dist/subfield8Utils.js.map +2 -2
- package/dist/subfieldValueNormalizations.test.js +1 -7
- package/dist/subfieldValueNormalizations.test.js.map +2 -2
- package/dist/sync-007-and-300.test.js +1 -7
- package/dist/sync-007-and-300.test.js.map +2 -2
- package/dist/sync-language.js +103 -0
- package/dist/sync-language.js.map +7 -0
- package/dist/sync-language.test.js +40 -0
- package/dist/sync-language.test.js.map +7 -0
- package/dist/translate-terms.js +124 -87
- package/dist/translate-terms.js.map +3 -3
- package/dist/translate-terms.test.js +5 -8
- package/dist/translate-terms.test.js.map +2 -2
- package/dist/typeOfDate-008.js +3 -1
- package/dist/typeOfDate-008.js.map +2 -2
- package/dist/update-field-540.js.map +2 -2
- package/dist/update-field-540.test.js +1 -7
- package/dist/update-field-540.test.js.map +2 -2
- package/dist/urn.js +13 -12
- package/dist/urn.js.map +2 -2
- package/dist/urn.test.js +1 -7
- package/dist/urn.test.js.map +2 -2
- package/dist/utils.js +29 -3
- package/dist/utils.js.map +2 -2
- package/package.json +20 -27
- package/src/addMissingField041.js +8 -4
- package/src/addMissingField336.js +10 -5
- package/src/addMissingField337.js +9 -5
- package/src/addMissingField338.js +11 -6
- package/src/cyrillux-usemarcon-replacement.js +9 -5
- package/src/cyrillux.js +34 -23
- package/src/dataProvenanceUtils.js +21 -0
- package/src/disambiguateSeriesStatements.js +4 -1
- package/src/disambiguateSeriesStatements.test.js +3 -8
- package/src/drop-terms.js +164 -0
- package/src/drop-terms.test.js +81 -0
- package/src/field-008-18-34-character-groups.test.js +3 -8
- package/src/field-505-separators.test.js +3 -8
- package/src/field-521-fix.test.js +3 -8
- package/src/fix-33X.js +10 -6
- package/src/fix-33X.test.js +1 -1
- package/src/fix-country-codes.js +7 -3
- package/src/fix-country-codes.test.js +3 -8
- package/src/fix-language-codes.js +8 -4
- package/src/fix-sami-041.js +147 -0
- package/src/fix-sami-041.test.js +52 -0
- package/src/fixRelatorTerms.js +5 -0
- package/src/fixRelatorTerms.test.js +3 -8
- package/src/index.js +20 -7
- package/src/indicator-fixes.js +22 -7
- package/src/indicator-fixes.test.js +3 -8
- package/src/item-language.js +49 -42
- package/src/item-language.test.js +3 -3
- package/src/melindaCustomMergeFields.js +31 -0
- package/src/merge-fields/controlSubfields.js +0 -1
- package/src/merge-fields/counterpartField.js +191 -290
- package/src/merge-fields/dataProvenance.js +8 -25
- package/src/merge-fields/index.js +1 -1
- package/src/merge-fields/mergableIndicator.js +4 -5
- package/src/merge-fields/mergableTag.js +2 -0
- package/src/merge-fields/mergeConfig.js +2 -1
- package/src/merge-fields/mergeConstraints.js +41 -36
- package/src/merge-fields/mergeField.js +4 -7
- package/src/merge-fields/mergeOrAddSubfield.js +8 -7
- package/src/merge-fields/mergeSubfield.js +11 -2
- package/src/merge-fields/worldKnowledge.js +77 -3
- package/src/merge-fields.test.js +5 -10
- package/src/mergeField500Lisapainokset.test.js +3 -8
- package/src/mergeRelatorTermFields.js +12 -11
- package/src/mergeRelatorTermFields.test.js +3 -8
- package/src/multiple-subfield-0.test.js +3 -8
- package/src/normalize-dashes.js +13 -7
- package/src/normalize-dashes.test.js +3 -8
- package/src/normalize-identifiers.js +12 -19
- package/src/normalize-identifiers.test.js +3 -8
- package/src/normalize-qualifying-information.test.js +3 -8
- package/src/normalize-utf8-diacritics.js +6 -3
- package/src/normalize-utf8-diacritics.test.js +3 -8
- package/src/normalizeFieldForComparison.js +39 -22
- package/src/normalizeSubfieldValueForComparison.js +2 -2
- package/src/prepublicationUtils.js +1 -1
- package/src/punctuation.test.js +3 -8
- package/src/punctuation2.js +44 -40
- package/src/punctuation2.test.js +3 -8
- package/src/reindexSubfield6OccurenceNumbers.js +13 -11
- package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
- package/src/remove-041-zxx.js +85 -0
- package/src/remove-041-zxx.test.js +52 -0
- package/src/removeDuplicateDataFields.js +30 -28
- package/src/removeDuplicateDataFields.test.js +3 -8
- package/src/removeInferiorDataFields.js +126 -71
- package/src/removeInferiorDataFields.test.js +7 -10
- package/src/resolveOrphanedSubfield6s.js +7 -5
- package/src/resolveOrphanedSubfield6s.test.js +3 -8
- package/src/sanitize-vocabulary-source-codes.test.js +3 -8
- package/src/sortFields.js +20 -1
- package/src/sortFields.test.js +3 -8
- package/src/sortRelatorTerms.test.js +3 -8
- package/src/sortSubfields.js +31 -25
- package/src/sortSubfields.test.js +3 -8
- package/src/stripPunctuation.js +10 -5
- package/src/stripPunctuation.test.js +3 -8
- package/src/subfield6Utils.js +31 -33
- package/src/subfield8Utils.js +10 -7
- package/src/subfieldValueNormalizations.test.js +3 -8
- package/src/sync-007-and-300.test.js +3 -8
- package/src/sync-language.js +148 -0
- package/src/sync-language.test.js +52 -0
- package/src/translate-terms.js +168 -109
- package/src/translate-terms.test.js +12 -16
- package/src/typeOfDate-008.js +4 -1
- package/src/update-field-540.js +7 -5
- package/src/update-field-540.test.js +3 -8
- package/src/urn.js +17 -13
- package/src/urn.test.js +3 -8
- package/src/utils.js +39 -12
- package/test-fixtures/cyrillux/f02b/expectedResult.json +23 -0
- package/test-fixtures/cyrillux/f02b/metadata.json +11 -0
- package/test-fixtures/cyrillux/f02b/record.json +14 -0
- package/test-fixtures/cyrillux/f14/expectedResult.json +32 -0
- package/test-fixtures/cyrillux/f14/metadata.json +10 -0
- package/test-fixtures/cyrillux/f14/record.json +14 -0
- package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
- package/test-fixtures/drop-terms/01/metadata.json +6 -0
- package/test-fixtures/drop-terms/01/record.json +35 -0
- package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
- package/test-fixtures/drop-terms/02/metadata.json +6 -0
- package/test-fixtures/drop-terms/02/record.json +40 -0
- package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
- package/test-fixtures/drop-terms/03/metadata.json +18 -0
- package/test-fixtures/drop-terms/03/record.json +39 -0
- package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
- package/test-fixtures/drop-terms/04/metadata.json +19 -0
- package/test-fixtures/drop-terms/04/record.json +24 -0
- package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
- package/test-fixtures/fix-relator-terms/f02/metadata.json +1 -1
- package/test-fixtures/fix-relator-terms/f04/expectedResult.json +18 -0
- package/test-fixtures/fix-relator-terms/f04/metadata.json +5 -0
- package/test-fixtures/fix-relator-terms/f04/record.json +20 -0
- package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
- package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/01/record.json +14 -0
- package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
- package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/02/record.json +8 -0
- package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
- package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
- package/test-fixtures/fix-sami-041/03/record.json +8 -0
- package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
- package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/04/record.json +10 -0
- package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
- package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
- package/test-fixtures/fix-sami-041/05/record.json +8 -0
- package/test-fixtures/fix-sami-041/06/expectedResult.json +10 -0
- package/test-fixtures/fix-sami-041/06/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/06/record.json +9 -0
- package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
- package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
- package/test-fixtures/indicator-fixes/11/record.json +10 -0
- package/test-fixtures/merge-fields/f042_01/expectedResult.json +12 -0
- package/test-fixtures/merge-fields/f042_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f042_01/record.json +13 -0
- package/test-fixtures/merge-fields/f05/metadata.json +1 -1
- package/test-fixtures/merge-fields/f06/expectedResult.json +42 -0
- package/test-fixtures/merge-fields/f06/metadata.json +6 -0
- package/test-fixtures/merge-fields/f06/record.json +41 -0
- package/test-fixtures/merge-fields/f07/expectedResult.json +18 -0
- package/test-fixtures/merge-fields/f07/metadata.json +6 -0
- package/test-fixtures/merge-fields/f07/record.json +18 -0
- package/test-fixtures/merge-fields/f08/expectedResult.json +12 -0
- package/test-fixtures/merge-fields/f08/metadata.json +7 -0
- package/test-fixtures/merge-fields/f08/record.json +10 -0
- package/test-fixtures/merge-fields/f09/expectedResult.json +14 -0
- package/test-fixtures/merge-fields/f09/metadata.json +6 -0
- package/test-fixtures/merge-fields/f09/record.json +14 -0
- package/test-fixtures/merge-fields/f10/expectedResult.json +25 -0
- package/test-fixtures/merge-fields/f10/metadata.json +6 -0
- package/test-fixtures/merge-fields/f10/record.json +25 -0
- package/test-fixtures/merge-fields/f11/expectedResult.json +40 -0
- package/test-fixtures/merge-fields/f11/metadata.json +7 -0
- package/test-fixtures/merge-fields/f11/record.json +50 -0
- package/test-fixtures/merge-fields/f12/expectedResult.json +17 -0
- package/test-fixtures/merge-fields/f12/metadata.json +6 -0
- package/test-fixtures/merge-fields/f12/record.json +25 -0
- package/test-fixtures/merge-fields/f13/expectedResult.json +18 -0
- package/test-fixtures/merge-fields/f13/metadata.json +6 -0
- package/test-fixtures/merge-fields/f13/record.json +28 -0
- package/test-fixtures/merge-fields/f14/expectedResult.json +25 -0
- package/test-fixtures/merge-fields/f14/metadata.json +6 -0
- package/test-fixtures/merge-fields/f14/record.json +25 -0
- package/test-fixtures/merge-fields/f15/expectedResult.json +8 -0
- package/test-fixtures/merge-fields/f15/metadata.json +6 -0
- package/test-fixtures/merge-fields/f15/record.json +9 -0
- package/test-fixtures/merge-fields/f16/expectedResult.json +12 -0
- package/test-fixtures/merge-fields/f16/metadata.json +7 -0
- package/test-fixtures/merge-fields/f16/record.json +13 -0
- package/test-fixtures/merge-fields/f300_01/expectedResult.json +9 -0
- package/test-fixtures/merge-fields/f300_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f300_01/record.json +8 -0
- package/test-fixtures/merge-fields/f300_02/expectedResult.json +13 -0
- package/test-fixtures/merge-fields/f300_02/metadata.json +6 -0
- package/test-fixtures/merge-fields/f300_02/record.json +16 -0
- package/test-fixtures/merge-fields/f300_03/expectedResult.json +13 -0
- package/test-fixtures/merge-fields/f300_03/metadata.json +6 -0
- package/test-fixtures/merge-fields/f300_03/record.json +16 -0
- package/test-fixtures/merge-fields/f490_01/expectedResult.json +13 -0
- package/test-fixtures/merge-fields/f490_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f490_01/record.json +16 -0
- package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
- package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/01/record.json +10 -0
- package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
- package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/02/record.json +9 -0
- package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
- package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/11/record.json +9 -0
- package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
- package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/12/record.json +9 -0
- package/test-fixtures/remove-inferior-datafields/f17/expectedResult.json +11 -0
- package/test-fixtures/remove-inferior-datafields/f17/metadata.json +5 -0
- package/test-fixtures/remove-inferior-datafields/f17/record.json +15 -0
- package/test-fixtures/remove-inferior-datafields/f18/expectedResult.json +13 -0
- package/test-fixtures/remove-inferior-datafields/f18/metadata.json +5 -0
- package/test-fixtures/remove-inferior-datafields/f18/record.json +18 -0
- package/test-fixtures/remove-inferior-datafields/f19/expectedResult.json +17 -0
- package/test-fixtures/remove-inferior-datafields/f19/metadata.json +5 -0
- package/test-fixtures/remove-inferior-datafields/f19/record.json +18 -0
- package/test-fixtures/remove-inferior-datafields/f20/expectedResult.json +15 -0
- package/test-fixtures/remove-inferior-datafields/f20/metadata.json +5 -0
- package/test-fixtures/remove-inferior-datafields/f20/record.json +29 -0
- package/test-fixtures/sort-fields/15/input.json +9 -0
- package/test-fixtures/sort-fields/15/metadata.json +5 -0
- package/test-fixtures/sort-fields/15/result.json +10 -0
- package/test-fixtures/sync-language/01/expectedResult.json +5 -0
- package/test-fixtures/sync-language/01/metadata.json +5 -0
- package/test-fixtures/sync-language/01/record.json +7 -0
- package/test-fixtures/sync-language/02/expectedResult.json +6 -0
- package/test-fixtures/sync-language/02/metadata.json +5 -0
- package/test-fixtures/sync-language/02/record.json +10 -0
- package/test-fixtures/sync-language/03/expectedResult.json +6 -0
- package/test-fixtures/sync-language/03/metadata.json +5 -0
- package/test-fixtures/sync-language/03/record.json +6 -0
- package/test-fixtures/sync-language/10/expectedResult.json +10 -0
- package/test-fixtures/sync-language/10/metadata.json +5 -0
- package/test-fixtures/sync-language/10/record.json +8 -0
- package/test-fixtures/sync-language/11/expectedResult.json +10 -0
- package/test-fixtures/sync-language/11/metadata.json +5 -0
- package/test-fixtures/sync-language/11/record.json +7 -0
- package/test-fixtures/sync-language/12/expectedResult.json +9 -0
- package/test-fixtures/sync-language/12/metadata.json +6 -0
- package/test-fixtures/sync-language/12/record.json +6 -0
- package/test-fixtures/sync-language/13/expectedResult.json +10 -0
- package/test-fixtures/sync-language/13/metadata.json +5 -0
- package/test-fixtures/sync-language/13/record.json +8 -0
- package/test-fixtures/sync-language/14/expectedResult.json +9 -0
- package/test-fixtures/sync-language/14/metadata.json +5 -0
- package/test-fixtures/sync-language/14/record.json +7 -0
- package/test-fixtures/sync-language/15/expectedResult.json +9 -0
- package/test-fixtures/sync-language/15/metadata.json +5 -0
- package/test-fixtures/sync-language/15/record.json +7 -0
- package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
- package/test-fixtures/translate-terms/05/metadata.json +7 -0
- package/test-fixtures/translate-terms/05/record.json +11 -0
- package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
- package/test-fixtures/translate-terms/06/metadata.json +7 -0
- package/test-fixtures/translate-terms/06/record.json +11 -0
- package/test-fixtures/translate-terms-data.js +23 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/reindexSubfield6OccurenceNumbers.js"],
|
|
4
|
-
"sourcesContent": ["import createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug} from './utils.js';\nimport {fieldGetOccurrenceNumberPairs, fieldGetUnambiguousOccurrenceNumber, fieldResetOccurrenceNumber, intToOccurrenceNumberString, isValidSubfield6,\n recordGetMaxSubfield6OccurrenceNumberAsInteger,\n subfield6GetOccurrenceNumber, subfield6GetOccurrenceNumberAsInteger, subfield6ResetOccurrenceNumber} from './subfield6Utils.js';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:reindexSubfield6OccurrenceNumbers');\n\n\n// NB! This validator/fixer has two functionalities:\n// 1) normal reindexing of occurrence numbers\n// 2) disambiguation (when possible) of unambiguous occurrence numbers\n\nexport default function () {\n return {\n description: 'Reindex occurrence numbers in $6 subfield so that they start from 01 and end in NN',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Fix SF6 occurrence numbers',
|
|
5
|
-
"mappings": "AAAA,OAAO,uBAAuB;AAC9B,SAAQ,kBAAkB,eAAe,eAAc;AACvD;AAAA,EAAQ;AAAA,EAA+B;AAAA,EAAqC;AAAA,EAA4B;AAAA,EAA6B;AAAA,EACnI;AAAA,EACA;AAAA,EAA8B;AAAA,EAAuC;AAAA,OAAqC;AAI5G,MAAM,QAAQ,kBAAkB,4EAA4E;
|
|
4
|
+
"sourcesContent": ["import createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug} from './utils.js';\nimport {fieldGetOccurrenceNumberPairs, fieldGetUnambiguousOccurrenceNumber, fieldResetOccurrenceNumber, intToOccurrenceNumberString, isValidSubfield6,\n recordGetMaxSubfield6OccurrenceNumberAsInteger,\n subfield6GetOccurrenceNumber, subfield6GetOccurrenceNumberAsInteger, subfield6ResetOccurrenceNumber} from './subfield6Utils.js';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:reindexSubfield6OccurrenceNumbers');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n\n// NB! This validator/fixer has two functionalities:\n// 1) normal reindexing of occurrence numbers\n// 2) disambiguation (when possible) of unambiguous occurrence numbers\n\nexport default function () {\n return {\n description: 'Reindex occurrence numbers in $6 subfield so that they start from 01 and end in NN',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Fix SF6 occurrence numbers', debugDev);\n const res = {message: [], fix: [], valid: true};\n //message.fix = [];\n\n // This can not really fail...\n\n recordDisambiguateSharedSubfield6OccurrenceNumbers(record);\n recordResetSubfield6OccurrenceNumbers(record);\n\n // message.valid = !(message.message.length >= 1);\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n\n nvdebug('Validate SF6 occurrence number multiuses', debugDev);\n if (recordGetSharedOccurrenceNumbers(record).length) {\n res.message.push(`Multi-use of occurrence number(s) detected`);\n }\n\n // Check max, and check number of different indexes\n nvdebug('Validate SF6 occurrence number (max vs n instances)', debugDev);\n const max = recordGetMaxSubfield6OccurrenceNumberAsInteger(record);\n const size = recordGetNumberOfUniqueSubfield6OccurrenceNumbers(record);\n\n\n if (max !== size) {\n res.message.push(`Gaps detected in occurrence numbers: found ${size}, seen max ${max}`);\n }\n res.valid = res.message.length < 1;\n return res;\n }\n}\n\nfunction getPotentialSharedOccurrenceNumberFields(occurrenceNumber, fields) {\n return fields.filter(f => f.tag !== '880' && f.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber));\n}\n\nfunction subfieldHasSharedOccurrenceNumber(subfield, candFields) {\n const occurrenceNumber = subfield6GetOccurrenceNumber(subfield);\n if (!occurrenceNumber || occurrenceNumber === '00') {\n return false;\n }\n const relevantFields = getPotentialSharedOccurrenceNumberFields(occurrenceNumber, candFields);\n // record.fields.filter(f => f.tag !== '880' && fieldHasOccurrenceNumber(f, occurrenceNumber));\n return relevantFields.length > 1;\n}\n\nfunction fieldHasSharedOccurrenceNumber(field, candFields) {\n if (!field.subfields || field.tag === '880') { // Should not happen\n return false;\n }\n\n // What if there are multiple $6s in a given field? Should not be, but...\n return field.subfields.some(subfield => subfieldHasSharedOccurrenceNumber(subfield, candFields));\n\n}\n\nfunction recordGetSharedOccurrenceNumbers(record) {\n const fieldsContainingSubfield6 = record.fields.filter(field => field.tag !== '880' && fieldHasSubfield(field, '6'));\n // fieldsContainingSubfield6.some(field => fieldHasSharedOccurrenceNumber(field, fieldsContainingSubfield6)))\n return fieldsContainingSubfield6.filter(field => fieldHasSharedOccurrenceNumber(field, fieldsContainingSubfield6));\n}\n\nfunction recordDisambiguateSharedSubfield6OccurrenceNumbers(record) {\n const sharedOccurrenceNumberFields = recordGetSharedOccurrenceNumbers(record);\n if (sharedOccurrenceNumberFields.length < 2) {\n return;\n }\n nvdebug(`Disambiguate occurrence numbers (N=${sharedOccurrenceNumberFields.length}) in...`, debugDev);\n sharedOccurrenceNumberFields.forEach(field => disambiguateOccurrenceNumber(field));\n\n function disambiguateable(field) {\n if (field.tag === '880') { // Not needed, already filtered...\n return false;\n }\n const occurrenceNumber = fieldGetUnambiguousOccurrenceNumber(field);\n nvdebug(` Trying to disambiguate ${occurrenceNumber} in '${fieldToString(field)}`, debugDev);\n if (occurrenceNumber === undefined) {\n return false;\n }\n const allRelevantFields = getPotentialSharedOccurrenceNumberFields(occurrenceNumber, sharedOccurrenceNumberFields);\n if (allRelevantFields.length < 2) {\n nvdebug(` Currently only ${allRelevantFields.length} field(s) use occurrence number ${occurrenceNumber}. No action required.`, debugDev);\n return false;\n }\n nvdebug(` Currently ${allRelevantFields.length} field(s) use occurrence number ${occurrenceNumber}. ACTION REQUIRED!`, debugDev);\n const relevantFieldsWithCurrFieldTag = allRelevantFields.filter(candField => field.tag === candField.tag);\n\n if (relevantFieldsWithCurrFieldTag.length !== 1) {\n nvdebug(` Number of them using tag ${field.tag} is ${relevantFieldsWithCurrFieldTag.length}. Can not disambiguate!`, debugDev);\n return false;\n }\n\n return true;\n }\n\n function disambiguateOccurrenceNumber(field) {\n if (!disambiguateable(field)) {\n return;\n }\n // Reset field:\n const occurrenceNumber = fieldGetUnambiguousOccurrenceNumber(field);\n const newOccurrenceNumberAsInt = recordGetMaxSubfield6OccurrenceNumberAsInteger(record) + 1;\n const newOccurrenceNumber = intToOccurrenceNumberString(newOccurrenceNumberAsInt);\n const pairedFields = fieldGetOccurrenceNumberPairs(field, record.fields);\n\n nvdebug(` Reindex '${fieldToString(field)}' occurrence number and it's ${pairedFields.length} pair(s) using '${newOccurrenceNumber}'`, debugDev);\n\n fieldResetOccurrenceNumber(field, newOccurrenceNumber, occurrenceNumber);\n pairedFields.forEach(pairedField => fieldResetOccurrenceNumber(pairedField, newOccurrenceNumber, occurrenceNumber));\n\n }\n\n\n}\nfunction recordGetNumberOfUniqueSubfield6OccurrenceNumbers(record) {\n // Calculates the number of used different occurrence numbers\n let indexArray = [];\n record.fields.forEach(field => gatherFieldData(field));\n\n function gatherFieldData(field) {\n if (!field.subfields) {\n return;\n }\n field.subfields.forEach(subfield => gatherSubfieldData(subfield));\n }\n\n function gatherSubfieldData(subfield) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const i = subfield6GetOccurrenceNumberAsInteger(subfield);\n if (i === 0) {\n return\n }\n indexArray[i] = 1;\n }\n let n = 0;\n indexArray.forEach(elem => n+= elem);\n return n;\n}\n\nexport function recordResetSubfield6OccurrenceNumbers(record) { // Remove gaps\n /* eslint-disable */\n let currentInt = 1;\n let oldtoNewCache = {};\n\n record.fields.forEach(field => fieldResetSubfield6(field));\n\n function fieldResetSubfield6(field) {\n nvdebug(`fieldResetSubfield6(${fieldToString(field)}), CURR:${currentInt}`, debugDev);\n if (!field.subfields) {\n return;\n }\n field.subfields.forEach(subfield => subfieldReset6(subfield));\n }\n\n function subfieldReset6(subfield) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const currIndex = subfield6GetOccurrenceNumber(subfield);\n if (currIndex === undefined || currIndex === '00') {\n return;\n }\n\n const newIndex = mapCurrIndexToNewIndex(currIndex);\n //nvdebug(`subfieldReset6(${subfieldToString(subfield)}): ${newIndex}`, debugDev);\n subfield6ResetOccurrenceNumber(subfield, newIndex);\n }\n\n function mapCurrIndexToNewIndex(currIndex) {\n if(currIndex in oldtoNewCache) {\n return oldtoNewCache[currIndex];\n }\n const newIndex = intToOccurrenceNumberString(currentInt);\n oldtoNewCache[currIndex] = newIndex;\n currentInt++;\n return newIndex;\n }\n\n /* eslint-enable */\n\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
|
|
|
3
3
|
import validatorFactory from "./reindexSubfield6OccurenceNumbers.js";
|
|
4
4
|
import { READERS } from "@natlibfi/fixura";
|
|
5
5
|
import generateTests from "@natlibfi/fixugen";
|
|
6
|
-
import createDebugLogger from "debug";
|
|
7
6
|
generateTests({
|
|
8
7
|
callback,
|
|
9
8
|
path: [import.meta.dirname, "..", "test-fixtures", "reindex-sf6-occurence-numbers"],
|
|
@@ -18,18 +17,13 @@ generateTests({
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/reindexSubfield6OccurrenceNumbers:test");
|
|
22
20
|
async function testValidatorFactory() {
|
|
23
21
|
const validator = await validatorFactory();
|
|
24
22
|
assert.equal(typeof validator, "object");
|
|
25
23
|
assert.equal(typeof validator.description, "string");
|
|
26
24
|
assert.equal(typeof validator.validate, "function");
|
|
27
25
|
}
|
|
28
|
-
async function callback({ getFixture,
|
|
29
|
-
if (enabled === false) {
|
|
30
|
-
debug("TEST SKIPPED!");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
33
27
|
const validator = await validatorFactory();
|
|
34
28
|
const record = new MarcRecord(getFixture("record.json"));
|
|
35
29
|
const expectedResult = getFixture("expectedResult.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/reindexSubfield6OccurenceNumbers.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './reindexSubfield6OccurenceNumbers.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './reindexSubfield6OccurenceNumbers.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'reindex-sf6-occurence-numbers'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/reindexSubfield6OccurrenceNumbers:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,+BAA+B;AAAA,EAClF,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAGD,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import clone from "clone";
|
|
2
|
+
import { fieldToString } from "./utils.js";
|
|
3
|
+
export default function() {
|
|
4
|
+
return {
|
|
5
|
+
description: "Remove 'zxx' from f041",
|
|
6
|
+
validate,
|
|
7
|
+
fix
|
|
8
|
+
};
|
|
9
|
+
function zxxRemoval041(record, validateMode) {
|
|
10
|
+
const fields041 = record.fields.filter((f) => f.tag === "041");
|
|
11
|
+
return handleZxx(fields041);
|
|
12
|
+
function handleZxx(fields, result = []) {
|
|
13
|
+
const [currField, ...remainingFields] = fields;
|
|
14
|
+
if (!currField) {
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
if (!currField.subfields || currField.subfields.some((sf) => sf.code === "2")) {
|
|
18
|
+
return handleZxx(remainingFields, result);
|
|
19
|
+
}
|
|
20
|
+
const otherSubfields = currField.subfields.filter((sf) => !sf.code.match(/^[a-z]$/u) || sf.value !== "zxx");
|
|
21
|
+
if (otherSubfields.length === currField.subfields.length) {
|
|
22
|
+
return handleZxx(remainingFields, result);
|
|
23
|
+
}
|
|
24
|
+
const originalString = fieldToString(currField);
|
|
25
|
+
if (otherSubfields.length === 0) {
|
|
26
|
+
const message2 = `Remove '${originalString}'`;
|
|
27
|
+
if (!validateMode) {
|
|
28
|
+
record.removeField(currField);
|
|
29
|
+
}
|
|
30
|
+
return handleZxx(remainingFields, [...result, message2]);
|
|
31
|
+
}
|
|
32
|
+
if (validateMode) {
|
|
33
|
+
const clonedField = clone(currField);
|
|
34
|
+
clonedField.subfields = otherSubfields;
|
|
35
|
+
const modifiedString2 = fieldToString(clonedField);
|
|
36
|
+
const message2 = `Modify '${originalString}' => '${modifiedString2}`;
|
|
37
|
+
return handleZxx(remainingFields, [...result, message2]);
|
|
38
|
+
}
|
|
39
|
+
currField.subfields = otherSubfields;
|
|
40
|
+
const modifiedString = fieldToString(currField);
|
|
41
|
+
const message = `Modify '${originalString}' => '${modifiedString}`;
|
|
42
|
+
return handleZxx(remainingFields, [...result, message]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function fix(record, validateMode = false) {
|
|
46
|
+
const messages = zxxRemoval041(record, validateMode);
|
|
47
|
+
if (validateMode) {
|
|
48
|
+
return { message: messages, valid: messages.length === 0 };
|
|
49
|
+
}
|
|
50
|
+
return { message: [], fix: messages, valid: true };
|
|
51
|
+
}
|
|
52
|
+
function validate(record) {
|
|
53
|
+
return fix(record, true);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=remove-041-zxx.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/remove-041-zxx.js"],
|
|
4
|
+
"sourcesContent": ["/*\n// remove-041-zxx.js\n//\n// https://wiki.helsinki.fi/xwiki/bin/view/rdasovellusohje/RDA-kuvailu%20MARC%2021%20-formaatilla/RDA-sovellusohje/008%20Kontrollikentt%C3%A4/#Hmp.35-37Kieli\n// \"008-kielikoodi on sama kuin ensimm\u00E4inen 041-kent\u00E4n a- (tai d-) osakentt\u00E4. Poikkeuksen muodostaa koodi zxx:\n// jos tietueen 008ssa on kielikoodi zxx (ei kielellist\u00E4 sis\u00E4lt\u00F6\u00E4, esim. soitinmusiikki), tietueessa ei voi olla 041 a- eik\u00E4 d-osakentt\u00E4\u00E4.\"\n// Effectively this means, that 'zxx' does not appear in 041!\n// Author(s): Nicholas Volk\n*/\n\n//import createDebugLogger from 'debug';\nimport clone from 'clone';\n\nimport {fieldToString} from './utils.js';\n\n// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:remove-041-zxx');\n\n\n\n\nexport default function () {\n\n return {\n description: \"Remove 'zxx' from f041\",\n validate, fix\n };\n\n function zxxRemoval041(record, validateMode) {\n const fields041 = record.fields.filter(f => f.tag === '041');\n\n return handleZxx(fields041);\n\n function handleZxx(fields, result = []) {\n const [currField, ...remainingFields] = fields;\n if ( !currField) {\n return result;\n }\n // Theoretically 'zxx' might mean something in ISO-639-3 or some other language code list:\n if (!currField.subfields || currField.subfields.some(sf => sf.code === '2')) {\n return handleZxx(remainingFields, result);\n }\n // Presumable 'zxx' is bad in any data subfield, not just 'a' and 'd':\n const otherSubfields = currField.subfields.filter(sf => (!sf.code.match(/^[a-z]$/u) || sf.value !== 'zxx'));\n if (otherSubfields.length === currField.subfields.length) {\n return handleZxx(remainingFields, result);\n }\n const originalString = fieldToString(currField);\n if (otherSubfields.length === 0) {\n const message = `Remove '${originalString}'`;\n if (!validateMode) {\n record.removeField(currField);\n }\n return handleZxx(remainingFields, [...result, message]);\n }\n // Some subfields are removed:\n if (validateMode) {\n // NB! In validation field is not really deleted, and the non-deleted field might trigger other fixes (than won't be done to a deleted field) later on\n const clonedField = clone(currField);\n clonedField.subfields = otherSubfields;\n const modifiedString = fieldToString(clonedField);\n const message = `Modify '${originalString}' => '${modifiedString}`;\n return handleZxx(remainingFields, [...result, message]);\n }\n currField.subfields = otherSubfields;\n const modifiedString = fieldToString(currField);\n const message = `Modify '${originalString}' => '${modifiedString}`;\n return handleZxx(remainingFields, [...result, message]);\n }\n }\n\n function fix(record, validateMode = false) {\n const messages = zxxRemoval041(record, validateMode);\n\n if (validateMode) {\n return {message: messages, valid: messages.length === 0};\n }\n return {message: [], fix: messages, valid: true};\n }\n\n\n function validate(record) {\n return fix(record, true);\n }\n}\n\n"],
|
|
5
|
+
"mappings": "AAWA,OAAO,WAAW;AAElB,SAAQ,qBAAoB;AAO5B,0BAA2B;AAEzB,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IAAU;AAAA,EACZ;AAEA,WAAS,cAAc,QAAQ,cAAc;AAC3C,UAAM,YAAY,OAAO,OAAO,OAAO,OAAK,EAAE,QAAQ,KAAK;AAE3D,WAAO,UAAU,SAAS;AAE1B,aAAS,UAAU,QAAQ,SAAS,CAAC,GAAG;AACtC,YAAM,CAAC,WAAW,GAAG,eAAe,IAAI;AACxC,UAAK,CAAC,WAAW;AACf,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,UAAU,aAAa,UAAU,UAAU,KAAK,QAAM,GAAG,SAAS,GAAG,GAAG;AAC3E,eAAO,UAAU,iBAAiB,MAAM;AAAA,MAC1C;AAEA,YAAM,iBAAiB,UAAU,UAAU,OAAO,QAAO,CAAC,GAAG,KAAK,MAAM,UAAU,KAAK,GAAG,UAAU,KAAM;AAC1G,UAAI,eAAe,WAAW,UAAU,UAAU,QAAQ;AACxD,eAAO,UAAU,iBAAiB,MAAM;AAAA,MAC1C;AACA,YAAM,iBAAiB,cAAc,SAAS;AAC9C,UAAI,eAAe,WAAW,GAAG;AAC/B,cAAMA,WAAU,WAAW,cAAc;AACzC,YAAI,CAAC,cAAc;AACjB,iBAAO,YAAY,SAAS;AAAA,QAC9B;AACA,eAAO,UAAU,iBAAiB,CAAC,GAAG,QAAQA,QAAO,CAAC;AAAA,MACxD;AAEA,UAAI,cAAc;AAEhB,cAAM,cAAc,MAAM,SAAS;AACnC,oBAAY,YAAY;AACxB,cAAMC,kBAAiB,cAAc,WAAW;AAChD,cAAMD,WAAU,WAAW,cAAc,SAASC,eAAc;AAChE,eAAO,UAAU,iBAAiB,CAAC,GAAG,QAAQD,QAAO,CAAC;AAAA,MACxD;AACA,gBAAU,YAAY;AACtB,YAAM,iBAAiB,cAAc,SAAS;AAC9C,YAAM,UAAU,WAAW,cAAc,SAAS,cAAc;AAChE,aAAO,UAAU,iBAAiB,CAAC,GAAG,QAAQ,OAAO,CAAC;AAAA,IACxD;AAAA,EACF;AAEA,WAAS,IAAI,QAAQ,eAAe,OAAO;AACzC,UAAM,WAAW,cAAc,QAAQ,YAAY;AAEnD,QAAI,cAAc;AACf,aAAO,EAAC,SAAS,UAAU,OAAO,SAAS,WAAW,EAAC;AAAA,IAC1D;AACA,WAAO,EAAC,SAAS,CAAC,GAAG,KAAK,UAAU,OAAO,KAAI;AAAA,EACjD;AAGA,WAAS,SAAS,QAAQ;AACxB,WAAO,IAAI,QAAQ,IAAI;AAAA,EACzB;AACF;",
|
|
6
|
+
"names": ["message", "modifiedString"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import validatorFactory from "./remove-041-zxx.js";
|
|
3
|
+
import { MarcRecord } from "@natlibfi/marc-record";
|
|
4
|
+
import { READERS } from "@natlibfi/fixura";
|
|
5
|
+
import generateTests from "@natlibfi/fixugen";
|
|
6
|
+
generateTests({
|
|
7
|
+
callback,
|
|
8
|
+
path: [import.meta.dirname, "..", "test-fixtures", "remove-041-zxx"],
|
|
9
|
+
useMetadataFile: true,
|
|
10
|
+
recurse: false,
|
|
11
|
+
fixura: {
|
|
12
|
+
reader: READERS.JSON
|
|
13
|
+
},
|
|
14
|
+
hooks: {
|
|
15
|
+
before: async () => {
|
|
16
|
+
testValidatorFactory();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
async function testValidatorFactory() {
|
|
21
|
+
const validator = await validatorFactory();
|
|
22
|
+
assert.equal(typeof validator, "object");
|
|
23
|
+
assert.equal(typeof validator.description, "string");
|
|
24
|
+
assert.equal(typeof validator.validate, "function");
|
|
25
|
+
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
27
|
+
const validator = await validatorFactory();
|
|
28
|
+
const record = new MarcRecord(getFixture("record.json"));
|
|
29
|
+
const expectedResult = getFixture("expectedResult.json");
|
|
30
|
+
if (!fix) {
|
|
31
|
+
const result = await validator.validate(record);
|
|
32
|
+
assert.deepEqual(result, expectedResult);
|
|
33
|
+
const originalRecord = new MarcRecord(getFixture("record.json"));
|
|
34
|
+
assert.deepEqual(record, originalRecord);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
await validator.fix(record);
|
|
38
|
+
assert.deepEqual(record, new MarcRecord(expectedResult));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=remove-041-zxx.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/remove-041-zxx.test.js"],
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert/strict';\n//import createDebugLogger from 'debug';\n\nimport validatorFactory from './remove-041-zxx.js';\n\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'remove-041-zxx'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/drop-terms:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n //const expectedResult = new MarcRecord(getFixture('expectedResult.json'));\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n const originalRecord = new MarcRecord(getFixture('record.json'));\n assert.deepEqual(record, originalRecord); // Validation should not change the record\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, new MarcRecord(expectedResult));\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AAGnB,OAAO,sBAAsB;AAE7B,SAAQ,kBAAiB;AACzB,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAE1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,gBAAgB;AAAA,EACnE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAIvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC,UAAM,iBAAiB,IAAI,WAAW,WAAW,aAAa,CAAC;AAC/D,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,IAAI,WAAW,cAAc,CAAC;AACzD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import createDebugLogger from "debug";
|
|
2
|
-
import {
|
|
2
|
+
import { fieldToString, nvdebug } from "./utils.js";
|
|
3
3
|
import { fieldHasValidSubfield6, fieldsGetOccurrenceNumbers, fieldsToNormalizedString, fieldToNormalizedString, get6s } from "./subfield6Utils.js";
|
|
4
4
|
import { add8s, fieldHasLinkingNumber, fieldHasValidSubfield8, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber } from "./subfield8Utils.js";
|
|
5
5
|
const LINK_ROOT = 4;
|
|
6
6
|
const LINKED_AND_PROCESSED = 2;
|
|
7
7
|
const LINKED_NOT_PROCESSED = 1;
|
|
8
8
|
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda:removeDuplicateDataFields");
|
|
9
|
+
const debugDev = debug.extend("dev");
|
|
9
10
|
export default function() {
|
|
10
11
|
return {
|
|
11
12
|
description: "Remove duplicate data fields. Certain exceptions apply, mainly too complited chained fields",
|
|
@@ -13,13 +14,13 @@ export default function() {
|
|
|
13
14
|
fix
|
|
14
15
|
};
|
|
15
16
|
function fix(record) {
|
|
16
|
-
nvdebug("Remove duplicate data fields");
|
|
17
|
+
nvdebug("Remove duplicate data fields", debugDev);
|
|
17
18
|
const res = { message: [], fix: [], valid: true };
|
|
18
19
|
removeDuplicateDatafields(record, true);
|
|
19
20
|
return res;
|
|
20
21
|
}
|
|
21
22
|
function validate(record) {
|
|
22
|
-
nvdebug("Validate record: duplicate data fields cause (t)error",
|
|
23
|
+
nvdebug("Validate record: duplicate data fields cause (t)error", debugDev);
|
|
23
24
|
const duplicates = removeDuplicateDatafields(record, false);
|
|
24
25
|
const res = { message: duplicates };
|
|
25
26
|
res.valid = res.message.length < 1;
|
|
@@ -82,31 +83,24 @@ function newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix)
|
|
|
82
83
|
export function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
83
84
|
let seen = {};
|
|
84
85
|
let removables = [];
|
|
85
|
-
nvdebug("CHAIN-8");
|
|
86
86
|
const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);
|
|
87
87
|
if (seenLinkingNumbers.length === 0) {
|
|
88
88
|
return removables;
|
|
89
89
|
}
|
|
90
|
-
nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(", ")}`, debug);
|
|
91
90
|
seenLinkingNumbers.forEach((currLinkingNumber) => {
|
|
92
91
|
const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber);
|
|
93
92
|
const normalizeOccurrenceNumber = true;
|
|
94
93
|
const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);
|
|
95
|
-
nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
96
|
-
nvdebug(`${linkedFieldsAsString}`, debug);
|
|
97
94
|
if (linkedFieldsAsString in seen) {
|
|
98
95
|
if (!removables.includes(linkedFieldsAsString)) {
|
|
99
96
|
removables.push(linkedFieldsAsString);
|
|
100
97
|
}
|
|
101
98
|
if (fix) {
|
|
102
|
-
nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
103
99
|
linkedFields.forEach((field) => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));
|
|
104
100
|
return;
|
|
105
101
|
}
|
|
106
|
-
nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);
|
|
107
102
|
return;
|
|
108
103
|
}
|
|
109
|
-
nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
110
104
|
seen[linkedFieldsAsString] = 1;
|
|
111
105
|
return;
|
|
112
106
|
});
|
|
@@ -114,24 +108,18 @@ export function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
|
114
108
|
}
|
|
115
109
|
export function handleDuplicateSubfield8Chains(record, fix) {
|
|
116
110
|
let seen = {};
|
|
117
|
-
nvdebug("CHAIN-8");
|
|
118
111
|
const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);
|
|
119
112
|
if (seenLinkingNumbers.length === 0) {
|
|
120
113
|
return;
|
|
121
114
|
}
|
|
122
|
-
nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(", ")}`, debug);
|
|
123
115
|
seenLinkingNumbers.forEach((currLinkingNumber) => {
|
|
124
116
|
const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber);
|
|
125
117
|
const normalizeOccurrenceNumber = false;
|
|
126
118
|
const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);
|
|
127
|
-
nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
128
|
-
nvdebug(`${linkedFieldsAsString}`, debug);
|
|
129
119
|
if (linkedFieldsAsString in seen) {
|
|
130
|
-
nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
131
120
|
linkedFields.forEach((field) => newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix));
|
|
132
121
|
return;
|
|
133
122
|
}
|
|
134
|
-
nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
135
123
|
seen[linkedFieldsAsString] = 1;
|
|
136
124
|
return;
|
|
137
125
|
});
|
|
@@ -140,10 +128,8 @@ function markIdenticalSubfield6Chains(chain, record) {
|
|
|
140
128
|
const normalizeOccurrenceNumber = true;
|
|
141
129
|
const normalizeTag = chain.some((field) => field.tag.substring(0, 1) === "1");
|
|
142
130
|
const chainAsString = fieldsToNormalizedString(chain, 0, normalizeOccurrenceNumber, normalizeTag);
|
|
143
|
-
nvdebug(`markIdenticalSubfield6Chains: ${chainAsString}`);
|
|
144
131
|
record.fields.forEach((f) => compareWithChain(f));
|
|
145
132
|
function compareWithChain(f) {
|
|
146
|
-
nvdebug(`FIELD2CHAIN ${fieldToString(f)}`);
|
|
147
133
|
const otherChain = fieldToChain(f, record);
|
|
148
134
|
if (otherChain.length === 0 || sameField(chain[0], otherChain[0])) {
|
|
149
135
|
return;
|
|
@@ -151,7 +137,6 @@ function markIdenticalSubfield6Chains(chain, record) {
|
|
|
151
137
|
const otherChainAsString = fieldsToNormalizedString(otherChain, 0, normalizeOccurrenceNumber, normalizeTag);
|
|
152
138
|
if (chainAsString === otherChainAsString) {
|
|
153
139
|
otherChain.forEach((f2) => {
|
|
154
|
-
nvdebug(` mark ${fieldToString(f2)} as deleted ($6-chain)...`);
|
|
155
140
|
f2.deleted = 1;
|
|
156
141
|
});
|
|
157
142
|
return;
|
|
@@ -166,7 +151,6 @@ function markIdenticalLoneFieldsAsDeletable(field, record) {
|
|
|
166
151
|
const fieldAsString = fieldToNormalizedString(field, 0, false, normalizeTag);
|
|
167
152
|
const identicalLoneFields = record.fields.filter((f) => !sameField(f, field) && fieldToNormalizedString(f, 0, false, normalizeTag) === fieldAsString);
|
|
168
153
|
identicalLoneFields.forEach((f) => {
|
|
169
|
-
nvdebug(` mark ${fieldToString(f)} as deleted (lone field)...`);
|
|
170
154
|
f.deleted = 1;
|
|
171
155
|
});
|
|
172
156
|
}
|
|
@@ -195,7 +179,6 @@ function acceptFieldsWithSubfield8(fieldsWithSubfield8, requireSingleTag = false
|
|
|
195
179
|
}
|
|
196
180
|
return true;
|
|
197
181
|
function anomaly8(linkingNumber) {
|
|
198
|
-
nvdebug(` Looking for anomalies in linkin number ${linkingNumber}`);
|
|
199
182
|
const relevantFields = fieldsWithSubfield8.filter((f) => fieldHasLinkingNumber(f, linkingNumber));
|
|
200
183
|
if (requireSingleTag) {
|
|
201
184
|
return !isSingleTagLinkingNumber(linkingNumber, relevantFields, relevantFields[0].tag);
|
|
@@ -221,7 +204,6 @@ export function fieldToChain(field, record) {
|
|
|
221
204
|
return [];
|
|
222
205
|
}
|
|
223
206
|
const chain = newGetAllLinkedFields(field, record, true, true);
|
|
224
|
-
nvdebug(` Chain contains ${chain.length} field(s)`);
|
|
225
207
|
if (!isChainHead(field, chain)) {
|
|
226
208
|
return [];
|
|
227
209
|
}
|
|
@@ -246,7 +228,6 @@ export function fieldToChain(field, record) {
|
|
|
246
228
|
}
|
|
247
229
|
function fieldHandleDuplicateDatafields(field, record) {
|
|
248
230
|
const chain = fieldToChain(field, record);
|
|
249
|
-
nvdebug(` TRY TO HANDLE DUPLICATES OF '${fieldsToString(chain)}'`);
|
|
250
231
|
if (chain.length === 0) {
|
|
251
232
|
return;
|
|
252
233
|
}
|
|
@@ -258,7 +239,6 @@ function fieldHandleDuplicateDatafields(field, record) {
|
|
|
258
239
|
}
|
|
259
240
|
if (fieldsWithSubfield6.length === 0) {
|
|
260
241
|
if (fieldsWithSubfield8.length === 0) {
|
|
261
|
-
nvdebug(` Trying to find duplicates of single field '${fieldToString(chain[0])}'`);
|
|
262
242
|
markIdenticalLoneFieldsAsDeletable(chain[0], record);
|
|
263
243
|
return;
|
|
264
244
|
}
|
|
@@ -272,8 +252,6 @@ function fieldHandleDuplicateDatafields(field, record) {
|
|
|
272
252
|
markIdenticalSubfield6Chains(chain, record);
|
|
273
253
|
return;
|
|
274
254
|
}
|
|
275
|
-
nvdebug(` NO HANDLER FOUND FOR '${fieldsToString(chain)}'`);
|
|
276
|
-
nvdebug(` N8s: ${fieldsWithSubfield6.length}`);
|
|
277
255
|
}
|
|
278
256
|
export function removeDuplicateDatafields(record, fix = true) {
|
|
279
257
|
handleDuplicateSubfield8Chains(record, fix);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/removeDuplicateDataFields.js"],
|
|
4
|
-
"sourcesContent": ["import createDebugLogger from 'debug';\nimport {fieldsToString, fieldToString, nvdebug} from './utils.js';\nimport {fieldHasValidSubfield6, fieldsGetOccurrenceNumbers, fieldsToNormalizedString, fieldToNormalizedString, get6s} from './subfield6Utils.js';\nimport {add8s, fieldHasLinkingNumber, fieldHasValidSubfield8, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils.js';\n\nconst LINK_ROOT = 4;\nconst LINKED_AND_PROCESSED = 2;\nconst LINKED_NOT_PROCESSED = 1;\n\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeDuplicateDataFields');\n\nexport default function () {\n return {\n description: 'Remove duplicate data fields. Certain exceptions apply, mainly too complited chained fields',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Remove duplicate data fields');\n const res = {message: [], fix: [], valid: true};\n removeDuplicateDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n nvdebug('Validate record: duplicate data fields cause (t)error', debug);\n\n const duplicates = removeDuplicateDatafields(record, false);\n\n //const orphanedFields = getOrphanedFields(fieldsContainingSubfield6);\n\n const res = {message: duplicates};\n\n /*\n if (orphanedFields.length > 0) {\n res.message = [`${orphanedFields.length} orphaned occurrence number field(s) detected`];\n }\n */\n res.valid = res.message.length < 1;\n return res;\n }\n}\n\n\n/*\nfunction numberOfLinkageSubfields(field) {\n nvdebug(`N of Linkage Subs(${fieldToString(field)})`);\n const subfields = field.subfields.filter(sf => sf.code === '6' || sf.code === '8');\n return subfields.length;\n}\n*/\n\nfunction removeLinkNotes(record) {\n record.fields.forEach(f => delete f.linkNote);\n}\n\n\nfunction newGetAllLinkedFields(field, record, useSixes = true, useEights = true) {\n removeLinkNotes(record); // should be clear, but let's play safe\n\n field.linkNote = LINK_ROOT;\n\n let currField = field;\n\n // Loop until all linked fields have been processed:\n while (currField !== undefined) {\n if (useSixes) {\n const related6s = get6s(currField, record.fields)\n related6s.forEach(f => linkField(f));\n }\n if (useEights) {\n const related8s = add8s([currField], record);\n related8s.forEach(f => linkField(f));\n }\n if (currField.linkNote !== LINK_ROOT) {\n currField.linkNote = LINKED_AND_PROCESSED;\n }\n currField = record.fields.find(f => f.linkNote === LINKED_NOT_PROCESSED);\n }\n\n // Collect relevant fields:\n const linkedFields = record.fields.filter(f => f.linkNote);\n\n removeLinkNotes(record);\n\n return linkedFields;\n\n function linkField(f) {\n if (!f.linkNote) {\n f.linkNote = LINKED_NOT_PROCESSED;\n }\n }\n\n}\n\n\nfunction recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n record.removeField(field);\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => record.removeSubfield(sf, field));\n}\n\nfunction newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n field.deleted = 1;\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => {\n field.modified = 1;\n if (fix) {\n record.removeSubfield(sf, field);\n }\n });\n}\n\n\nexport function removeDuplicateSubfield8Chains(record, fix = true) {\n\n // Seen $8 subsfields in various fields:\n // 161 700\n // 17 710\n // 11 110\n // 8 730\n // 1 100\n // Given these stats, there's no need to check for 1XX-vs-7XX removals\n\n let seen = {};\n\n let removables = []; // for validation\n\n nvdebug(\"CHAIN-8\");\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return removables;\n }\n\n nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n // As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true\n const normalizeOccurrenceNumber = true;\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);\n nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);\n nvdebug(`${linkedFieldsAsString}`, debug);\n\n if (linkedFieldsAsString in seen) {\n if (!removables.includes(linkedFieldsAsString)) {\n removables.push(linkedFieldsAsString);\n }\n\n if (fix) {\n nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);\n linkedFields.forEach(field => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));\n return;\n }\n\n nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);\n return;\n }\n nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n return removables;\n}\n\n\nexport function handleDuplicateSubfield8Chains(record, fix) {\n\n // Seen $8 subsfields in various fields:\n // 161 700\n // 17 710\n // 11 110\n // 8 730\n // 1 100\n // Given these stats, there's no need to check for 1XX-vs-7XX removals\n\n let seen = {};\n\n nvdebug(\"CHAIN-8\");\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return;\n }\n\n nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n // As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true\n const normalizeOccurrenceNumber = false; //true;\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);\n nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);\n nvdebug(`${linkedFieldsAsString}`, debug);\n\n if (linkedFieldsAsString in seen) {\n nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);\n linkedFields.forEach(field => newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix));\n return;\n }\n nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n}\n\nfunction markIdenticalSubfield6Chains(chain, record) {\n const normalizeOccurrenceNumber = true;\n const normalizeTag = chain.some(field => field.tag.substring(0, 1) === '1'); // 1XX can delete 7XX as well!\n const chainAsString = fieldsToNormalizedString(chain, 0, normalizeOccurrenceNumber, normalizeTag);\n\n nvdebug(`markIdenticalSubfield6Chains: ${chainAsString}`);\n record.fields.forEach(f => compareWithChain(f));\n\n\n function compareWithChain(f) {\n nvdebug(`FIELD2CHAIN ${fieldToString(f)}`);\n const otherChain = fieldToChain(f, record);\n // Not a lone field or chain (head) or ... or is-same-chain\n if (otherChain.length === 0 || sameField(chain[0], otherChain[0])) {\n return;\n }\n const otherChainAsString = fieldsToNormalizedString(otherChain, 0, normalizeOccurrenceNumber, normalizeTag);\n\n // Mark other chain as deleted:\n if (chainAsString === otherChainAsString) {\n otherChain.forEach(f => {\n nvdebug(` mark ${fieldToString(f)} as deleted ($6-chain)...`);\n f.deleted = 1;\n });\n return;\n }\n }\n\n}\n\nfunction markIdenticalLoneFieldsAsDeletable(field, record) {\n if (field.deleted) {\n return;\n }\n // targetLinkingNumber = 0, normalizedOccurenceNumber = false, normalizeTag = true)\n const normalizeTag = field.tag.substring(0, 1) === '1'; // 1XX can delete 7XX as well!\n const fieldAsString = fieldToNormalizedString(field, 0, false, normalizeTag);\n\n const identicalLoneFields = record.fields.filter(f => !sameField(f, field) && fieldToNormalizedString(f, 0, false, normalizeTag) === fieldAsString);\n\n // Mark fields as deleted:\n identicalLoneFields.forEach(f => {\n nvdebug(` mark ${fieldToString(f)} as deleted (lone field)...`);\n f.deleted = 1;\n });\n\n}\n\nfunction acceptFieldsWithSubfield6(fieldsWithSubfield6) {\n // There can be only one non-880 field:\n const non880 = fieldsWithSubfield6.filter(f => f.tag !== '880');\n if (non880.length > 1) {\n return false;\n }\n\n const occurrenceNumbers = fieldsGetOccurrenceNumbers(fieldsWithSubfield6);\n // Chain can contain only single occurrence number:\n if (occurrenceNumbers.length > 1) {\n return false;\n }\n\n return true;\n}\n\n\nfunction isSingleTagLinkingNumber(linkingNumber, fields, tag) {\n const relevantFields = fields.filter(f => fieldHasLinkingNumber(f, linkingNumber));\n if (relevantFields.some(f => f.tag !== tag)) {\n return false;\n }\n return true;\n}\n\nfunction acceptFieldsWithSubfield8(fieldsWithSubfield8, requireSingleTag = false) {\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fieldsWithSubfield8);\n if (linkingNumbers.some(linkingNumber => anomaly8(linkingNumber))) {\n return false;\n }\n return true;\n\n // If linking number\n function anomaly8(linkingNumber) {\n nvdebug(` Looking for anomalies in linkin number ${linkingNumber}`);\n const relevantFields = fieldsWithSubfield8.filter(f => fieldHasLinkingNumber(f, linkingNumber));\n if (requireSingleTag) {\n return !isSingleTagLinkingNumber(linkingNumber, relevantFields, relevantFields[0].tag);\n }\n\n const f880 = relevantFields.filter(f => f.tag === '880');\n if (f880.length === 0 || f880.length === relevantFields.length) {\n return false;\n }\n return true;\n }\n}\n\n\nexport function sameField(field1, field2) {\n field1.tmpMyId = 666;\n const result = field2.tmpMyId === 666 ? true : false;\n delete field1.tmpMyId;\n return result;\n}\n\nexport function isChainHead(field, chain) {\n return sameField(field, chain[0]);\n}\n\nexport function fieldToChain(field, record) {\n if (field.deleted || !field.subfields) {\n return [];\n }\n const chain = newGetAllLinkedFields(field, record, true, true);\n\n nvdebug(` Chain contains ${chain.length} field(s)`);\n if (!isChainHead(field, chain)) { // newGetAllLinkedFields() marks relevant record.fields!\n return [];\n }\n\n const fieldsWithSubfield6 = chain.filter(f => fieldHasValidSubfield6(f));\n // Hack: multiple $6 fields, but either all are non-880 or all are 880: treat field as a single entry\n if (fieldsWithSubfield6.length > 0) {\n const non880 = fieldsWithSubfield6.filter(f => f.tag !== '880');\n if (non880.length === 0 || non880.length === fieldsWithSubfield6.length) {\n return [field];\n }\n if (non880.length !== 1) {\n return [field];\n }\n }\n\n if (!acceptFieldsWithSubfield6(fieldsWithSubfield6)) { // Check tag subfield $6s are legal(ish)\n return [];\n }\n const fieldsWithSubfield8 = chain.filter(f => fieldHasValidSubfield8(f));\n if (!acceptFieldsWithSubfield8(fieldsWithSubfield8, false)) {\n return [];\n }\n\n //nvdebug(`Proceed with ${fieldsToString(chain)}`);\n\n\n return chain;\n}\n\n\nfunction fieldHandleDuplicateDatafields(field, record) {\n const chain = fieldToChain(field, record);\n nvdebug(` TRY TO HANDLE DUPLICATES OF '${fieldsToString(chain)}'`);\n\n if (chain.length === 0) {\n return;\n }\n\n const fieldsWithSubfield6 = chain.filter(f => fieldHasValidSubfield6(f));\n const fieldsWithSubfield8 = chain.filter(f => fieldHasValidSubfield8(f));\n\n // Lone fields:\n if (chain.length === 1) {\n markIdenticalLoneFieldsAsDeletable(chain[0], record);\n return;\n }\n if (fieldsWithSubfield6.length === 0) {\n\n if (fieldsWithSubfield8.length === 0) { // chain.length === 1?\n nvdebug(` Trying to find duplicates of single field '${fieldToString(chain[0])}'`);\n markIdenticalLoneFieldsAsDeletable(chain[0], record);\n return;\n }\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fieldsWithSubfield8);\n if (linkingNumbers.length < 2) {\n markIdenticalSubfield6Chains(chain, record);\n return;\n }\n }\n\n if (fieldsWithSubfield6.length > 0 && acceptFieldsWithSubfield8(fieldsWithSubfield8, true)) { // Checks that non-880 tags are all same\n // Chain is removable\n markIdenticalSubfield6Chains(chain, record);\n return;\n }\n\n\n nvdebug(` NO HANDLER FOUND FOR '${fieldsToString(chain)}'`);\n nvdebug(` N8s: ${fieldsWithSubfield6.length}`);\n\n}\n\n\nexport function removeDuplicateDatafields(record, fix = true) {\n // Sometimes only $8 subfield (vs the whole field) is removed. Thus they are handled separately:\n handleDuplicateSubfield8Chains(record, fix);\n\n const dataFields = record.fields.filter(f => f.subfields !== undefined);\n\n dataFields.forEach(f => fieldHandleDuplicateDatafields(f, record));\n\n const deletableFields = dataFields.filter(f => f.deleted);\n const modifiedFields = dataFields.filter(f => f.modified && !f.deleted);\n\n const result = deletableFields.map(f => `DEL: ${fieldToString(f)}`);\n if (modifiedFields.length) {\n modifiedFields.forEach(f => delete f.modified);\n result.push(modifiedFields.map(f => `MOD: ${fieldToString(f)}`));\n }\n\n if (fix) {\n deletableFields.forEach(f => record.removeField(f));\n return result;\n }\n\n deletableFields.forEach(f => delete f.deleted);\n deletableFields.forEach(f => delete f.modified);\n\n\n return result;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,uBAAuB;AAC9B,SAAQ,
|
|
4
|
+
"sourcesContent": ["import createDebugLogger from 'debug';\nimport {fieldToString, nvdebug} from './utils.js';\nimport {fieldHasValidSubfield6, fieldsGetOccurrenceNumbers, fieldsToNormalizedString, fieldToNormalizedString, get6s} from './subfield6Utils.js';\nimport {add8s, fieldHasLinkingNumber, fieldHasValidSubfield8, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils.js';\n\nconst LINK_ROOT = 4;\nconst LINKED_AND_PROCESSED = 2;\nconst LINKED_NOT_PROCESSED = 1;\n\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeDuplicateDataFields');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nexport default function () {\n return {\n description: 'Remove duplicate data fields. Certain exceptions apply, mainly too complited chained fields',\n validate, fix\n };\n\n function fix(record) {\n nvdebug('Remove duplicate data fields', debugDev);\n const res = {message: [], fix: [], valid: true};\n removeDuplicateDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n nvdebug('Validate record: duplicate data fields cause (t)error', debugDev);\n\n const duplicates = removeDuplicateDatafields(record, false);\n\n //const orphanedFields = getOrphanedFields(fieldsContainingSubfield6);\n\n const res = {message: duplicates};\n\n /*\n if (orphanedFields.length > 0) {\n res.message = [`${orphanedFields.length} orphaned occurrence number field(s) detected`];\n }\n */\n res.valid = res.message.length < 1;\n return res;\n }\n}\n\n\n/*\nfunction numberOfLinkageSubfields(field) {\n nvdebug(`N of Linkage Subs(${fieldToString(field)})`, debugDev);\n const subfields = field.subfields.filter(sf => sf.code === '6' || sf.code === '8');\n return subfields.length;\n}\n*/\n\nfunction removeLinkNotes(record) {\n record.fields.forEach(f => delete f.linkNote);\n}\n\n\nfunction newGetAllLinkedFields(field, record, useSixes = true, useEights = true) {\n removeLinkNotes(record); // should be clear, but let's play safe\n\n field.linkNote = LINK_ROOT;\n\n let currField = field;\n\n // Loop until all linked fields have been processed:\n while (currField !== undefined) {\n if (useSixes) {\n const related6s = get6s(currField, record.fields)\n related6s.forEach(f => linkField(f));\n }\n if (useEights) {\n const related8s = add8s([currField], record);\n related8s.forEach(f => linkField(f));\n }\n if (currField.linkNote !== LINK_ROOT) {\n currField.linkNote = LINKED_AND_PROCESSED;\n }\n currField = record.fields.find(f => f.linkNote === LINKED_NOT_PROCESSED);\n }\n\n // Collect relevant fields:\n const linkedFields = record.fields.filter(f => f.linkNote);\n\n removeLinkNotes(record);\n\n return linkedFields;\n\n function linkField(f) {\n if (!f.linkNote) {\n f.linkNote = LINKED_NOT_PROCESSED;\n }\n }\n\n}\n\n\nfunction recordRemoveFieldOrSubfield8(record, field, currLinkingNumber) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n record.removeField(field);\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => record.removeSubfield(sf, field));\n}\n\nfunction newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix) {\n const eights = field.subfields.filter(sf => sf.code === '8');\n if (eights.length < 2) {\n field.deleted = 1;\n return;\n }\n const subfields = field.subfields.filter(sf => getSubfield8LinkingNumber(sf) === currLinkingNumber);\n subfields.forEach(sf => {\n field.modified = 1;\n if (fix) {\n record.removeSubfield(sf, field);\n }\n });\n}\n\n\nexport function removeDuplicateSubfield8Chains(record, fix = true) {\n\n // Seen $8 subsfields in various fields:\n // 161 700\n // 17 710\n // 11 110\n // 8 730\n // 1 100\n // Given these stats, there's no need to check for 1XX-vs-7XX removals\n\n let seen = {};\n\n let removables = []; // for validation\n\n //nvdebug(\"CHAIN-8\", debugDev);\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return removables;\n }\n\n //nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debugDev);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n // As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true\n const normalizeOccurrenceNumber = true;\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);\n //nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debugDev);\n //nvdebug(`${linkedFieldsAsString}`, debugDev);\n\n if (linkedFieldsAsString in seen) {\n if (!removables.includes(linkedFieldsAsString)) {\n removables.push(linkedFieldsAsString);\n }\n\n if (fix) {\n //nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debugDev);\n linkedFields.forEach(field => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));\n return;\n }\n\n //nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debugDev);\n return;\n }\n //nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debugDev);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n return removables;\n}\n\n\nexport function handleDuplicateSubfield8Chains(record, fix) {\n\n // Seen $8 subsfields in various fields:\n // 161 700\n // 17 710\n // 11 110\n // 8 730\n // 1 100\n // Given these stats, there's no need to check for 1XX-vs-7XX removals\n\n let seen = {};\n\n //nvdebug(\"CHAIN-8\", debugDev);\n const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);\n if (seenLinkingNumbers.length === 0) {\n return;\n }\n\n //nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debugDev);\n\n seenLinkingNumbers.forEach(currLinkingNumber => {\n const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);\n // As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true\n const normalizeOccurrenceNumber = false; //true;\n const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);\n //nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debugDev);\n //nvdebug(`${linkedFieldsAsString}`, debugDev);\n\n if (linkedFieldsAsString in seen) {\n //nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debugDev);\n linkedFields.forEach(field => newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix));\n return;\n }\n //nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debugDev);\n seen[linkedFieldsAsString] = 1;\n return;\n });\n\n}\n\nfunction markIdenticalSubfield6Chains(chain, record) {\n const normalizeOccurrenceNumber = true;\n const normalizeTag = chain.some(field => field.tag.substring(0, 1) === '1'); // 1XX can delete 7XX as well!\n const chainAsString = fieldsToNormalizedString(chain, 0, normalizeOccurrenceNumber, normalizeTag);\n\n //nvdebug(`markIdenticalSubfield6Chains: ${chainAsString}`, debugDev);\n record.fields.forEach(f => compareWithChain(f));\n\n\n function compareWithChain(f) {\n //nvdebug(`FIELD2CHAIN ${fieldToString(f)}`, debugDev);\n const otherChain = fieldToChain(f, record);\n // Not a lone field or chain (head) or ... or is-same-chain\n if (otherChain.length === 0 || sameField(chain[0], otherChain[0])) {\n return;\n }\n const otherChainAsString = fieldsToNormalizedString(otherChain, 0, normalizeOccurrenceNumber, normalizeTag);\n\n // Mark other chain as deleted:\n if (chainAsString === otherChainAsString) {\n otherChain.forEach(f => {\n //nvdebug(` mark ${fieldToString(f)} as deleted ($6-chain)...`, debugDev);\n f.deleted = 1;\n });\n return;\n }\n }\n\n}\n\nfunction markIdenticalLoneFieldsAsDeletable(field, record) {\n if (field.deleted) {\n return;\n }\n // targetLinkingNumber = 0, normalizedOccurenceNumber = false, normalizeTag = true)\n const normalizeTag = field.tag.substring(0, 1) === '1'; // 1XX can delete 7XX as well!\n const fieldAsString = fieldToNormalizedString(field, 0, false, normalizeTag);\n\n const identicalLoneFields = record.fields.filter(f => !sameField(f, field) && fieldToNormalizedString(f, 0, false, normalizeTag) === fieldAsString);\n\n // Mark fields as deleted:\n identicalLoneFields.forEach(f => {\n //nvdebug(` mark ${fieldToString(f)} as deleted (lone field)...`, debugDev);\n f.deleted = 1;\n });\n\n}\n\nfunction acceptFieldsWithSubfield6(fieldsWithSubfield6) {\n // There can be only one non-880 field:\n const non880 = fieldsWithSubfield6.filter(f => f.tag !== '880');\n if (non880.length > 1) {\n return false;\n }\n\n const occurrenceNumbers = fieldsGetOccurrenceNumbers(fieldsWithSubfield6);\n // Chain can contain only single occurrence number:\n if (occurrenceNumbers.length > 1) {\n return false;\n }\n\n return true;\n}\n\n\nfunction isSingleTagLinkingNumber(linkingNumber, fields, tag) {\n const relevantFields = fields.filter(f => fieldHasLinkingNumber(f, linkingNumber));\n if (relevantFields.some(f => f.tag !== tag)) {\n return false;\n }\n return true;\n}\n\nfunction acceptFieldsWithSubfield8(fieldsWithSubfield8, requireSingleTag = false) {\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fieldsWithSubfield8);\n if (linkingNumbers.some(linkingNumber => anomaly8(linkingNumber))) {\n return false;\n }\n return true;\n\n // If linking number\n function anomaly8(linkingNumber) {\n //nvdebug(` Looking for anomalies in linkin number ${linkingNumber}`, debugDev);\n const relevantFields = fieldsWithSubfield8.filter(f => fieldHasLinkingNumber(f, linkingNumber));\n if (requireSingleTag) {\n return !isSingleTagLinkingNumber(linkingNumber, relevantFields, relevantFields[0].tag);\n }\n\n const f880 = relevantFields.filter(f => f.tag === '880');\n if (f880.length === 0 || f880.length === relevantFields.length) {\n return false;\n }\n return true;\n }\n}\n\n\nexport function sameField(field1, field2) {\n field1.tmpMyId = 666;\n const result = field2.tmpMyId === 666 ? true : false;\n delete field1.tmpMyId;\n return result;\n}\n\nexport function isChainHead(field, chain) {\n return sameField(field, chain[0]);\n}\n\nexport function fieldToChain(field, record) {\n if (field.deleted || !field.subfields) {\n return [];\n }\n const chain = newGetAllLinkedFields(field, record, true, true);\n\n // nvdebug(` Chain contains ${chain.length} field(s)`, debugDev);\n if (!isChainHead(field, chain)) { // newGetAllLinkedFields() marks relevant record.fields!\n return [];\n }\n\n const fieldsWithSubfield6 = chain.filter(f => fieldHasValidSubfield6(f));\n // Hack: multiple $6 fields, but either all are non-880 or all are 880: treat field as a single entry\n if (fieldsWithSubfield6.length > 0) {\n const non880 = fieldsWithSubfield6.filter(f => f.tag !== '880');\n if (non880.length === 0 || non880.length === fieldsWithSubfield6.length) {\n return [field];\n }\n if (non880.length !== 1) {\n return [field];\n }\n }\n\n if (!acceptFieldsWithSubfield6(fieldsWithSubfield6)) { // Check tag subfield $6s are legal(ish)\n return [];\n }\n const fieldsWithSubfield8 = chain.filter(f => fieldHasValidSubfield8(f));\n if (!acceptFieldsWithSubfield8(fieldsWithSubfield8, false)) {\n return [];\n }\n\n //nvdebug(`Proceed with ${fieldsToString(chain)}`, debugDev);\n\n\n return chain;\n}\n\n\nfunction fieldHandleDuplicateDatafields(field, record) {\n const chain = fieldToChain(field, record);\n //nvdebug(` TRY TO HANDLE DUPLICATES OF '${fieldsToString(chain)}'`, debugDev);\n\n if (chain.length === 0) {\n return;\n }\n\n const fieldsWithSubfield6 = chain.filter(f => fieldHasValidSubfield6(f));\n const fieldsWithSubfield8 = chain.filter(f => fieldHasValidSubfield8(f));\n\n // Lone fields:\n if (chain.length === 1) {\n markIdenticalLoneFieldsAsDeletable(chain[0], record);\n return;\n }\n if (fieldsWithSubfield6.length === 0) {\n\n if (fieldsWithSubfield8.length === 0) { // chain.length === 1?\n //nvdebug(` Trying to find duplicates of single field '${fieldToString(chain[0])}'`, debugDev);\n markIdenticalLoneFieldsAsDeletable(chain[0], record);\n return;\n }\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fieldsWithSubfield8);\n if (linkingNumbers.length < 2) {\n markIdenticalSubfield6Chains(chain, record);\n return;\n }\n }\n\n if (fieldsWithSubfield6.length > 0 && acceptFieldsWithSubfield8(fieldsWithSubfield8, true)) { // Checks that non-880 tags are all same\n // Chain is removable\n markIdenticalSubfield6Chains(chain, record);\n return;\n }\n\n\n //nvdebug(` NO HANDLER FOUND FOR '${fieldsToString(chain)}'`, debugDev);\n //nvdebug(` N8s: ${fieldsWithSubfield6.length}`, debugDev);\n\n}\n\n\nexport function removeDuplicateDatafields(record, fix = true) {\n // Sometimes only $8 subfield (vs the whole field) is removed. Thus they are handled separately:\n handleDuplicateSubfield8Chains(record, fix);\n\n const dataFields = record.fields.filter(f => f.subfields !== undefined);\n\n dataFields.forEach(f => fieldHandleDuplicateDatafields(f, record));\n\n const deletableFields = dataFields.filter(f => f.deleted);\n const modifiedFields = dataFields.filter(f => f.modified && !f.deleted);\n\n const result = deletableFields.map(f => `DEL: ${fieldToString(f)}`);\n if (modifiedFields.length) {\n modifiedFields.forEach(f => delete f.modified);\n result.push(modifiedFields.map(f => `MOD: ${fieldToString(f)}`));\n }\n\n if (fix) {\n deletableFields.forEach(f => record.removeField(f));\n return result;\n }\n\n deletableFields.forEach(f => delete f.deleted);\n deletableFields.forEach(f => delete f.modified);\n\n\n return result;\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,uBAAuB;AAC9B,SAAQ,eAAe,eAAc;AACrC,SAAQ,wBAAwB,4BAA4B,0BAA0B,yBAAyB,aAAY;AAC3H,SAAQ,OAAO,uBAAuB,wBAAwB,qCAAqC,2BAA2B,qCAAqC,iDAAgD;AAEnN,MAAM,YAAY;AAClB,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAK7B,MAAM,QAAQ,kBAAkB,oEAAoE;AAEpG,MAAM,WAAW,MAAM,OAAO,KAAK;AAEnC,0BAA2B;AACzB,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IAAU;AAAA,EACZ;AAEA,WAAS,IAAI,QAAQ;AACnB,YAAQ,gCAAgC,QAAQ;AAChD,UAAM,MAAM,EAAC,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO,KAAI;AAC9C,8BAA0B,QAAQ,IAAI;AAEtC,WAAO;AAAA,EACT;AAEA,WAAS,SAAS,QAAQ;AAExB,YAAQ,yDAAyD,QAAQ;AAEzE,UAAM,aAAa,0BAA0B,QAAQ,KAAK;AAI1D,UAAM,MAAM,EAAC,SAAS,WAAU;AAOhC,QAAI,QAAQ,IAAI,QAAQ,SAAS;AACjC,WAAO;AAAA,EACT;AACF;AAWA,SAAS,gBAAgB,QAAQ;AAC/B,SAAO,OAAO,QAAQ,OAAK,OAAO,EAAE,QAAQ;AAC9C;AAGA,SAAS,sBAAsB,OAAO,QAAQ,WAAW,MAAM,YAAY,MAAM;AAC/E,kBAAgB,MAAM;AAEtB,QAAM,WAAW;AAEjB,MAAI,YAAY;AAGhB,SAAO,cAAc,QAAW;AAC9B,QAAI,UAAU;AACZ,YAAM,YAAY,MAAM,WAAW,OAAO,MAAM;AAChD,gBAAU,QAAQ,OAAK,UAAU,CAAC,CAAC;AAAA,IACrC;AACA,QAAI,WAAW;AACb,YAAM,YAAY,MAAM,CAAC,SAAS,GAAG,MAAM;AAC3C,gBAAU,QAAQ,OAAK,UAAU,CAAC,CAAC;AAAA,IACrC;AACA,QAAI,UAAU,aAAa,WAAW;AACpC,gBAAU,WAAW;AAAA,IACvB;AACA,gBAAY,OAAO,OAAO,KAAK,OAAK,EAAE,aAAa,oBAAoB;AAAA,EACzE;AAGA,QAAM,eAAe,OAAO,OAAO,OAAO,OAAK,EAAE,QAAQ;AAEzD,kBAAgB,MAAM;AAEtB,SAAO;AAEP,WAAS,UAAU,GAAG;AACpB,QAAI,CAAC,EAAE,UAAU;AACf,QAAE,WAAW;AAAA,IACf;AAAA,EACF;AAEF;AAGA,SAAS,6BAA6B,QAAQ,OAAO,mBAAmB;AACtE,QAAM,SAAS,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,GAAG;AAC3D,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,YAAY,KAAK;AACxB;AAAA,EACF;AACA,QAAM,YAAY,MAAM,UAAU,OAAO,QAAM,0BAA0B,EAAE,MAAM,iBAAiB;AAClG,YAAU,QAAQ,QAAM,OAAO,eAAe,IAAI,KAAK,CAAC;AAC1D;AAEA,SAAS,gCAAgC,QAAQ,OAAO,mBAAmB,KAAK;AAC9E,QAAM,SAAS,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,GAAG;AAC3D,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,UAAU;AAChB;AAAA,EACF;AACA,QAAM,YAAY,MAAM,UAAU,OAAO,QAAM,0BAA0B,EAAE,MAAM,iBAAiB;AAClG,YAAU,QAAQ,QAAM;AACtB,UAAM,WAAW;AACjB,QAAI,KAAK;AACP,aAAO,eAAe,IAAI,KAAK;AAAA,IACjC;AAAA,EACF,CAAC;AACH;AAGO,gBAAS,+BAA+B,QAAQ,MAAM,MAAM;AAUjE,MAAI,OAAO,CAAC;AAEZ,MAAI,aAAa,CAAC;AAGlB,QAAM,qBAAqB,oCAAoC,MAAM;AACrE,MAAI,mBAAmB,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAIA,qBAAmB,QAAQ,uBAAqB;AAC9C,UAAM,eAAe,0CAA0C,QAAQ,iBAAiB;AAExF,UAAM,4BAA4B;AAClC,UAAM,uBAAuB,yBAAyB,cAAc,mBAAmB,2BAA2B,IAAI;AAItH,QAAI,wBAAwB,MAAO;AACjC,UAAI,CAAC,WAAW,SAAS,oBAAoB,GAAG;AAC9C,mBAAW,KAAK,oBAAoB;AAAA,MACtC;AAEA,UAAI,KAAK;AAEP,qBAAa,QAAQ,WAAS,6BAA6B,QAAQ,OAAO,iBAAiB,CAAC;AAC5F;AAAA,MACF;AAGA;AAAA,IACF;AAEA,SAAK,oBAAoB,IAAI;AAC7B;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGO,gBAAS,+BAA+B,QAAQ,KAAK;AAU1D,MAAI,OAAO,CAAC;AAGZ,QAAM,qBAAqB,oCAAoC,MAAM;AACrE,MAAI,mBAAmB,WAAW,GAAG;AACnC;AAAA,EACF;AAIA,qBAAmB,QAAQ,uBAAqB;AAC9C,UAAM,eAAe,0CAA0C,QAAQ,iBAAiB;AAExF,UAAM,4BAA4B;AAClC,UAAM,uBAAuB,yBAAyB,cAAc,mBAAmB,2BAA2B,IAAI;AAItH,QAAI,wBAAwB,MAAO;AAEjC,mBAAa,QAAQ,WAAS,gCAAgC,QAAQ,OAAO,mBAAmB,GAAG,CAAC;AACpG;AAAA,IACF;AAEA,SAAK,oBAAoB,IAAI;AAC7B;AAAA,EACF,CAAC;AAEH;AAEA,SAAS,6BAA6B,OAAO,QAAQ;AACnD,QAAM,4BAA4B;AAClC,QAAM,eAAe,MAAM,KAAK,WAAS,MAAM,IAAI,UAAU,GAAG,CAAC,MAAM,GAAG;AAC1E,QAAM,gBAAgB,yBAAyB,OAAO,GAAG,2BAA2B,YAAY;AAGhG,SAAO,OAAO,QAAQ,OAAK,iBAAiB,CAAC,CAAC;AAG9C,WAAS,iBAAiB,GAAG;AAE3B,UAAM,aAAa,aAAa,GAAG,MAAM;AAEzC,QAAI,WAAW,WAAW,KAAK,UAAU,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG;AACjE;AAAA,IACF;AACA,UAAM,qBAAqB,yBAAyB,YAAY,GAAG,2BAA2B,YAAY;AAG1G,QAAI,kBAAkB,oBAAoB;AACxC,iBAAW,QAAQ,CAAAA,OAAK;AAEtB,QAAAA,GAAE,UAAU;AAAA,MACd,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAEF;AAEA,SAAS,mCAAmC,OAAO,QAAQ;AACzD,MAAI,MAAM,SAAS;AACjB;AAAA,EACF;AAEA,QAAM,eAAe,MAAM,IAAI,UAAU,GAAG,CAAC,MAAM;AACnD,QAAM,gBAAgB,wBAAwB,OAAO,GAAG,OAAO,YAAY;AAE3E,QAAM,sBAAsB,OAAO,OAAO,OAAO,OAAK,CAAC,UAAU,GAAG,KAAK,KAAK,wBAAwB,GAAG,GAAG,OAAO,YAAY,MAAM,aAAa;AAGlJ,sBAAoB,QAAQ,OAAK;AAE/B,MAAE,UAAU;AAAA,EACd,CAAC;AAEH;AAEA,SAAS,0BAA0B,qBAAqB;AAEtD,QAAM,SAAS,oBAAoB,OAAO,OAAK,EAAE,QAAQ,KAAK;AAC9D,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,oBAAoB,2BAA2B,mBAAmB;AAExE,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAGA,SAAS,yBAAyB,eAAe,QAAQ,KAAK;AAC5D,QAAM,iBAAiB,OAAO,OAAO,OAAK,sBAAsB,GAAG,aAAa,CAAC;AACjF,MAAI,eAAe,KAAK,OAAK,EAAE,QAAQ,GAAG,GAAG;AAC3C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,qBAAqB,mBAAmB,OAAO;AAChF,QAAM,iBAAiB,oCAAoC,mBAAmB;AAC9E,MAAI,eAAe,KAAK,mBAAiB,SAAS,aAAa,CAAC,GAAG;AACjE,WAAO;AAAA,EACT;AACA,SAAO;AAGP,WAAS,SAAS,eAAe;AAE/B,UAAM,iBAAiB,oBAAoB,OAAO,OAAK,sBAAsB,GAAG,aAAa,CAAC;AAC9F,QAAI,kBAAkB;AACpB,aAAO,CAAC,yBAAyB,eAAe,gBAAgB,eAAe,CAAC,EAAE,GAAG;AAAA,IACvF;AAEA,UAAM,OAAO,eAAe,OAAO,OAAK,EAAE,QAAQ,KAAK;AACvD,QAAI,KAAK,WAAW,KAAK,KAAK,WAAW,eAAe,QAAQ;AAC9D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;AAGO,gBAAS,UAAU,QAAQ,QAAQ;AACxC,SAAO,UAAU;AACjB,QAAM,SAAS,OAAO,YAAY,MAAM,OAAO;AAC/C,SAAO,OAAO;AACd,SAAO;AACT;AAEO,gBAAS,YAAY,OAAO,OAAO;AACxC,SAAO,UAAU,OAAO,MAAM,CAAC,CAAC;AAClC;AAEO,gBAAS,aAAa,OAAO,QAAQ;AAC1C,MAAI,MAAM,WAAW,CAAC,MAAM,WAAW;AACrC,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,sBAAsB,OAAO,QAAQ,MAAM,IAAI;AAG7D,MAAI,CAAC,YAAY,OAAO,KAAK,GAAG;AAC9B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,sBAAsB,MAAM,OAAO,OAAK,uBAAuB,CAAC,CAAC;AAEvE,MAAI,oBAAoB,SAAS,GAAG;AAClC,UAAM,SAAS,oBAAoB,OAAO,OAAK,EAAE,QAAQ,KAAK;AAC9D,QAAI,OAAO,WAAW,KAAK,OAAO,WAAW,oBAAoB,QAAQ;AACvE,aAAO,CAAC,KAAK;AAAA,IACf;AACA,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO,CAAC,KAAK;AAAA,IACf;AAAA,EACF;AAEA,MAAI,CAAC,0BAA0B,mBAAmB,GAAG;AACnD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,sBAAsB,MAAM,OAAO,OAAK,uBAAuB,CAAC,CAAC;AACvE,MAAI,CAAC,0BAA0B,qBAAqB,KAAK,GAAG;AAC1D,WAAO,CAAC;AAAA,EACV;AAKA,SAAO;AACT;AAGA,SAAS,+BAA+B,OAAO,QAAQ;AACrD,QAAM,QAAQ,aAAa,OAAO,MAAM;AAGxC,MAAI,MAAM,WAAW,GAAG;AACtB;AAAA,EACF;AAEA,QAAM,sBAAsB,MAAM,OAAO,OAAK,uBAAuB,CAAC,CAAC;AACvE,QAAM,sBAAsB,MAAM,OAAO,OAAK,uBAAuB,CAAC,CAAC;AAGvE,MAAI,MAAM,WAAW,GAAG;AACtB,uCAAmC,MAAM,CAAC,GAAG,MAAM;AACnD;AAAA,EACF;AACA,MAAI,oBAAoB,WAAW,GAAG;AAEpC,QAAI,oBAAoB,WAAW,GAAG;AAEpC,yCAAmC,MAAM,CAAC,GAAG,MAAM;AACnD;AAAA,IACF;AACA,UAAM,iBAAiB,oCAAoC,mBAAmB;AAC9E,QAAI,eAAe,SAAS,GAAG;AAC7B,mCAA6B,OAAO,MAAM;AAC1C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,oBAAoB,SAAS,KAAK,0BAA0B,qBAAqB,IAAI,GAAG;AAE1F,iCAA6B,OAAO,MAAM;AAC1C;AAAA,EACF;AAMF;AAGO,gBAAS,0BAA0B,QAAQ,MAAM,MAAM;AAE5D,iCAA+B,QAAQ,GAAG;AAE1C,QAAM,aAAa,OAAO,OAAO,OAAO,OAAK,EAAE,cAAc,MAAS;AAEtE,aAAW,QAAQ,OAAK,+BAA+B,GAAG,MAAM,CAAC;AAEjE,QAAM,kBAAkB,WAAW,OAAO,OAAK,EAAE,OAAO;AACxD,QAAM,iBAAiB,WAAW,OAAO,OAAK,EAAE,YAAY,CAAC,EAAE,OAAO;AAEtE,QAAM,SAAS,gBAAgB,IAAI,OAAK,QAAQ,cAAc,CAAC,CAAC,EAAE;AAClE,MAAI,eAAe,QAAQ;AACzB,mBAAe,QAAQ,OAAK,OAAO,EAAE,QAAQ;AAC7C,WAAO,KAAK,eAAe,IAAI,OAAK,QAAQ,cAAc,CAAC,CAAC,EAAE,CAAC;AAAA,EACjE;AAEA,MAAI,KAAK;AACP,oBAAgB,QAAQ,OAAK,OAAO,YAAY,CAAC,CAAC;AAClD,WAAO;AAAA,EACT;AAEA,kBAAgB,QAAQ,OAAK,OAAO,EAAE,OAAO;AAC7C,kBAAgB,QAAQ,OAAK,OAAO,EAAE,QAAQ;AAG9C,SAAO;AACT;",
|
|
6
6
|
"names": ["f"]
|
|
7
7
|
}
|
|
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
|
|
|
3
3
|
import validatorFactory from "./removeDuplicateDataFields.js";
|
|
4
4
|
import { READERS } from "@natlibfi/fixura";
|
|
5
5
|
import generateTests from "@natlibfi/fixugen";
|
|
6
|
-
import createDebugLogger from "debug";
|
|
7
6
|
generateTests({
|
|
8
7
|
callback,
|
|
9
8
|
path: [import.meta.dirname, "..", "test-fixtures", "remove-duplicate-datafields"],
|
|
@@ -18,18 +17,13 @@ generateTests({
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/removeDuplicateDataFields:test");
|
|
22
20
|
async function testValidatorFactory() {
|
|
23
21
|
const validator = await validatorFactory();
|
|
24
22
|
assert.equal(typeof validator, "object");
|
|
25
23
|
assert.equal(typeof validator.description, "string");
|
|
26
24
|
assert.equal(typeof validator.validate, "function");
|
|
27
25
|
}
|
|
28
|
-
async function callback({ getFixture,
|
|
29
|
-
if (enabled === false) {
|
|
30
|
-
debug("TEST SKIPPED!");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
33
27
|
const validator = await validatorFactory();
|
|
34
28
|
const record = new MarcRecord(getFixture("record.json"));
|
|
35
29
|
const expectedResult = getFixture("expectedResult.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/removeDuplicateDataFields.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './removeDuplicateDataFields.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './removeDuplicateDataFields.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'remove-duplicate-datafields'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/removeDuplicateDataFields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,6BAA6B;AAAA,EAChF,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAGD,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|