@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,41 +1,24 @@
|
|
|
1
1
|
// See https://www.loc.gov/marc/bibliographic/bdapndxj.html for details
|
|
2
2
|
|
|
3
|
-
import {subfieldArraysContainSameData} from
|
|
4
|
-
|
|
5
|
-
export function tagToDataProvenanceSubfieldCode(tag) {
|
|
6
|
-
if ( ['533', '800', '810', '811', '830'].includes(tag)) {
|
|
7
|
-
return 'y';
|
|
8
|
-
}
|
|
9
|
-
if ( tag === '856' || tag === '857' ) {
|
|
10
|
-
return 'e';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if ( tag.match(/^7[678]/u) ) {
|
|
14
|
-
return 'l'
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if ( tag.match(/^00/u)) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
return '7';
|
|
21
|
-
}
|
|
22
|
-
|
|
3
|
+
import {subfieldArraysContainSameData} from '../utils.js';
|
|
4
|
+
import {tagToDataProvenanceSubfieldCode} from '../dataProvenanceUtils.js';
|
|
23
5
|
|
|
24
6
|
export function provenanceSubfieldsPermitMerge(baseField, sourceField) {
|
|
25
|
-
const provinanceSubfieldCode = tagToDataProvenanceSubfieldCode(baseField.tag);
|
|
26
7
|
if (!baseField.subfields) {
|
|
27
8
|
return true;
|
|
28
9
|
}
|
|
29
|
-
|
|
10
|
+
const provenanceSubfieldCode = tagToDataProvenanceSubfieldCode(baseField.tag);
|
|
11
|
+
|
|
12
|
+
if (provenanceSubfieldCode === undefined) {
|
|
30
13
|
return false;
|
|
31
14
|
}
|
|
32
15
|
|
|
33
|
-
const
|
|
34
|
-
const
|
|
16
|
+
const baseProvenanceSubfields = baseField.subfields.filter(sf => sf.code === provenanceSubfieldCode);
|
|
17
|
+
const sourceProvenanceSubfields = sourceField.subfields.filter(sf => sf.code === provenanceSubfieldCode);
|
|
35
18
|
|
|
36
19
|
// Currently we just compare two arrays. Later on we might do something more sophisticated with specific $7 data provenance category/relationship codes,
|
|
37
20
|
// or actual values.
|
|
38
21
|
|
|
39
|
-
return subfieldArraysContainSameData(
|
|
22
|
+
return subfieldArraysContainSameData(baseProvenanceSubfields, sourceProvenanceSubfields);
|
|
40
23
|
|
|
41
24
|
}
|
|
@@ -49,7 +49,7 @@ export default function (defaultTagPattern = undefined) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function fix(record, config = undefined) {
|
|
52
|
-
const config2 = config || defaultConfig;
|
|
52
|
+
const config2 = config || defaultConfig.mergeConfiguration;
|
|
53
53
|
record.internalMerge = true;
|
|
54
54
|
mergeFieldsWithinRecord(record, config2);
|
|
55
55
|
delete record.internalMerge;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import createDebugLogger from 'debug';
|
|
2
|
-
import {marc21GetTagsLegalInd1Value, marc21GetTagsLegalInd2Value
|
|
1
|
+
//import createDebugLogger from 'debug';
|
|
2
|
+
import {marc21GetTagsLegalInd1Value, marc21GetTagsLegalInd2Value} from '../utils.js';
|
|
3
3
|
|
|
4
4
|
// Specs: https://workgroups.helsinki.fi/x/K1ohCw (though we occasionally differ from them)...
|
|
5
5
|
|
|
6
|
-
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:mergableIndicator');
|
|
6
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:mergableIndicator');
|
|
7
7
|
//const debugData = debug.extend('data');
|
|
8
|
-
const debugDev = debug.extend('dev');
|
|
8
|
+
//const debugDev = debug.extend('dev');
|
|
9
9
|
|
|
10
10
|
const ind1NonFilingChars = ['130', '630', '730', '740'];
|
|
11
11
|
const ind2NonFilingChars = ['222', '240', '242', '243', '245', '830'];
|
|
@@ -20,7 +20,6 @@ function marc21NoNeedToCheckInd1(tag) {
|
|
|
20
20
|
|
|
21
21
|
function marc21NoNeedToCheckInd2(tag) {
|
|
22
22
|
const cands = marc21GetTagsLegalInd2Value(tag);
|
|
23
|
-
nvdebug(`CHECK IND2 ${typeof cands} FOR ${tag}`, debugDev);
|
|
24
23
|
if (typeof cands === 'string') { // single cand
|
|
25
24
|
return true;
|
|
26
25
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const defaultNonMergableFields = [
|
|
9
9
|
'066', // 066 - Character sets present (NR)
|
|
10
|
+
'361',
|
|
10
11
|
'382', // 382: merging would be madness due to $n position etc...
|
|
11
12
|
// However, this will miss cases, where only $5 or $9 differs... Such is!
|
|
12
13
|
// 59X: always copy, never merge. NB! No specs exist!
|
|
@@ -52,6 +53,7 @@ const defaultNonMergableFields = [
|
|
|
52
53
|
'854',
|
|
53
54
|
'855',
|
|
54
55
|
// '856' is mergable, but a pain in the ass
|
|
56
|
+
'857',
|
|
55
57
|
'863',
|
|
56
58
|
'864',
|
|
57
59
|
'865',
|
|
@@ -30,9 +30,10 @@ export const mergeConfig = {
|
|
|
30
30
|
'246': {'0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '7': 1, '8': 1, ' ': 2},
|
|
31
31
|
'363': {'0': 1, '1': 1, ' ': 2},
|
|
32
32
|
'382': {'0': 1, '1': 1, ' ': 2},
|
|
33
|
-
'730': ['2', ' ']
|
|
33
|
+
'730': ['2', ' '] // If this is ok, it ok for 700, 710 and 711 as well...
|
|
34
34
|
},
|
|
35
35
|
'comment #4': 'List indicators that do not block merge here. Non-filing indicators do not prevent field merge (their support is hard-coded). They are mainly listed here as an example.',
|
|
36
|
+
// Actually I wouldn't want to ignore X00ind1=3 vs other values such as IND1=1... However, this is not currently supported.
|
|
36
37
|
'ignoreIndicator1': ['100', '110', '111', '130', '210', '242', '245', '246', '247', '307', '490', '505', '506', '510', '511', '516', '520', '521', '522', '524', '526', '583', '586', '600', '610', '630', '650', '651', '655', '700', '710', '730', '740', '760', '762', '765', '767', '770', '772', '773', '774', '775', '776', '777', '780', '785', '786', '787', '788', '800', '810'],
|
|
37
38
|
'ignoreIndicator2': ['017', '222', '240', '242', '243', '245', '760', '762', '765', '767', '770', '773', '774', '775', '776', '777', '786', '787', '788', '830'],
|
|
38
39
|
'comment #5': 'If one indicator has value, and the other has not, it does not necessarily mean mismatch',
|
|
@@ -3,19 +3,20 @@ const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:me
|
|
|
3
3
|
//const debugData = debug.extend('data');
|
|
4
4
|
const debugDev = debug.extend('dev');
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
// "key"
|
|
9
|
-
//
|
|
6
|
+
// "required": both fields bust have the subfield and the value must be same.
|
|
7
|
+
// "paired": subfield bust either exists (with value match) or not exist in both fields (negative XOR). Sort of an optional version of 'required'
|
|
8
|
+
// "key": one or both fields lack the subfield OR both fields have it and theor values match.
|
|
9
|
+
// There are typically NR subfields but the system should support multival repeatable subfields. However, (R) support is considered experimental.
|
|
10
10
|
// NB: key+paired with identical values is an attempt to prevent copy for (ET) fields, and to force separate fields on (T) fields.
|
|
11
11
|
// NB! If base has eg. no 264, two+ 264 fields can be copied from the source.
|
|
12
12
|
|
|
13
13
|
// NB! not all X00 fields have, say, $x subfield. However, we can still share them...
|
|
14
14
|
// $h is non-1XX?, $i is 7XX only, $w is 8XX only...
|
|
15
|
-
const keyX00 = '
|
|
16
|
-
const keyX10 = '
|
|
17
|
-
const keyX11 = '
|
|
15
|
+
const keyX00 = 'abcjklnoqrstuwx'; // Shared: $abcdefg...
|
|
16
|
+
const keyX10 = 'abcdfghklnoprstuwx';
|
|
17
|
+
const keyX11 = 'acdefghklnpqstuwx';
|
|
18
18
|
const keyX30 = 'adfghklmnoprstvwxyz';
|
|
19
|
+
const pairedTitleSubfields = 'iklmnoprst'
|
|
19
20
|
|
|
20
21
|
const mergeConstraints = [
|
|
21
22
|
{'tag': '010', 'required': 'a', 'key': 'a'},
|
|
@@ -24,7 +25,7 @@ const mergeConstraints = [
|
|
|
24
25
|
{'tag': '016', 'required': 'a', 'key': 'a2'},
|
|
25
26
|
{'tag': '017', 'required': 'a', 'key': 'a'},
|
|
26
27
|
{'tag': '018', 'required': 'a', 'key': 'a'},
|
|
27
|
-
{'tag': '020', 'required': '', 'paired': 'a', 'key': '
|
|
28
|
+
{'tag': '020', 'required': '', 'paired': 'a', 'key': 'az'}, // NB! $a foo $z lorum and $a foo $z ipsum would not merge! Due to common denominator and f020$z onlies this is the best we can done. This could be handled if 020 would have multiple merge constrains: one for f020$a, and one for f020$z...
|
|
28
29
|
{'tag': '022', 'required': '', 'paired': 'a', 'key': 'alz'},
|
|
29
30
|
{'tag': '024', 'required': '', 'paired': 'a', 'key': 'ad'},
|
|
30
31
|
{'tag': '025', 'required': 'a', 'key': 'a'},
|
|
@@ -41,8 +42,8 @@ const mergeConstraints = [
|
|
|
41
42
|
{'tag': '037', 'required': 'b', 'key': 'ab'},
|
|
42
43
|
{'tag': '039', 'required': 'a'},
|
|
43
44
|
{'tag': '040', 'required': '', 'key': ''},
|
|
44
|
-
{'tag': '041', 'required': '', 'paired': '2', 'key': ''}, // Don't put $2 in 'key'! hasCommonNominator() would get into trouble with it...
|
|
45
|
-
{'tag': '042', 'required': '
|
|
45
|
+
{'tag': '041', 'required': '', 'paired': '2', 'key': 'ad'}, // Don't put $2 in 'key'! hasCommonNominator() would get into trouble with it...
|
|
46
|
+
{'tag': '042', 'required': '', 'key': ''}, // Contents (supposedly $a subfields) can be anything, and still merge... (042 $a foo + 042 $b bar is perfectly mergeable)
|
|
46
47
|
{'tag': '043', 'required': 'a', 'key': 'abc'},
|
|
47
48
|
{'tag': '044', 'required': '', 'key': 'abc', 'paired': 'abc'},
|
|
48
49
|
{'tag': '045', 'required': '', 'key': 'abc', 'paired': 'abc'}, // (ET) // 045 is problematic either-$a or $b or $c...
|
|
@@ -69,11 +70,11 @@ const mergeConstraints = [
|
|
|
69
70
|
{'tag': '086', 'required': '', 'paired': 'a', 'key': 'a'},
|
|
70
71
|
{'tag': '088', 'required': '', 'paired': 'a', 'key': 'a'},
|
|
71
72
|
// NB! 100, 110 and 111 may have title parts that are handled elsewhere
|
|
72
|
-
{'tag': '100', 'required': 'a', 'paired':
|
|
73
|
-
{'tag': '110', 'required': 'a', 'paired':
|
|
74
|
-
{'tag': '111', 'required': 'a', 'paired':
|
|
73
|
+
{'tag': '100', 'required': 'a', 'paired': `b${pairedTitleSubfields}`, 'key': keyX00},
|
|
74
|
+
{'tag': '110', 'required': 'a', 'paired': `b${pairedTitleSubfields}`, 'key': keyX10},
|
|
75
|
+
{'tag': '111', 'required': 'a', 'paired': pairedTitleSubfields, 'key': keyX11},
|
|
75
76
|
// NB! 130 has no name part, key is used for title part
|
|
76
|
-
{'tag': '130', 'required': 'a', 'key': keyX30},
|
|
77
|
+
{'tag': '130', 'required': 'a', paired: pairedTitleSubfields, 'key': keyX30},
|
|
77
78
|
{'tag': '210', 'required': 'a', 'key': 'ab'},
|
|
78
79
|
{'tag': '222', 'required': 'a', 'key': 'ab'},
|
|
79
80
|
{'tag': '240', 'required': 'a', 'key': 'adfghklmnoprs'},
|
|
@@ -95,7 +96,7 @@ const mergeConstraints = [
|
|
|
95
96
|
//{'tag': '264', 'required': '', 'paired': 'abc', 'key': 'abc'}, // NB "S.l." normalizations?" not implemented
|
|
96
97
|
{'tag': '264', 'required': '', 'key': 'abc'}, // NB "S.l." normalizations?" not implemented
|
|
97
98
|
// SKIP TAG 270 ON PURPOSE! Melinda's N=43.
|
|
98
|
-
{'tag': '300', 'required': '
|
|
99
|
+
{'tag': '300', 'required': '', 'key': 'abcefg'},
|
|
99
100
|
{'tag': '306', 'required': 'a', 'key': 'a'},
|
|
100
101
|
// SKIP TAG 307 ON PURPOSE! N=0
|
|
101
102
|
{'tag': '310', 'required': 'a', 'key': 'ab'},
|
|
@@ -105,7 +106,7 @@ const mergeConstraints = [
|
|
|
105
106
|
{'tag': '337', 'required': 'b2', 'key': 'ab2'}, // MET-88: don't merge different $a subfields
|
|
106
107
|
{'tag': '338', 'required': 'b2', 'key': 'ab2'}, // / MET-88: don't merge different $a subfields
|
|
107
108
|
{'tag': '340', 'required': '', 'paired': 'abcdefghijkmnop', 'key': 'abcdefghijkmnop'},
|
|
108
|
-
{'tag': '341', 'required': '', 'paired': '
|
|
109
|
+
{'tag': '341', 'required': '', 'paired': 'a2', 'key': 'abcde2'}, // NEW! Starting to appear!
|
|
109
110
|
{'tag': '342', 'required': '', 'paired': 'abcdefghijklmnopqrstuvw', 'key': 'abcdefghijklmnopqrstuvw'}, // SKIP 342. NOT SEEN!
|
|
110
111
|
{'tag': '343', 'required': '', 'paired': 'abcdefghi', 'key': 'abcdefghi'}, // SKIP 343.
|
|
111
112
|
{'tag': '344', 'required': '', 'paired': 'abcdefgh', 'key': 'abcdefgh'},
|
|
@@ -132,7 +133,7 @@ const mergeConstraints = [
|
|
|
132
133
|
{'tag': '385', 'required': 'a', 'paired': 'abmn', 'key': 'abmn'},
|
|
133
134
|
{'tag': '386', 'required': 'a', 'paired': 'abmn', 'key': 'abmn'},
|
|
134
135
|
{'tag': '388', 'required': 'a', 'key': 'a'},
|
|
135
|
-
{'tag': '490', 'required': '
|
|
136
|
+
{'tag': '490', 'required': '', 'key': 'axvl'},
|
|
136
137
|
{'tag': '500', 'required': 'a', 'key': 'a'},
|
|
137
138
|
{'tag': '501', 'required': 'a', 'key': 'a'},
|
|
138
139
|
{'tag': '502', 'required': 'a', 'key': 'abcdgo'},
|
|
@@ -195,10 +196,10 @@ const mergeConstraints = [
|
|
|
195
196
|
{'tag': '597', 'required': ''},
|
|
196
197
|
{'tag': '598', 'required': ''},
|
|
197
198
|
{'tag': '599', 'required': ''},
|
|
198
|
-
{'tag': '600', 'required': 'a', 'paired':
|
|
199
|
-
{'tag': '610', 'required': 'a', 'paired':
|
|
200
|
-
{'tag': '611', 'required': 'a', 'paired':
|
|
201
|
-
{'tag': '630', 'required': 'a', 'paired':
|
|
199
|
+
{'tag': '600', 'required': 'a', 'paired': `b${pairedTitleSubfields}vxyz`, 'key': keyX00},
|
|
200
|
+
{'tag': '610', 'required': 'a', 'paired': `b${pairedTitleSubfields}vxyz`, 'key': keyX10},
|
|
201
|
+
{'tag': '611', 'required': 'a', 'paired': `${pairedTitleSubfields}vxyz`, 'key': keyX11},
|
|
202
|
+
{'tag': '630', 'required': 'a', 'paired': `${pairedTitleSubfields}vxyz`, 'key': keyX30},
|
|
202
203
|
// NB! 700, 710 and 711 may have title parts that are handled elsewhere
|
|
203
204
|
{'tag': '647', 'required': 'a', 'paired': 'avxyz', 'key': 'acdgvxyz02'},
|
|
204
205
|
{'tag': '648', 'required': 'a', 'paired': 'avxyz', 'key': 'avxyz02'},
|
|
@@ -212,12 +213,12 @@ const mergeConstraints = [
|
|
|
212
213
|
{'tag': '658', 'required': 'a', 'paired': 'abcd'}, // N=0
|
|
213
214
|
{'tag': '662', 'required': '', 'paired': 'abcdefgh'}, // N=0
|
|
214
215
|
{'tag': '688', 'required': 'a'}, // N=0
|
|
215
|
-
{'tag': '700', 'required': 'a', 'paired':
|
|
216
|
-
{'tag': '710', 'required': 'a', 'paired':
|
|
217
|
-
{'tag': '711', 'required': 'a', 'paired':
|
|
216
|
+
{'tag': '700', 'required': 'a', 'paired': `b${pairedTitleSubfields}x`, 'key': keyX00}, // h/i/m/o/r/s/x are missing from 100, NB! 's' is repeatable, but we are not merging them here!
|
|
217
|
+
{'tag': '710', 'required': 'a', 'paired': `b${pairedTitleSubfields}x`, 'key': keyX10}, // h/j/m/o/r/s/x are missing from 110
|
|
218
|
+
{'tag': '711', 'required': 'a', 'paired': `cdef${pairedTitleSubfields}x`, 'key': keyX11}, // h/i/s/x are missing from 711
|
|
218
219
|
{'tag': '720', 'required': 'a', 'key': 'a'},
|
|
219
220
|
// NB! 730 has no name part, key is used for title part
|
|
220
|
-
{'tag': '730', 'required': 'a', 'key': keyX30}, // NB: 130->730 magic subfields might not agree...
|
|
221
|
+
{'tag': '730', 'required': 'a', 'paired': `df${pairedTitleSubfields}x`, 'key': keyX30}, // NB: 130->730 magic subfields might not agree...
|
|
221
222
|
{'tag': '740', 'required': 'a', 'key': 'ahnp'},
|
|
222
223
|
{'tag': '751', 'required': 'a', 'key': 'a'}, // N=11, kaikissa pelkkä $a
|
|
223
224
|
{'tag': '752', 'required': '', 'key': 'abcdefgh'}, // N=12234
|
|
@@ -242,7 +243,7 @@ const mergeConstraints = [
|
|
|
242
243
|
{'tag': '786', 'required': '', 'paired': 'abcrstuxyz', 'key': 'abcdhijmprstuxyz4'},
|
|
243
244
|
{'tag': '787', 'required': '', 'paired': 'abcdhmstuxyz4'},
|
|
244
245
|
{'tag': '788', 'required': '', 'paired': 'stx', 'key': 'abdestx'},
|
|
245
|
-
{'tag': '800', 'required': 'a', 'paired': '
|
|
246
|
+
{'tag': '800', 'required': 'a', 'paired': 'bt', 'key': keyX00},
|
|
246
247
|
{'tag': '810', 'required': 'a', 'paired': 'bt', 'key': keyX10},
|
|
247
248
|
{'tag': '811', 'required': 'a', 'paired': 't', 'key': keyX11},
|
|
248
249
|
{'tag': '830', 'required': 'a', 'key': keyX30},
|
|
@@ -289,22 +290,26 @@ const mergeConstraints = [
|
|
|
289
290
|
{'tag': 'SID', 'required': ''}
|
|
290
291
|
];
|
|
291
292
|
|
|
292
|
-
function constraintToValue(tagsConstraints, constraintName) {
|
|
293
|
-
if (constraintName in tagsConstraints) {
|
|
294
|
-
return tagsConstraints[constraintName];
|
|
295
|
-
}
|
|
296
|
-
return null; // NB! "" might mean "apply to everything" (eg. 040.key) while null means that it is not applied.
|
|
297
|
-
}
|
|
298
293
|
|
|
299
|
-
export function getMergeConstraintsForTag(tag, constraintName) {
|
|
294
|
+
export function getMergeConstraintsForTag(tag, constraintName = undefined) {
|
|
300
295
|
const tagsConstraintsArray = mergeConstraints.filter(entry => tag === entry.tag);
|
|
301
296
|
if (tagsConstraintsArray.length === 0) {
|
|
302
|
-
debugDev(`WARNING\tNo key found for ${tag}
|
|
303
|
-
|
|
297
|
+
debugDev(`WARNING\tNo key found for ${tag}!`);
|
|
298
|
+
}
|
|
299
|
+
if (!constraintName) {
|
|
300
|
+
return tagsConstraintsArray;
|
|
304
301
|
}
|
|
305
302
|
// NB! should we support multiple contains for a field? Eg. 505$a vs 505($tg)+
|
|
306
303
|
if (tagsConstraintsArray.length > 1) {
|
|
307
304
|
debugDev(`WARNING\tMultiple values for '${constraintName}' (N=${tagsConstraintsArray.length}) found in ${tag}. Using first values.`);
|
|
308
305
|
}
|
|
309
|
-
return constraintToValue(tagsConstraintsArray[0], constraintName);
|
|
306
|
+
//return constraintToValue(tagsConstraintsArray[0], constraintName);
|
|
307
|
+
return tagsConstraintsArray.map(c => constraintToValue(c, constraintName));
|
|
308
|
+
|
|
309
|
+
function constraintToValue(tagsConstraints, constraintName) {
|
|
310
|
+
if (constraintName in tagsConstraints) {
|
|
311
|
+
return tagsConstraints[constraintName];
|
|
312
|
+
}
|
|
313
|
+
return null; // NB! "" might mean "apply to everything" (eg. 040.key) while null means that it is not applied.
|
|
314
|
+
}
|
|
310
315
|
}
|
|
@@ -2,19 +2,16 @@
|
|
|
2
2
|
import createDebugLogger from 'debug';
|
|
3
3
|
import {fieldToString, fieldsToString, fieldsAreIdentical, nvdebug, hasCopyright, removeCopyright, subfieldToString} from '../utils.js';
|
|
4
4
|
import {fieldGetOccurrenceNumberPairs} from '../subfield6Utils.js';
|
|
5
|
-
import {cloneAndNormalizeFieldForComparison, cloneAndRemovePunctuation
|
|
5
|
+
import {cloneAndNormalizeFieldForComparison, cloneAndRemovePunctuation} from '../normalizeFieldForComparison.js';
|
|
6
6
|
import {mergeOrAddSubfield} from './mergeOrAddSubfield.js';
|
|
7
7
|
import {mergeIndicators} from './mergeIndicator.js';
|
|
8
8
|
import {mergableTag} from './mergableTag.js';
|
|
9
9
|
import {getCounterpart} from './counterpartField.js';
|
|
10
|
+
import {isEnnakkotietoSubfield} from '../prepublicationUtils.js';
|
|
10
11
|
//import {default as normalizeEncoding} from '@natlibfi/marc-record-validators-melinda/dist/normalize-utf8-diacritics';
|
|
11
12
|
//import {postprocessRecords} from './mergeOrAddPostprocess.js';
|
|
12
13
|
//import {preprocessBeforeAdd} from './processFilter.js';
|
|
13
14
|
|
|
14
|
-
//import fs from 'fs';
|
|
15
|
-
//import path from 'path';
|
|
16
|
-
|
|
17
|
-
|
|
18
15
|
//const defaultConfig = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'src', 'reducers', 'config.json'), 'utf8'));
|
|
19
16
|
|
|
20
17
|
// Specs: https://workgroups.helsinki.fi/x/K1ohCw (though we occasionally differ from them)...
|
|
@@ -25,7 +22,7 @@ const debugDev = debug.extend('dev');
|
|
|
25
22
|
|
|
26
23
|
// NB! Can we do this via config.json?
|
|
27
24
|
function removeEnnakkotieto(field) {
|
|
28
|
-
const tmp = field.subfields.filter(subfield => !
|
|
25
|
+
const tmp = field.subfields.filter(subfield => !isEnnakkotietoSubfield(subfield));
|
|
29
26
|
// remove only iff some other subfield remains
|
|
30
27
|
if (tmp.length > 0) {
|
|
31
28
|
field.subfields = tmp;
|
|
@@ -59,7 +56,7 @@ function mergeField2(baseRecord, baseField, sourceField, config, candFieldPairs8
|
|
|
59
56
|
// If a base ennakkotieto is merged with real data, remove ennakkotieto subfield:
|
|
60
57
|
// (If our prepub normalizations are ok, this should not be needed.
|
|
61
58
|
// However, it's simple and works well enough, so let's keep it here.)
|
|
62
|
-
if (baseField.subfields?.find(sf =>
|
|
59
|
+
if (baseField.subfields?.find(sf => isEnnakkotietoSubfield(sf)) && !sourceField.subfields?.find(sf => isEnnakkotietoSubfield(sf))) {
|
|
63
60
|
removeEnnakkotieto(baseField);
|
|
64
61
|
baseField.merged = 1;
|
|
65
62
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
|
-
import {cloneAndNormalizeFieldForComparison
|
|
2
|
+
import {cloneAndNormalizeFieldForComparison} from '../normalizeFieldForComparison.js';
|
|
3
3
|
import {normalizeAs, normalizeControlSubfieldValue} from '../normalize-identifiers.js';
|
|
4
|
-
import {fieldHasSubfield, fieldToString,
|
|
4
|
+
import {fieldHasSubfield, fieldToString, isContentSubfieldCode, nvdebug, subfieldIsRepeatable, subfieldToString} from '../utils.js';
|
|
5
5
|
import {mergeSubfield} from './mergeSubfield.js';
|
|
6
6
|
import {sortAdjacentSubfields} from '../sortSubfields.js';
|
|
7
7
|
|
|
8
8
|
import {valueCarriesMeaning} from './worldKnowledge.js';
|
|
9
9
|
import {resetSubfield6Tag} from '../subfield6Utils.js';
|
|
10
|
+
import {isEnnakkotietoSubfield} from '../prepublicationUtils.js';
|
|
10
11
|
|
|
11
12
|
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:mergeOrAddSubfield');
|
|
12
13
|
//const debugData = debug.extend('data');
|
|
@@ -25,11 +26,11 @@ function catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTa
|
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
function
|
|
29
|
-
if (
|
|
29
|
+
function dataContainsPrepublicationSubfield(candSubfieldData) {
|
|
30
|
+
if (isEnnakkotietoSubfield({'code': candSubfieldData.code, 'value': candSubfieldData.originalValue})) {
|
|
30
31
|
// Skip just ‡g subfield or the whole field?
|
|
31
32
|
// We decided to skip just this subfield. We want at least $0 and maybe even more from ennakkotieto.
|
|
32
|
-
debugDev(`Skip '
|
|
33
|
+
debugDev(`Skip '‡${candSubfieldData.code} ${candSubfieldData.originalValue}'`);
|
|
33
34
|
return true;
|
|
34
35
|
}
|
|
35
36
|
return false;
|
|
@@ -75,7 +76,7 @@ function skipNormalizedComparison(tag, subfieldCode, subfieldValue) {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
function mergeOrAddSubfieldNotRequired(targetField, candSubfieldData) {
|
|
78
|
-
if (catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) ||
|
|
79
|
+
if (catalogingSourceModifyingAgencyCandIsOriginalCatalogingSourceAgencyInTargetField(targetField, candSubfieldData) || dataContainsPrepublicationSubfield(candSubfieldData)) {
|
|
79
80
|
return true;
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -126,7 +127,7 @@ function addSubfield(targetField, candSubfield) {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
function setPunctuationFlag(field, addedSubfield) {
|
|
129
|
-
if (
|
|
130
|
+
if (!isContentSubfieldCode(addedSubfield.code, field.tag)) { // These are never punctuation related
|
|
130
131
|
return;
|
|
131
132
|
}
|
|
132
133
|
field.useExternalEndPunctuation = 1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
2
|
import {partsAgree, subfieldContainsPartData} from '../normalizeSubfieldValueForComparison.js';
|
|
3
|
-
import {valueCarriesMeaning} from './worldKnowledge.js';
|
|
3
|
+
import {getSynonyms, valueCarriesMeaning} from './worldKnowledge.js';
|
|
4
4
|
import {nvdebug} from '../utils.js';
|
|
5
5
|
import {tagAndSubfieldCodeReferToIsbn} from '../normalizeFieldForComparison.js';
|
|
6
6
|
import {canContainOptionalQualifier, splitToNameAndQualifier} from './counterpartField.js';
|
|
@@ -88,7 +88,7 @@ function isPehmeakantinen(value) {
|
|
|
88
88
|
return ['mjuka pärmar', 'paperback', 'pehmeäkantinen', 'softcover'].includes(value);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function isItsenainenJatkoOsa(value) {
|
|
91
|
+
function isItsenainenJatkoOsa(value) { // Probably movable to synonyms...
|
|
92
92
|
if (value.match(/^Fristående fortsättning på verket[^a-z]*$/ui)) {
|
|
93
93
|
return true;
|
|
94
94
|
}
|
|
@@ -142,6 +142,15 @@ function pairHttpAndHttps(candSubfield, relevantSubfields) {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
function isSynonym(field, candSubfield, relevantSubfields) {
|
|
145
|
+
|
|
146
|
+
const finnishForm = getSynonyms(candSubfield.value, field.tag, candSubfield.code, 'fin');
|
|
147
|
+
if (finnishForm && finnishForm === relevantSubfields.some(sf => finnishForm === getSynonyms(sf.value, field.tag, candSubfield.code, 'fin'))) {
|
|
148
|
+
// NB! There's currently no intelligence (such as checking cat language from 040$b): the preferred value is the one in base.
|
|
149
|
+
// We might later on create a separate translation validator/fixer...
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
145
154
|
if (candSubfield.code === 'q' && ['015', '020', '024', '028'].includes(field.tag)) {
|
|
146
155
|
return coverTypesMatch(candSubfield, relevantSubfields);
|
|
147
156
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
//import {nvdebug} from '../utils';
|
|
1
|
+
//import {nvdebug} from '../utils.js';
|
|
2
|
+
//import createDebugLogger from 'debug';
|
|
3
|
+
|
|
4
|
+
// NB! This file (or at least synonyms) should eventually be moved away from merge to '..'.
|
|
5
|
+
|
|
6
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:worldKnowledge');
|
|
7
|
+
//const debugData = debug.extend('data');
|
|
8
|
+
//const debugDev = debug.extend('dev');
|
|
9
|
+
|
|
2
10
|
|
|
3
11
|
export function valueCarriesMeaning(tag, subfieldCode, value) {
|
|
4
12
|
// Some data is pretty meaningless and as meaningless is pretty close to nothing, this meaningless data should no prevent merge.
|
|
@@ -20,11 +28,77 @@ export function valueCarriesMeaning(tag, subfieldCode, value) {
|
|
|
20
28
|
return true;
|
|
21
29
|
}
|
|
22
30
|
|
|
31
|
+
const synonyms = [
|
|
32
|
+
{tags: ['700', '710', '711', '730'], code: 'i', 'fin': 'Sisältää (ekspressio)', 'swe': 'Innehåller (uttryck)'},
|
|
33
|
+
{tags: ['700', '710', '711', '730'], code: 'i', 'fin': 'Sisältää (teos)', 'swe': 'Innehåller (verk)'},
|
|
34
|
+
{tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Englanti', 'swe': 'Engelska'},
|
|
35
|
+
{tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Ruotsi', 'swe': 'Svenska'},
|
|
36
|
+
{tags: ['700', '710', '711', '730'], code: 'l', 'fin': 'Suomi', 'swe': 'Finska'}
|
|
37
|
+
// There might eventually be need for a list of terms is given language (eg. engl. paperback and softcover)
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export function getSynonyms(term, tag = undefined, subfieldCode = undefined, preferredLanguage = undefined, ignoreCase = true, relevantLanguagesString = 'fin swe',) {
|
|
41
|
+
if (!term) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
//nvdebug(`WP1 CANDS: ${synonyms.length} FOR '${term}'`, debugDev);
|
|
45
|
+
const relevantLanguges = relevantLanguagesString.split(/\s+/u);
|
|
46
|
+
const normalizedTerm = ignoreCase ? term.toLowerCase() : term;
|
|
47
|
+
const synonymsWithTag = tag ? synonyms.filter(s => s.tags.includes(tag)) : synonyms;
|
|
48
|
+
if (synonymsWithTag.length === 0) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
//nvdebug(`WP2 (FILTER ${tag}) CANDS: ${synonymsWithTag.length}`, debugDev);
|
|
52
|
+
const synonymsWithTagAndCode = subfieldCode ? synonymsWithTag.filter(s => s.code === subfieldCode) : synonymsWithTag;
|
|
53
|
+
//nvdebug(`WP3 (FILTER $${subfieldCode}) CANDS: ${synonymsWithTagAndCode.length}:\n${JSON.stringify(synonymsWithTagAndCode)}`, debugDev);
|
|
54
|
+
const matchingSynonyms = synonymsWithTagAndCode.filter(s => termAndLangMatch(s));
|
|
55
|
+
|
|
56
|
+
if (preferredLanguage && matchingSynonyms.length > 0) {
|
|
57
|
+
//console.log(`USING PREFERRED LANG '${preferredLanguage}' for TERM '${term}':\n${JSON.stringify(matchingSynonyms)}`, debugDev);
|
|
58
|
+
return matchingSynonyms.map(s => s[preferredLanguage]);
|
|
59
|
+
}
|
|
60
|
+
return matchingSynonyms;
|
|
61
|
+
|
|
62
|
+
function termAndLangMatch(synonym) {
|
|
63
|
+
if (relevantLanguges.includes('fin')) {
|
|
64
|
+
if (ignoreCase && synonym.fin.toLowerCase() === normalizedTerm ) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (!ignoreCase && synonym.fin === term) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (relevantLanguges.includes('swe')) {
|
|
73
|
+
if (ignoreCase && synonym.swe.toLowerCase() === normalizedTerm ) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (!ignoreCase && synonym.swe === term) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function getSynonym(tag, subfieldCode, originalValue) {
|
|
85
|
+
const finnishForm = getSynonyms(originalValue, tag, subfieldCode, 'fin');
|
|
86
|
+
if (finnishForm.length === 1) {
|
|
87
|
+
//nvdebug(`FINNISH FORM FOR ${tag}$${subfieldCode}: '${finnishForm[0]}'`, debugDev);
|
|
88
|
+
return finnishForm[0];
|
|
89
|
+
}
|
|
90
|
+
return originalValue;
|
|
91
|
+
}
|
|
92
|
+
|
|
23
93
|
export function normalizeForSamenessCheck(tag, subfieldCode, originalValue) {
|
|
24
94
|
// NB! These work only for non-repeatable subfields!
|
|
25
95
|
// Repeatable subfields are currently handled in mergeSubfields.js. Only non-repeatable subfields block field merge,
|
|
26
|
-
// (This split is suboptiomal... Minimum fix: make this
|
|
27
|
-
|
|
96
|
+
// (This split is suboptiomal... Minimum fix: make this distinction cleaner...)
|
|
97
|
+
|
|
98
|
+
//nvdebug(`TRYING TO DO ${tag}$${subfieldCode} '${originalValue}'`, debugDev);
|
|
99
|
+
originalValue = getSynonym(tag, subfieldCode, originalValue);
|
|
100
|
+
|
|
101
|
+
if (subfieldCode === 'a' && ['100', '600', '700', '800'].includes(tag)) { // "Etunimi Sukunimi"...
|
|
28
102
|
return normalizePersonalName(originalValue);
|
|
29
103
|
}
|
|
30
104
|
|
package/src/merge-fields.test.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
2
|
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
3
|
import validatorFactory from './merge-fields/index.js';
|
|
4
4
|
import {READERS} from '@natlibfi/fixura';
|
|
5
5
|
import generateTests from '@natlibfi/fixugen';
|
|
6
6
|
import createDebugLogger from 'debug';
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
|
|
9
9
|
generateTests({
|
|
10
10
|
callback,
|
|
@@ -30,13 +30,8 @@ async function testValidatorFactory() {
|
|
|
30
30
|
assert.equal(typeof validator.validate, 'function');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
async function callback({getFixture,
|
|
34
|
-
|
|
35
|
-
debug('TEST SKIPPED!');
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
nvdebug(`TAG PATTERN: ${tagPattern}`);
|
|
33
|
+
async function callback({getFixture, fix = false, tagPattern = false}) {
|
|
34
|
+
debug(`Run test using tag pattern ${tagPattern}`);
|
|
40
35
|
|
|
41
36
|
const validator = await validatorFactory(tagPattern);
|
|
42
37
|
const record = new MarcRecord(getFixture('record.json'));
|
|
@@ -51,5 +46,5 @@ async function callback({getFixture, enabled = true, fix = false, tagPattern = f
|
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
await validator.fix(record);
|
|
54
|
-
assert.deepEqual(record, expectedResult);
|
|
49
|
+
assert.deepEqual(record, new MarcRecord(expectedResult));
|
|
55
50
|
}
|
|
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
|
|
|
3
3
|
import validatorFactory from './mergeField500Lisapainokset.js';
|
|
4
4
|
import {READERS} from '@natlibfi/fixura';
|
|
5
5
|
import generateTests from '@natlibfi/fixugen';
|
|
6
|
-
import createDebugLogger from 'debug';
|
|
6
|
+
//import createDebugLogger from 'debug';
|
|
7
7
|
|
|
8
8
|
generateTests({
|
|
9
9
|
callback,
|
|
@@ -19,7 +19,7 @@ generateTests({
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeField500Lisapainokset:test');
|
|
22
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeField500Lisapainokset:test');
|
|
23
23
|
|
|
24
24
|
async function testValidatorFactory() {
|
|
25
25
|
const validator = await validatorFactory();
|
|
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
|
|
|
29
29
|
assert.equal(typeof validator.validate, 'function');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async function callback({getFixture,
|
|
33
|
-
if (enabled === false) {
|
|
34
|
-
debug('TEST SKIPPED!');
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
32
|
+
async function callback({getFixture, fix = false}) {
|
|
38
33
|
const validator = await validatorFactory();
|
|
39
34
|
const record = new MarcRecord(getFixture('record.json'));
|
|
40
35
|
const expectedResult = getFixture('expectedResult.json');
|
|
@@ -11,11 +11,12 @@ import {fieldFixPunctuation, fieldStripPunctuation} from './punctuation2.js';
|
|
|
11
11
|
import {fieldToString, nvdebug} from './utils.js';
|
|
12
12
|
import {sortAdjacentSubfields} from './sortSubfields.js';
|
|
13
13
|
import {sortAdjacentRelatorTerms, tagToRelatorTermSubfieldCode} from './sortRelatorTerms.js';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
import createDebugLogger from 'debug';
|
|
15
|
+
|
|
16
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');
|
|
17
17
|
//const debugData = debug.extend('data');
|
|
18
|
-
|
|
18
|
+
const debugDev = debug.extend('dev');
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
export default function () {
|
|
21
22
|
|
|
@@ -80,31 +81,31 @@ function copyRelatorSubfields(fromField, toField) {
|
|
|
80
81
|
|
|
81
82
|
function mergeRelatorTermFields(record, fix = false) {
|
|
82
83
|
// NV: 111/711, 751 and 752 where so rare that I did not add them here. Can't remember why I skipped 6XX and 8XX...
|
|
83
|
-
let fields = record.get('(?:[17][01]0|720)');
|
|
84
|
+
let fields = record.get('(?:[17][01]0|720)');
|
|
84
85
|
let result = [];
|
|
85
86
|
const comparisonFieldsAsString = fields.map(f => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));
|
|
86
87
|
|
|
87
|
-
nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found
|
|
88
|
+
nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`, debugDev);
|
|
88
89
|
for(let i=0; i < fields.length-1; i++) {
|
|
89
90
|
let currField = fields[i];
|
|
90
91
|
if (currField.deleted) {
|
|
91
92
|
continue;
|
|
92
93
|
}
|
|
93
|
-
nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}
|
|
94
|
+
nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`, debugDev);
|
|
94
95
|
for (let j=i+1; j < fields.length; j++) {
|
|
95
|
-
nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}
|
|
96
|
+
nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`, debugDev);
|
|
96
97
|
let mergableField = fields[j];
|
|
97
98
|
// Skip 1/7 from 1XX/7XX for similarity check:
|
|
98
99
|
if ( comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {
|
|
99
|
-
nvdebug(" NOT PAIR");
|
|
100
|
+
nvdebug(" NOT PAIR", debugDev);
|
|
100
101
|
continue;
|
|
101
102
|
}
|
|
102
103
|
if (mergableField.deleted) {
|
|
103
|
-
nvdebug(" DELETED");
|
|
104
|
+
nvdebug(" DELETED", debugDev);
|
|
104
105
|
continue;
|
|
105
106
|
}
|
|
106
107
|
const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;
|
|
107
|
-
nvdebug(str);
|
|
108
|
+
nvdebug(str, debugDev);
|
|
108
109
|
|
|
109
110
|
if(!result.includes(str)) {
|
|
110
111
|
result.push(str)
|