@natlibfi/marc-record-validators-melinda 11.6.7 → 12.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/melinda-node-tests.yml +1 -1
- package/dist/access-rights.js +63 -91
- package/dist/access-rights.js.map +7 -1
- package/dist/access-rights.test.js +137 -0
- package/dist/access-rights.test.js.map +7 -0
- package/dist/addMissingField041.js +21 -53
- package/dist/addMissingField041.js.map +7 -1
- package/dist/addMissingField041.test.js +39 -0
- package/dist/addMissingField041.test.js.map +7 -0
- package/dist/addMissingField336.js +99 -191
- package/dist/addMissingField336.js.map +7 -1
- package/dist/addMissingField336.test.js +39 -0
- package/dist/addMissingField336.test.js.map +7 -0
- package/dist/addMissingField337.js +63 -132
- package/dist/addMissingField337.js.map +7 -1
- package/dist/addMissingField337.test.js +39 -0
- package/dist/addMissingField337.test.js.map +7 -0
- package/dist/addMissingField338.js +147 -253
- package/dist/addMissingField338.js.map +7 -1
- package/dist/addMissingField338.test.js +39 -0
- package/dist/addMissingField338.test.js.map +7 -0
- package/dist/cyrillux-usemarcon-replacement.js +119 -272
- package/dist/cyrillux-usemarcon-replacement.js.map +7 -1
- package/dist/cyrillux-usemarcon-replacement.test.js +46 -0
- package/dist/cyrillux-usemarcon-replacement.test.js.map +7 -0
- package/dist/cyrillux.js +119 -223
- package/dist/cyrillux.js.map +7 -1
- package/dist/cyrillux.test.js +39 -0
- package/dist/cyrillux.test.js.map +7 -0
- package/dist/disambiguateSeriesStatements.js +40 -81
- package/dist/disambiguateSeriesStatements.js.map +7 -1
- package/dist/disambiguateSeriesStatements.test.js +44 -0
- package/dist/disambiguateSeriesStatements.test.js.map +7 -0
- package/dist/double-commas.js +7 -14
- package/dist/double-commas.js.map +7 -1
- package/dist/double-commas.test.js +48 -0
- package/dist/double-commas.test.js.map +7 -0
- package/dist/duplicates-ind1.js +10 -31
- package/dist/duplicates-ind1.js.map +7 -1
- package/dist/duplicates-ind1.test.js +40 -0
- package/dist/duplicates-ind1.test.js.map +7 -0
- package/dist/empty-fields.js +10 -22
- package/dist/empty-fields.js.map +7 -1
- package/dist/empty-fields.test.js +129 -0
- package/dist/empty-fields.test.js.map +7 -0
- package/dist/ending-punctuation-conf.js +871 -769
- package/dist/ending-punctuation-conf.js.map +7 -1
- package/dist/ending-punctuation.js +84 -167
- package/dist/ending-punctuation.js.map +7 -1
- package/dist/ending-punctuation.test.js +2290 -0
- package/dist/ending-punctuation.test.js.map +7 -0
- package/dist/ending-whitespace.js +10 -35
- package/dist/ending-whitespace.js.map +7 -1
- package/dist/ending-whitespace.test.js +38 -0
- package/dist/ending-whitespace.test.js.map +7 -0
- package/dist/field-008-18-34-character-groups.js +40 -125
- package/dist/field-008-18-34-character-groups.js.map +7 -1
- package/dist/field-008-18-34-character-groups.test.js +45 -0
- package/dist/field-008-18-34-character-groups.test.js.map +7 -0
- package/dist/field-505-separators.js +19 -39
- package/dist/field-505-separators.js.map +7 -1
- package/dist/field-505-separators.test.js +45 -0
- package/dist/field-505-separators.test.js.map +7 -0
- package/dist/field-521-fix.js +19 -47
- package/dist/field-521-fix.js.map +7 -1
- package/dist/field-521-fix.test.js +44 -0
- package/dist/field-521-fix.test.js.map +7 -0
- package/dist/field-exclusion.js +37 -91
- package/dist/field-exclusion.js.map +7 -1
- package/dist/field-exclusion.test.js +821 -0
- package/dist/field-exclusion.test.js.map +7 -0
- package/dist/field-structure.js +52 -104
- package/dist/field-structure.js.map +7 -1
- package/dist/field-structure.test.js +587 -0
- package/dist/field-structure.test.js.map +7 -0
- package/dist/field33XUtils.js +119 -503
- package/dist/field33XUtils.js.map +7 -1
- package/dist/fields-present.js +11 -23
- package/dist/fields-present.js.map +7 -1
- package/dist/fields-present.test.js +95 -0
- package/dist/fields-present.test.js.map +7 -0
- package/dist/fix-33X.js +393 -431
- package/dist/fix-33X.js.map +7 -1
- package/dist/fix-33X.test.js +39 -0
- package/dist/fix-33X.test.js.map +7 -0
- package/dist/fix-country-codes.js +20 -50
- package/dist/fix-country-codes.js.map +7 -1
- package/dist/fix-country-codes.test.js +44 -0
- package/dist/fix-country-codes.test.js.map +7 -0
- package/dist/fix-language-codes.js +23 -53
- package/dist/fix-language-codes.js.map +7 -1
- package/dist/fix-language-codes.test.js +38 -0
- package/dist/fix-language-codes.test.js.map +7 -0
- package/dist/fixRelatorTerms.js +82 -209
- package/dist/fixRelatorTerms.js.map +7 -1
- package/dist/fixRelatorTerms.test.js +44 -0
- package/dist/fixRelatorTerms.test.js.map +7 -0
- package/dist/fixed-fields.js +21 -30
- package/dist/fixed-fields.js.map +7 -1
- package/dist/fixed-fields.test.js +87 -0
- package/dist/fixed-fields.test.js.map +7 -0
- package/dist/identical-fields.js +8 -24
- package/dist/identical-fields.js.map +7 -1
- package/dist/identical-fields.test.js +119 -0
- package/dist/identical-fields.test.js.map +7 -0
- package/dist/index.js +119 -413
- package/dist/index.js.map +7 -1
- package/dist/indicator-fixes.js +57 -95
- package/dist/indicator-fixes.js.map +7 -1
- package/dist/indicator-fixes.test.js +42 -0
- package/dist/indicator-fixes.test.js.map +7 -0
- package/dist/isbn-issn.js +66 -126
- package/dist/isbn-issn.js.map +7 -1
- package/dist/isbn-issn.test.js +398 -0
- package/dist/isbn-issn.test.js.map +7 -0
- package/dist/item-language.js +32 -65
- package/dist/item-language.js.map +7 -1
- package/dist/item-language.test.js +322 -0
- package/dist/item-language.test.js.map +7 -0
- package/dist/melindaCustomMergeFields.js +5182 -11233
- package/dist/melindaCustomMergeFields.js.map +7 -1
- package/dist/merge-fields/controlSubfields.js +75 -142
- package/dist/merge-fields/controlSubfields.js.map +7 -1
- package/dist/merge-fields/counterpartField.js +182 -379
- package/dist/merge-fields/counterpartField.js.map +7 -1
- package/dist/merge-fields/index.js +15 -49
- package/dist/merge-fields/index.js.map +7 -1
- package/dist/merge-fields/mergableIndicator.js +18 -51
- package/dist/merge-fields/mergableIndicator.js.map +7 -1
- package/dist/merge-fields/mergableTag.js +78 -30
- package/dist/merge-fields/mergableTag.js.map +7 -1
- package/dist/merge-fields/mergeConfig.js +66 -171
- package/dist/merge-fields/mergeConfig.js.map +7 -1
- package/dist/merge-fields/mergeConstraints.js +323 -1214
- package/dist/merge-fields/mergeConstraints.js.map +7 -1
- package/dist/merge-fields/mergeField.js +47 -111
- package/dist/merge-fields/mergeField.js.map +7 -1
- package/dist/merge-fields/mergeIndicator.js +64 -118
- package/dist/merge-fields/mergeIndicator.js.map +7 -1
- package/dist/merge-fields/mergeOrAddPostprocess.js +14 -38
- package/dist/merge-fields/mergeOrAddPostprocess.js.map +7 -1
- package/dist/merge-fields/mergeOrAddSubfield.js +62 -104
- package/dist/merge-fields/mergeOrAddSubfield.js.map +7 -1
- package/dist/merge-fields/mergeSubfield.js +47 -95
- package/dist/merge-fields/mergeSubfield.js.map +7 -1
- package/dist/merge-fields/removeDuplicateSubfields.js +18 -31
- package/dist/merge-fields/removeDuplicateSubfields.js.map +7 -1
- package/dist/merge-fields/worldKnowledge.js +15 -40
- package/dist/merge-fields/worldKnowledge.js.map +7 -1
- package/dist/merge-fields.test.js +44 -0
- package/dist/merge-fields.test.js.map +7 -0
- package/dist/mergeField500Lisapainokset.js +28 -57
- package/dist/mergeField500Lisapainokset.js.map +7 -1
- package/dist/mergeField500Lisapainokset.test.js +44 -0
- package/dist/mergeField500Lisapainokset.test.js.map +7 -0
- package/dist/mergeRelatorTermFields.js +33 -69
- package/dist/mergeRelatorTermFields.js.map +7 -1
- package/dist/mergeRelatorTermFields.test.js +44 -0
- package/dist/mergeRelatorTermFields.test.js.map +7 -0
- package/dist/modernize-502.js +23 -55
- package/dist/modernize-502.js.map +7 -1
- package/dist/modernize-502.test.js +38 -0
- package/dist/modernize-502.test.js.map +7 -0
- package/dist/multiple-subfield-0.js +23 -48
- package/dist/multiple-subfield-0.js.map +7 -1
- package/dist/multiple-subfield-0.test.js +44 -0
- package/dist/multiple-subfield-0.test.js.map +7 -0
- package/dist/non-breaking-space.js +11 -32
- package/dist/non-breaking-space.js.map +7 -1
- package/dist/non-breaking-space.test.js +38 -0
- package/dist/non-breaking-space.test.js.map +7 -0
- package/dist/normalize-dashes.js +18 -37
- package/dist/normalize-dashes.js.map +7 -1
- package/dist/normalize-dashes.test.js +44 -0
- package/dist/normalize-dashes.test.js.map +7 -0
- package/dist/normalize-identifiers.js +54 -140
- package/dist/normalize-identifiers.js.map +7 -1
- package/dist/normalize-identifiers.test.js +44 -0
- package/dist/normalize-identifiers.test.js.map +7 -0
- package/dist/normalize-qualifying-information.js +23 -48
- package/dist/normalize-qualifying-information.js.map +7 -1
- package/dist/normalize-qualifying-information.test.js +44 -0
- package/dist/normalize-qualifying-information.test.js.map +7 -0
- package/dist/normalize-utf8-diacritics.js +19 -105
- package/dist/normalize-utf8-diacritics.js.map +7 -1
- package/dist/normalize-utf8-diacritics.test.js +44 -0
- package/dist/normalize-utf8-diacritics.test.js.map +7 -0
- package/dist/normalizeFieldForComparison.js +67 -158
- package/dist/normalizeFieldForComparison.js.map +7 -1
- package/dist/normalizeSubfieldValueForComparison.js +37 -77
- package/dist/normalizeSubfieldValueForComparison.js.map +7 -1
- package/dist/prepublicationUtils.js +58 -111
- package/dist/prepublicationUtils.js.map +7 -1
- package/dist/punctuation/index.js +56 -72
- package/dist/punctuation/index.js.map +7 -1
- package/dist/punctuation/rules/aut.js +372 -331
- package/dist/punctuation/rules/aut.js.map +7 -1
- package/dist/punctuation/rules/bib.js +420 -373
- package/dist/punctuation/rules/bib.js.map +7 -1
- package/dist/punctuation/rules/index.js +7 -21
- package/dist/punctuation/rules/index.js.map +7 -1
- package/dist/punctuation.test.js +44 -0
- package/dist/punctuation.test.js.map +7 -0
- package/dist/punctuation2.js +251 -800
- package/dist/punctuation2.js.map +7 -1
- package/dist/punctuation2.test.js +44 -0
- package/dist/punctuation2.test.js.map +7 -0
- package/dist/reindexSubfield6OccurenceNumbers.js +61 -96
- package/dist/reindexSubfield6OccurenceNumbers.js.map +7 -1
- package/dist/reindexSubfield6OccurenceNumbers.test.js +44 -0
- package/dist/reindexSubfield6OccurenceNumbers.test.js.map +7 -0
- package/dist/removeDuplicateDataFields.js +102 -202
- package/dist/removeDuplicateDataFields.js.map +7 -1
- package/dist/removeDuplicateDataFields.test.js +44 -0
- package/dist/removeDuplicateDataFields.test.js.map +7 -0
- package/dist/removeInferiorDataFields.js +103 -227
- package/dist/removeInferiorDataFields.js.map +7 -1
- package/dist/removeInferiorDataFields.test.js +44 -0
- package/dist/removeInferiorDataFields.test.js.map +7 -0
- package/dist/resolvable-ext-references-melinda.js +25 -60
- package/dist/resolvable-ext-references-melinda.js.map +7 -1
- package/dist/resolvable-ext-references-melinda.test.js +160 -0
- package/dist/resolvable-ext-references-melinda.test.js.map +7 -0
- package/dist/resolveOrphanedSubfield6s.js +33 -64
- package/dist/resolveOrphanedSubfield6s.js.map +7 -1
- package/dist/resolveOrphanedSubfield6s.test.js +44 -0
- package/dist/resolveOrphanedSubfield6s.test.js.map +7 -0
- package/dist/sanitize-vocabulary-source-codes.js +27 -55
- package/dist/sanitize-vocabulary-source-codes.js.map +7 -1
- package/dist/sanitize-vocabulary-source-codes.test.js +45 -0
- package/dist/sanitize-vocabulary-source-codes.test.js.map +7 -0
- package/dist/sort-tags.js +13 -25
- package/dist/sort-tags.js.map +7 -1
- package/dist/sort-tags.test.js +261 -0
- package/dist/sort-tags.test.js.map +7 -0
- package/dist/sortFields.js +152 -222
- package/dist/sortFields.js.map +7 -1
- package/dist/sortFields.test.js +44 -0
- package/dist/sortFields.test.js.map +7 -0
- package/dist/sortRelatorTerms.js +30 -68
- package/dist/sortRelatorTerms.js.map +7 -1
- package/dist/sortRelatorTerms.test.js +44 -0
- package/dist/sortRelatorTerms.test.js.map +7 -0
- package/dist/sortSubfields.js +102 -255
- package/dist/sortSubfields.js.map +7 -1
- package/dist/sortSubfields.test.js +44 -0
- package/dist/sortSubfields.test.js.map +7 -0
- package/dist/stripPunctuation.js +13 -36
- package/dist/stripPunctuation.js.map +7 -1
- package/dist/stripPunctuation.test.js +44 -0
- package/dist/stripPunctuation.test.js.map +7 -0
- package/dist/subfield-exclusion.js +28 -75
- package/dist/subfield-exclusion.js.map +7 -1
- package/dist/subfield-exclusion.test.js +471 -0
- package/dist/subfield-exclusion.test.js.map +7 -0
- package/dist/subfield6Utils.js +107 -269
- package/dist/subfield6Utils.js.map +7 -1
- package/dist/subfield8Utils.js +26 -50
- package/dist/subfield8Utils.js.map +7 -1
- package/dist/subfieldValueNormalizations.js +40 -74
- package/dist/subfieldValueNormalizations.js.map +7 -1
- package/dist/subfieldValueNormalizations.test.js +45 -0
- package/dist/subfieldValueNormalizations.test.js.map +7 -0
- package/dist/sync-007-and-300.js +22 -53
- package/dist/sync-007-and-300.js.map +7 -1
- package/dist/sync-007-and-300.test.js +44 -0
- package/dist/sync-007-and-300.test.js.map +7 -0
- package/dist/translate-terms.js +67 -155
- package/dist/translate-terms.js.map +7 -1
- package/dist/translate-terms.test.js +44 -0
- package/dist/translate-terms.test.js.map +7 -0
- package/dist/typeOfDate-008.js +10 -25
- package/dist/typeOfDate-008.js.map +7 -1
- package/dist/typeOfDate-008.test.js +40 -0
- package/dist/typeOfDate-008.test.js.map +7 -0
- package/dist/unicode-decomposition.js +94 -107
- package/dist/unicode-decomposition.js.map +7 -1
- package/dist/unicode-decomposition.test.js +94 -0
- package/dist/unicode-decomposition.test.js.map +7 -0
- package/dist/update-field-540.js +30 -75
- package/dist/update-field-540.js.map +7 -1
- package/dist/update-field-540.test.js +44 -0
- package/dist/update-field-540.test.js.map +7 -0
- package/dist/urn.js +55 -128
- package/dist/urn.js.map +7 -1
- package/dist/urn.test.js +44 -0
- package/dist/urn.test.js.map +7 -0
- package/dist/utils.js +72 -126
- package/dist/utils.js.map +7 -1
- package/eslint.config.mjs +1 -2
- package/package.json +21 -93
- package/src/access-rights.js +1 -1
- package/src/{access-rights.spec.js → access-rights.test.js} +9 -10
- package/src/addMissingField041.js +1 -1
- package/src/{addMissingField336.spec.js → addMissingField041.test.js} +13 -14
- package/src/addMissingField336.js +3 -3
- package/src/{addMissingField041.spec.js → addMissingField336.test.js} +13 -14
- package/src/addMissingField337.js +2 -2
- package/src/{addMissingField337.spec.js → addMissingField337.test.js} +13 -14
- package/src/addMissingField338.js +2 -2
- package/src/{addMissingField338.spec.js → addMissingField338.test.js} +13 -14
- package/src/cyrillux-usemarcon-replacement.js +18 -18
- package/src/cyrillux-usemarcon-replacement.test.js +55 -0
- package/src/cyrillux.js +19 -12
- package/src/{cyrillux.spec.js → cyrillux.test.js} +13 -14
- package/src/disambiguateSeriesStatements.js +2 -2
- package/src/{disambiguateSeriesStatements.spec.js → disambiguateSeriesStatements.test.js} +12 -13
- package/src/double-commas.js +1 -1
- package/src/{double-commas.spec.js → double-commas.test.js} +9 -11
- package/src/duplicates-ind1.js +1 -1
- package/src/{duplicates-ind1.spec.js → duplicates-ind1.test.js} +12 -13
- package/src/{empty-fields.spec.js → empty-fields.test.js} +11 -13
- package/src/ending-punctuation.js +1 -1
- package/src/{ending-punctuation.spec.js → ending-punctuation.test.js} +172 -173
- package/src/{ending-whitespace.spec.js → ending-whitespace.test.js} +12 -13
- package/src/field-008-18-34-character-groups.js +2 -2
- package/src/{field-008-18-34-character-groups.spec.js → field-008-18-34-character-groups.test.js} +13 -13
- package/src/field-505-separators.js +3 -3
- package/src/{field-505-separators.spec.js → field-505-separators.test.js} +16 -14
- package/src/field-521-fix.js +2 -2
- package/src/{field-521-fix.spec.js → field-521-fix.test.js} +12 -13
- package/src/field-exclusion.js +1 -1
- package/src/{field-exclusion.spec.js → field-exclusion.test.js} +60 -57
- package/src/{field-structure.spec.js → field-structure.test.js} +29 -29
- package/src/{fields-present.spec.js → fields-present.test.js} +12 -15
- package/src/fix-33X.js +4 -4
- package/src/{fix-33X.spec.js → fix-33X.test.js} +13 -14
- package/src/fix-country-codes.js +1 -1
- package/src/{fix-country-codes.spec.js → fix-country-codes.test.js} +12 -13
- package/src/fix-language-codes.js +5 -5
- package/src/{fix-language-codes.spec.js → fix-language-codes.test.js} +12 -13
- package/src/fixRelatorTerms.js +5 -5
- package/src/{fixRelatorTerms.spec.js → fixRelatorTerms.test.js} +13 -13
- package/src/{fixed-fields.spec.js → fixed-fields.test.js} +11 -14
- package/src/identical-fields.js +1 -1
- package/src/{identical-fields.spec.js → identical-fields.test.js} +9 -11
- package/src/index.js +58 -58
- package/src/indicator-fixes.js +3 -3
- package/src/{indicator-fixes.spec.js → indicator-fixes.test.js} +9 -12
- package/src/isbn-issn.js +1 -1
- package/src/{isbn-issn.spec.js → isbn-issn.test.js} +20 -22
- package/src/{item-language.spec.js → item-language.test.js} +21 -22
- package/src/merge-fields/controlSubfields.js +1 -1
- package/src/merge-fields/counterpartField.js +8 -9
- package/src/merge-fields/index.js +1 -1
- package/src/merge-fields/mergableIndicator.js +1 -1
- package/src/merge-fields/mergeField.js +6 -6
- package/src/merge-fields/mergeIndicator.js +1 -1
- package/src/merge-fields/mergeOrAddPostprocess.js +4 -4
- package/src/merge-fields/mergeOrAddSubfield.js +2 -2
- package/src/merge-fields/mergeSubfield.js +4 -4
- package/src/merge-fields/removeDuplicateSubfields.js +2 -2
- package/src/{merge-fields.spec.js → merge-fields.test.js} +12 -13
- package/src/{mergeField500Lisapainokset.spec.js → mergeField500Lisapainokset.test.js} +12 -13
- package/src/mergeRelatorTermFields.js +5 -7
- package/src/{mergeRelatorTermFields.spec.js → mergeRelatorTermFields.test.js} +12 -13
- package/src/modernize-502.js +1 -1
- package/src/{modernize-502.spec.js → modernize-502.test.js} +12 -13
- package/src/multiple-subfield-0.js +3 -3
- package/src/{multiple-subfield-0.spec.js → multiple-subfield-0.test.js} +13 -13
- package/src/{non-breaking-space.spec.js → non-breaking-space.test.js} +12 -13
- package/src/normalize-dashes.js +2 -2
- package/src/{normalize-dashes.spec.js → normalize-dashes.test.js} +12 -13
- package/src/normalize-identifiers.js +1 -1
- package/src/{normalize-identifiers.spec.js → normalize-identifiers.test.js} +12 -13
- package/src/normalize-qualifying-information.js +2 -2
- package/src/{normalize-qualifying-information.spec.js → normalize-qualifying-information.test.js} +12 -13
- package/src/normalize-utf8-diacritics.js +2 -2
- package/src/{normalize-utf8-diacritics.spec.js → normalize-utf8-diacritics.test.js} +13 -13
- package/src/normalizeFieldForComparison.js +6 -6
- package/src/normalizeSubfieldValueForComparison.js +1 -1
- package/src/prepublicationUtils.js +4 -4
- package/src/punctuation/index.js +1 -1
- package/src/punctuation/rules/index.js +2 -2
- package/src/{punctuation.spec.js → punctuation.test.js} +12 -13
- package/src/punctuation2.js +4 -4
- package/src/{punctuation2.spec.js → punctuation2.test.js} +12 -13
- package/src/reindexSubfield6OccurenceNumbers.js +5 -7
- package/src/{reindexSubfield6OccurenceNumbers.spec.js → reindexSubfield6OccurenceNumbers.test.js} +12 -13
- package/src/removeDuplicateDataFields.js +11 -19
- package/src/{removeDuplicateDataFields.spec.js → removeDuplicateDataFields.test.js} +12 -13
- package/src/removeInferiorDataFields.js +11 -11
- package/src/{removeInferiorDataFields.spec.js → removeInferiorDataFields.test.js} +13 -13
- package/src/resolvable-ext-references-melinda.js +1 -1
- package/src/{resolvable-ext-references-melinda.spec.js → resolvable-ext-references-melinda.test.js} +42 -27
- package/src/resolveOrphanedSubfield6s.js +5 -5
- package/src/{resolveOrphanedSubfield6s.spec.js → resolveOrphanedSubfield6s.test.js} +13 -13
- package/src/sanitize-vocabulary-source-codes.js +4 -4
- package/src/{sanitize-vocabulary-source-codes.spec.js → sanitize-vocabulary-source-codes.test.js} +16 -14
- package/src/{sort-tags.spec.js → sort-tags.test.js} +9 -11
- package/src/sortFields.js +4 -4
- package/src/{sortFields.spec.js → sortFields.test.js} +12 -13
- package/src/sortRelatorTerms.js +3 -3
- package/src/{sortRelatorTerms.spec.js → sortRelatorTerms.test.js} +13 -13
- package/src/sortSubfields.js +1 -1
- package/src/{sortSubfields.spec.js → sortSubfields.test.js} +13 -13
- package/src/stripPunctuation.js +3 -3
- package/src/{stripPunctuation.spec.js → stripPunctuation.test.js} +13 -13
- package/src/subfield-exclusion.js +1 -1
- package/src/{subfield-exclusion.spec.js → subfield-exclusion.test.js} +45 -36
- package/src/subfield6Utils.js +6 -10
- package/src/subfield8Utils.js +4 -4
- package/src/subfieldValueNormalizations.js +3 -3
- package/src/{subfieldValueNormalizations.spec.js → subfieldValueNormalizations.test.js} +18 -14
- package/src/sync-007-and-300.js +2 -2
- package/src/{sync-007-and-300.spec.js → sync-007-and-300.test.js} +13 -13
- package/src/translate-terms.js +3 -3
- package/src/{translate-terms.spec.js → translate-terms.test.js} +13 -13
- package/src/{typeOfDate-008.spec.js → typeOfDate-008.test.js} +12 -13
- package/src/{unicode-decomposition.spec.js → unicode-decomposition.test.js} +10 -16
- package/src/update-field-540.js +2 -2
- package/src/{update-field-540.spec.js → update-field-540.test.js} +13 -10
- package/src/urn.js +2 -2
- package/src/{urn.spec.js → urn.test.js} +12 -13
- package/src/utils.js +3 -3
- package/test-fixtures/field-505-separators/03/expectedResult.json +3 -1
- package/test-fixtures/field-505-separators/03/record.json +3 -0
- package/test-fixtures/normalize-subfield-value/01/metadata.json +4 -1
- package/test-fixtures/normalize-subfield-value/01/record.json +3 -0
- package/test-fixtures/normalize-subfield-value/02/expectedResult.json +3 -1
- package/test-fixtures/normalize-subfield-value/02/metadata.json +2 -1
- package/test-fixtures/normalize-subfield-value/02/record.json +3 -0
- package/test-fixtures/sanitize-vocabulary-source-codes/f03/expectedResult.json +3 -1
- package/test-fixtures/sanitize-vocabulary-source-codes/f04/expectedResult.json +3 -1
- package/test-fixtures/sanitize-vocabulary-source-codes/v04/metadata.json +1 -4
- package/test-fixtures/sanitize-vocabulary-source-codes/v04/record.json +1 -1
- package/dist/access-rights.spec.js +0 -195
- package/dist/access-rights.spec.js.map +0 -1
- package/dist/addMissingField041.spec.js +0 -45
- package/dist/addMissingField041.spec.js.map +0 -1
- package/dist/addMissingField336.spec.js +0 -45
- package/dist/addMissingField336.spec.js.map +0 -1
- package/dist/addMissingField337.spec.js +0 -43
- package/dist/addMissingField337.spec.js.map +0 -1
- package/dist/addMissingField338.spec.js +0 -45
- package/dist/addMissingField338.spec.js.map +0 -1
- package/dist/cyrillux-usemarcon-replacement.spec.js +0 -45
- package/dist/cyrillux-usemarcon-replacement.spec.js.map +0 -1
- package/dist/cyrillux.spec.js +0 -46
- package/dist/cyrillux.spec.js.map +0 -1
- package/dist/disambiguateSeriesStatements.spec.js +0 -51
- package/dist/disambiguateSeriesStatements.spec.js.map +0 -1
- package/dist/double-commas.spec.js +0 -73
- package/dist/double-commas.spec.js.map +0 -1
- package/dist/duplicates-ind1.spec.js +0 -45
- package/dist/duplicates-ind1.spec.js.map +0 -1
- package/dist/empty-fields.spec.js +0 -118
- package/dist/empty-fields.spec.js.map +0 -1
- package/dist/ending-punctuation.spec.js +0 -2654
- package/dist/ending-punctuation.spec.js.map +0 -1
- package/dist/ending-whitespace.spec.js +0 -42
- package/dist/ending-whitespace.spec.js.map +0 -1
- package/dist/field-008-18-34-character-groups.spec.js +0 -51
- package/dist/field-008-18-34-character-groups.spec.js.map +0 -1
- package/dist/field-505-separators.spec.js +0 -51
- package/dist/field-505-separators.spec.js.map +0 -1
- package/dist/field-521-fix.spec.js +0 -51
- package/dist/field-521-fix.spec.js.map +0 -1
- package/dist/field-exclusion.spec.js +0 -1054
- package/dist/field-exclusion.spec.js.map +0 -1
- package/dist/field-structure.spec.js +0 -535
- package/dist/field-structure.spec.js.map +0 -1
- package/dist/fields-present.spec.js +0 -121
- package/dist/fields-present.spec.js.map +0 -1
- package/dist/fix-33X.spec.js +0 -45
- package/dist/fix-33X.spec.js.map +0 -1
- package/dist/fix-country-codes.spec.js +0 -51
- package/dist/fix-country-codes.spec.js.map +0 -1
- package/dist/fix-language-codes.spec.js +0 -44
- package/dist/fix-language-codes.spec.js.map +0 -1
- package/dist/fixRelatorTerms.spec.js +0 -51
- package/dist/fixRelatorTerms.spec.js.map +0 -1
- package/dist/fixed-fields.spec.js +0 -140
- package/dist/fixed-fields.spec.js.map +0 -1
- package/dist/identical-fields.spec.js +0 -99
- package/dist/identical-fields.spec.js.map +0 -1
- package/dist/indicator-fixes.spec.js +0 -51
- package/dist/indicator-fixes.spec.js.map +0 -1
- package/dist/isbn-issn.spec.js +0 -595
- package/dist/isbn-issn.spec.js.map +0 -1
- package/dist/item-language.spec.js +0 -306
- package/dist/item-language.spec.js.map +0 -1
- package/dist/melindaCustomMergeFields.json +0 -5120
- package/dist/merge-fields.spec.js +0 -51
- package/dist/merge-fields.spec.js.map +0 -1
- package/dist/mergeField500Lisapainokset.spec.js +0 -51
- package/dist/mergeField500Lisapainokset.spec.js.map +0 -1
- package/dist/mergeRelatorTermFields.spec.js +0 -51
- package/dist/mergeRelatorTermFields.spec.js.map +0 -1
- package/dist/modernize-502.spec.js +0 -49
- package/dist/modernize-502.spec.js.map +0 -1
- package/dist/multiple-subfield-0.spec.js +0 -51
- package/dist/multiple-subfield-0.spec.js.map +0 -1
- package/dist/non-breaking-space.spec.js +0 -42
- package/dist/non-breaking-space.spec.js.map +0 -1
- package/dist/normalize-dashes.spec.js +0 -51
- package/dist/normalize-dashes.spec.js.map +0 -1
- package/dist/normalize-identifiers.spec.js +0 -51
- package/dist/normalize-identifiers.spec.js.map +0 -1
- package/dist/normalize-qualifying-information.spec.js +0 -51
- package/dist/normalize-qualifying-information.spec.js.map +0 -1
- package/dist/normalize-utf8-diacritics.spec.js +0 -51
- package/dist/normalize-utf8-diacritics.spec.js.map +0 -1
- package/dist/punctuation.spec.js +0 -51
- package/dist/punctuation.spec.js.map +0 -1
- package/dist/punctuation2.spec.js +0 -51
- package/dist/punctuation2.spec.js.map +0 -1
- package/dist/reindexSubfield6OccurenceNumbers.spec.js +0 -51
- package/dist/reindexSubfield6OccurenceNumbers.spec.js.map +0 -1
- package/dist/removeDuplicateDataFields.spec.js +0 -51
- package/dist/removeDuplicateDataFields.spec.js.map +0 -1
- package/dist/removeInferiorDataFields.spec.js +0 -51
- package/dist/removeInferiorDataFields.spec.js.map +0 -1
- package/dist/resolvable-ext-references-melinda.spec.js +0 -166
- package/dist/resolvable-ext-references-melinda.spec.js.map +0 -1
- package/dist/resolveOrphanedSubfield6s.spec.js +0 -51
- package/dist/resolveOrphanedSubfield6s.spec.js.map +0 -1
- package/dist/sanitize-vocabulary-source-codes.spec.js +0 -51
- package/dist/sanitize-vocabulary-source-codes.spec.js.map +0 -1
- package/dist/sort-tags.spec.js +0 -207
- package/dist/sort-tags.spec.js.map +0 -1
- package/dist/sortFields.spec.js +0 -51
- package/dist/sortFields.spec.js.map +0 -1
- package/dist/sortRelatorTerms.spec.js +0 -51
- package/dist/sortRelatorTerms.spec.js.map +0 -1
- package/dist/sortSubfields.spec.js +0 -52
- package/dist/sortSubfields.spec.js.map +0 -1
- package/dist/stripPunctuation.spec.js +0 -51
- package/dist/stripPunctuation.spec.js.map +0 -1
- package/dist/subfield-exclusion.spec.js +0 -523
- package/dist/subfield-exclusion.spec.js.map +0 -1
- package/dist/subfieldValueNormalizations.spec.js +0 -51
- package/dist/subfieldValueNormalizations.spec.js.map +0 -1
- package/dist/sync-007-and-300.spec.js +0 -51
- package/dist/sync-007-and-300.spec.js.map +0 -1
- package/dist/translate-terms.spec.js +0 -51
- package/dist/translate-terms.spec.js.map +0 -1
- package/dist/typeOfDate-008.spec.js +0 -47
- package/dist/typeOfDate-008.spec.js.map +0 -1
- package/dist/unicode-decomposition.spec.js +0 -91
- package/dist/unicode-decomposition.spec.js.map +0 -1
- package/dist/update-field-540.spec.js +0 -51
- package/dist/update-field-540.spec.js.map +0 -1
- package/dist/urn.spec.js +0 -52
- package/dist/urn.spec.js.map +0 -1
- package/src/cyrillux-usemarcon-replacement.spec.js +0 -47
|
@@ -1,127 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var _normalizeFieldForComparison = require("../normalizeFieldForComparison");
|
|
14
|
-
var _normalizeIdentifiers = require("../normalize-identifiers");
|
|
15
|
-
var _mergeConstraints = require("./mergeConstraints");
|
|
16
|
-
var _controlSubfields = require("./controlSubfields");
|
|
17
|
-
var _mergableIndicator = require("./mergableIndicator");
|
|
18
|
-
var _normalizeSubfieldValueForComparison = require("../normalizeSubfieldValueForComparison");
|
|
19
|
-
var _worldKnowledge = require("./worldKnowledge");
|
|
20
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
|
-
// For each incoming field that
|
|
22
|
-
|
|
23
|
-
// This should be done via our own normalizer:
|
|
24
|
-
|
|
25
|
-
const debug = (0, _debug.default)('@natlibfi/marc-record-validators-melinda:mergeField:counterpart');
|
|
26
|
-
//const debugData = debug.extend('data');
|
|
27
|
-
const debugDev = debug.extend('dev');
|
|
28
|
-
const irrelevantSubfieldsInNameAndTitlePartComparison = '5689';
|
|
1
|
+
import createDebugLogger from "debug";
|
|
2
|
+
import { fieldHasSubfield, fieldHasNSubfields, fieldHasMultipleSubfields, fieldToString, nvdebug, removeCopyright } from "../utils.js";
|
|
3
|
+
import { cloneAndNormalizeFieldForComparison, cloneAndRemovePunctuation } from "../normalizeFieldForComparison.js";
|
|
4
|
+
import { normalizeControlSubfieldValue } from "../normalize-identifiers.js";
|
|
5
|
+
import { getMergeConstraintsForTag } from "./mergeConstraints.js";
|
|
6
|
+
import { controlSubfieldsPermitMerge } from "./controlSubfields.js";
|
|
7
|
+
import { mergableIndicator1, mergableIndicator2 } from "./mergableIndicator.js";
|
|
8
|
+
import { partsAgree } from "../normalizeSubfieldValueForComparison.js";
|
|
9
|
+
import { normalizeForSamenessCheck, valueCarriesMeaning } from "./worldKnowledge.js";
|
|
10
|
+
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda:mergeField:counterpart");
|
|
11
|
+
const debugDev = debug.extend("dev");
|
|
12
|
+
const irrelevantSubfieldsInNameAndTitlePartComparison = "5689";
|
|
29
13
|
const counterpartRegexps = {
|
|
30
14
|
// NB! tag is from source!
|
|
31
15
|
// Note that in the normal case, all source 1XX fields have been converted to 7XX fields.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
"100": /^[17]00$/u,
|
|
17
|
+
"110": /^[17]10$/u,
|
|
18
|
+
"111": /^[17]11$/u,
|
|
19
|
+
"130": /^[17]30$/u,
|
|
20
|
+
"260": /^26[04]$/u,
|
|
21
|
+
"264": /^26[04]$/u,
|
|
22
|
+
"700": /^[17]00$/u,
|
|
23
|
+
"710": /^[17]10$/u,
|
|
24
|
+
"711": /^[17]11$/u,
|
|
25
|
+
"730": /^[17]30$/u,
|
|
42
26
|
// Hacks:
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
"940": /^[29]40$/u,
|
|
28
|
+
"973": /^[79]73$/u
|
|
45
29
|
};
|
|
46
30
|
const counterpartRegexpsSingle = {
|
|
47
31
|
// when base===source, never merge 1XX to 7XX, always 7XX to 1XX! Also, don't merge 264 to 260.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
"260": /^26[04]$/u,
|
|
33
|
+
"700": /^[17]00$/u,
|
|
34
|
+
"110": /^[17]10$/u,
|
|
35
|
+
"111": /^[17]11$/u,
|
|
36
|
+
"130": /^[17]30$/u,
|
|
53
37
|
// Hacks:
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
"940": /^[29]40$/u,
|
|
39
|
+
"973": /^[79]73$/u
|
|
56
40
|
};
|
|
57
|
-
|
|
58
|
-
/*
|
|
59
|
-
function differentPublisherSubfields(field1, field2) {
|
|
60
|
-
if (field1.tag === '260' && field2.tag === '264' && field2.ind2 === '3') {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
if (field1.tag === '264' && field1.ind2 === '3' && field2.tag === '260') {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
function splitToNameAndQualifier(value) {
|
|
41
|
+
export function splitToNameAndQualifier(value) {
|
|
71
42
|
if (value.match(/^.* \([^()]+\)$/u)) {
|
|
72
|
-
const name = value.replace(/^(.*) \([^()]+\)$/u,
|
|
73
|
-
const qualifier = value.replace(/^.* (\([^()]+\))$/u,
|
|
43
|
+
const name = value.replace(/^(.*) \([^()]+\)$/u, "$1");
|
|
44
|
+
const qualifier = value.replace(/^.* (\([^()]+\))$/u, "$1");
|
|
74
45
|
return [name, qualifier];
|
|
75
46
|
}
|
|
76
|
-
return [value,
|
|
47
|
+
return [value, void 0];
|
|
77
48
|
}
|
|
78
|
-
function splitToNameAndQualifierAndProcessName(name) {
|
|
79
|
-
//const nameOnly = name.replace(/(?: \([^)]+\)| abp?| Kustannus| Kustannus Oy|, kustannusosakeyhtiö| oyj?| ry)$/ugi, '');
|
|
49
|
+
export function splitToNameAndQualifierAndProcessName(name) {
|
|
80
50
|
const [qualifierlessName, qualifier] = splitToNameAndQualifier(name);
|
|
81
51
|
const [prefix, basename, suffix] = stripPrefixAndSuffix(qualifierlessName);
|
|
82
|
-
return {
|
|
83
|
-
name: getBestName(basename).toLowerCase(),
|
|
84
|
-
prefix,
|
|
85
|
-
suffix,
|
|
86
|
-
qualifier
|
|
87
|
-
};
|
|
52
|
+
return { name: getBestName(basename).toLowerCase(), prefix, suffix, qualifier };
|
|
88
53
|
function stripPrefixAndSuffix(companyName) {
|
|
89
|
-
const [nameOnly,
|
|
90
|
-
const [nameOnly2,
|
|
91
|
-
return [
|
|
92
|
-
}
|
|
93
|
-
function extractSuffix(
|
|
94
|
-
const nameOnly =
|
|
95
|
-
if (nameOnly ===
|
|
96
|
-
return [
|
|
54
|
+
const [nameOnly, suffix2] = extractSuffix(companyName);
|
|
55
|
+
const [nameOnly2, prefix2] = extractPrefix(nameOnly);
|
|
56
|
+
return [prefix2, nameOnly2, suffix2];
|
|
57
|
+
}
|
|
58
|
+
function extractSuffix(name2) {
|
|
59
|
+
const nameOnly = name2.replace(/(?: \([^)]+\)| abp?| Kustannus| Kustannus Oy|, kustannusosakeyhtiö| oyj?| ry)$/ugi, "");
|
|
60
|
+
if (nameOnly === name2) {
|
|
61
|
+
return [name2, void 0];
|
|
97
62
|
}
|
|
98
|
-
return [nameOnly,
|
|
63
|
+
return [nameOnly, name2.substring(nameOnly.length).replace(/^,? /u, "")];
|
|
99
64
|
}
|
|
100
|
-
function extractPrefix(
|
|
101
|
-
const nameOnly =
|
|
102
|
-
if (nameOnly ===
|
|
103
|
-
return [
|
|
65
|
+
function extractPrefix(name2) {
|
|
66
|
+
const nameOnly = name2.replace(/^(?:Ab|Kustannusosakeyhtiö|Kustannus Oy|Oy) /ugi, "");
|
|
67
|
+
if (nameOnly === name2) {
|
|
68
|
+
return [name2, void 0];
|
|
104
69
|
}
|
|
105
|
-
return [nameOnly,
|
|
70
|
+
return [nameOnly, name2.substring(0, name2.length - nameOnly.length - 1)];
|
|
106
71
|
}
|
|
107
|
-
function getBestName(
|
|
108
|
-
const NAME =
|
|
109
|
-
if (NAME ===
|
|
110
|
-
return
|
|
72
|
+
function getBestName(name2) {
|
|
73
|
+
const NAME = name2.toUpperCase();
|
|
74
|
+
if (NAME === "WSOY") {
|
|
75
|
+
return "Werner S\xF6derstr\xF6m osakeyhti\xF6";
|
|
111
76
|
}
|
|
112
|
-
if (NAME ===
|
|
113
|
-
return
|
|
77
|
+
if (NAME === "NTAMO") {
|
|
78
|
+
return "ntamo";
|
|
114
79
|
}
|
|
115
|
-
return
|
|
80
|
+
return name2;
|
|
116
81
|
}
|
|
117
82
|
}
|
|
118
|
-
function canContainOptionalQualifier(tag, subfieldCode) {
|
|
119
|
-
|
|
120
|
-
if (tag === '300' && subfieldCode === 'a') {
|
|
83
|
+
export function canContainOptionalQualifier(tag, subfieldCode) {
|
|
84
|
+
if (tag === "300" && subfieldCode === "a") {
|
|
121
85
|
return true;
|
|
122
86
|
}
|
|
123
|
-
|
|
124
|
-
if (tag === '776' && subfieldCode === 'i') {
|
|
87
|
+
if (tag === "776" && subfieldCode === "i") {
|
|
125
88
|
return true;
|
|
126
89
|
}
|
|
127
90
|
return false;
|
|
@@ -132,174 +95,101 @@ function withAndWithoutQualifierAgree(value1, value2, tag, subfieldCode) {
|
|
|
132
95
|
}
|
|
133
96
|
const [name1, qualifier1] = splitToNameAndQualifier(value1);
|
|
134
97
|
const [name2, qualifier2] = splitToNameAndQualifier(value2);
|
|
135
|
-
|
|
136
|
-
//nvdebug(`CN1: '${name1}', '${qualifier1}'`, debugDev);
|
|
137
|
-
//nvdebug(`CN2: '${name2}', '${qualifier2}'`, debugDev);
|
|
138
|
-
|
|
139
98
|
if (name1.toLowerCase() !== name2.toLowerCase()) {
|
|
140
99
|
return false;
|
|
141
100
|
}
|
|
142
|
-
|
|
143
|
-
// If either value does not have a qualifier, they are considered equals:
|
|
144
|
-
if (qualifier1 === undefined || qualifier2 === undefined || qualifier1.toLowerCase() === qualifier2.toLowerCase()) {
|
|
101
|
+
if (qualifier1 === void 0 || qualifier2 === void 0 || qualifier1.toLowerCase() === qualifier2.toLowerCase()) {
|
|
145
102
|
return true;
|
|
146
103
|
}
|
|
147
104
|
return false;
|
|
148
105
|
}
|
|
149
106
|
function corporateNamesAgree(value1, value2, tag, subfieldCode) {
|
|
150
|
-
if (subfieldCode !==
|
|
107
|
+
if (subfieldCode !== "a" || !["110", "610", "710", "810"].includes(tag)) {
|
|
151
108
|
return false;
|
|
152
109
|
}
|
|
153
110
|
const nameData1 = splitToNameAndQualifierAndProcessName(value1);
|
|
154
111
|
const nameData2 = splitToNameAndQualifierAndProcessName(value2);
|
|
155
|
-
|
|
156
|
-
|
|
112
|
+
nvdebug(`CN1: '${nameData1.name}', '${nameData1.qualifier}'`, debugDev);
|
|
113
|
+
nvdebug(`CN2: '${nameData2.name}', '${nameData2.qualifier}'`, debugDev);
|
|
157
114
|
if (nameData1.name !== nameData2.name) {
|
|
158
115
|
return false;
|
|
159
116
|
}
|
|
160
117
|
if (nameData1.qualifier && nameData2.qualifier && nameData1.qualifier !== nameData2.qualifier) {
|
|
161
118
|
return false;
|
|
162
119
|
}
|
|
163
|
-
// Currently all prefixes and suffixes are publisher information, so there's no point comparing them any further...
|
|
164
|
-
|
|
165
120
|
return true;
|
|
166
|
-
|
|
167
|
-
/*
|
|
168
|
-
function isKustantaja(nameData) {
|
|
169
|
-
if (nameData.suffix.match(/^(?:Kustannus|Kustannus oy|kustannusosakeyhtiö)$/iu)) {
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
if (nameData.prefix.match(/^Kustannus Oy$/i)) {
|
|
173
|
-
return true;
|
|
174
|
-
}
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
*/
|
|
178
121
|
}
|
|
179
122
|
function pairableValue(tag, subfieldCode, value1, value2) {
|
|
180
|
-
// This function could just return true or false.
|
|
181
|
-
// I thought of preference when I wrote this, but preference implemented *here* (modularity). mergeFields.js should handle preference.
|
|
182
123
|
if (withAndWithoutQualifierAgree(value1, value2, tag, subfieldCode)) {
|
|
183
|
-
// 300$a "whatever" and "whatever (123 sivua)"
|
|
184
124
|
return value1;
|
|
185
125
|
}
|
|
186
|
-
if (
|
|
187
|
-
// Pure baseness: here we assume that base's value1 is better than source's value2.
|
|
126
|
+
if (partsAgree(value1, value2, tag, subfieldCode) || corporateNamesAgree(value1, value2, tag, subfieldCode)) {
|
|
188
127
|
return value1;
|
|
189
128
|
}
|
|
190
|
-
return
|
|
129
|
+
return void 0;
|
|
191
130
|
}
|
|
192
131
|
function counterpartExtraNormalize(tag, subfieldCode, value) {
|
|
193
|
-
|
|
194
|
-
value = value.replace(
|
|
195
|
-
|
|
196
|
-
value = value
|
|
197
|
-
value = value.replace(
|
|
198
|
-
|
|
199
|
-
value = (0, _utils.removeCopyright)(value);
|
|
200
|
-
value = value.replace(/http:\/\//ug, 'https://'); // MET-501: http vs https
|
|
201
|
-
value = (0, _worldKnowledge.normalizeForSamenessCheck)(tag, subfieldCode, value);
|
|
202
|
-
|
|
203
|
-
/* eslint-enable */
|
|
132
|
+
value = value.replace(/(\S)(?:,|\.|\?|!|\. -| *:| *;| =| \/)$/u, "$1");
|
|
133
|
+
value = value.replace(/^\(([^()]+)\)$/u, "$1");
|
|
134
|
+
value = value.replace(/^\[([^[\]]+)\]$/u, "$1");
|
|
135
|
+
value = removeCopyright(value);
|
|
136
|
+
value = value.replace(/http:\/\//ug, "https://");
|
|
137
|
+
value = normalizeForSamenessCheck(tag, subfieldCode, value);
|
|
204
138
|
return value;
|
|
205
139
|
}
|
|
206
140
|
function uniqueKeyMatches(baseField, sourceField, forcedKeyString = null) {
|
|
207
|
-
|
|
208
|
-
// What to do if if base
|
|
209
|
-
// const keySubfieldsAsString = forcedKeyString || getUniqueKeyFields(field1);
|
|
210
|
-
const keySubfieldsAsString = forcedKeyString || (0, _mergeConstraints.getMergeConstraintsForTag)(baseField.tag, 'key');
|
|
211
|
-
//return mandatorySubfieldComparison(baseField, sourceField, keySubfieldsAsString);
|
|
141
|
+
const keySubfieldsAsString = forcedKeyString || getMergeConstraintsForTag(baseField.tag, "key");
|
|
212
142
|
return optionalSubfieldComparison(baseField, sourceField, keySubfieldsAsString);
|
|
213
143
|
}
|
|
214
144
|
function optionalSubfieldComparison(originalBaseField, originalSourceField, keySubfieldsAsString) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// We use clones here, since these changes done below are not intented to appear on the actual records.
|
|
218
|
-
const field1 = (0, _normalizeFieldForComparison.cloneAndNormalizeFieldForComparison)(originalBaseField);
|
|
219
|
-
const field2 = (0, _normalizeFieldForComparison.cloneAndNormalizeFieldForComparison)(originalSourceField);
|
|
145
|
+
const field1 = cloneAndNormalizeFieldForComparison(originalBaseField);
|
|
146
|
+
const field2 = cloneAndNormalizeFieldForComparison(originalSourceField);
|
|
220
147
|
if (keySubfieldsAsString === null) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
// (However, keySubfieldsAsString === '' will always succeed. Used by 040 at least.)
|
|
226
|
-
// NB! substring(6) skips "TAG II" (I=indicator. Thus we skip indicators)
|
|
227
|
-
return (0, _utils.fieldToString)(field1).substring(6) === (0, _utils.fieldToString)(field2).substring(6);
|
|
228
|
-
}
|
|
229
|
-
const subfieldArray = keySubfieldsAsString.split('');
|
|
230
|
-
|
|
231
|
-
// Long forgotten, but my educated guess about this: if 'key' is defined in merge constraints
|
|
232
|
-
// for this field, then at least one of the subfield codes in 'key' must be present in both fields.
|
|
233
|
-
// However, this is not necessarily right.
|
|
234
|
-
if (subfieldArray.length > 0 && !subfieldArray.some(sfCode => hasCommonNominator(sfCode))) {
|
|
148
|
+
return fieldToString(field1).substring(6) === fieldToString(field2).substring(6);
|
|
149
|
+
}
|
|
150
|
+
const subfieldArray = keySubfieldsAsString.split("");
|
|
151
|
+
if (subfieldArray.length > 0 && !subfieldArray.some((sfCode) => hasCommonNominator(sfCode))) {
|
|
235
152
|
return false;
|
|
236
153
|
}
|
|
237
|
-
return subfieldArray.every(subfieldCode => testOptionalSubfield(originalBaseField.tag, subfieldCode));
|
|
154
|
+
return subfieldArray.every((subfieldCode) => testOptionalSubfield(originalBaseField.tag, subfieldCode));
|
|
238
155
|
function hasCommonNominator(subfieldCode) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// If base has $a and source has $b, there's no common nominator, thus fail...
|
|
242
|
-
const subfields1 = field1.subfields.filter(subfield => subfield.code === subfieldCode && (0, _worldKnowledge.valueCarriesMeaning)(field1.tag, subfield.code, subfield.value));
|
|
243
|
-
const subfields2 = field2.subfields.filter(subfield => subfield.code === subfieldCode && (0, _worldKnowledge.valueCarriesMeaning)(field2.tag, subfield.code, subfield.value));
|
|
156
|
+
const subfields1 = field1.subfields.filter((subfield) => subfield.code === subfieldCode && valueCarriesMeaning(field1.tag, subfield.code, subfield.value));
|
|
157
|
+
const subfields2 = field2.subfields.filter((subfield) => subfield.code === subfieldCode && valueCarriesMeaning(field2.tag, subfield.code, subfield.value));
|
|
244
158
|
return subfields1.length > 0 && subfields2.length > 0;
|
|
245
159
|
}
|
|
246
160
|
function testOptionalSubfield(tag, subfieldCode) {
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
const subfields2 = field2.subfields.filter(subfield => subfield.code === subfieldCode && (0, _worldKnowledge.valueCarriesMeaning)(field2.tag, subfield.code, subfield.value));
|
|
250
|
-
|
|
251
|
-
// If one side is empty, all is good
|
|
161
|
+
const subfields1 = field1.subfields.filter((subfield) => subfield.code === subfieldCode && valueCarriesMeaning(field1.tag, subfield.code, subfield.value));
|
|
162
|
+
const subfields2 = field2.subfields.filter((subfield) => subfield.code === subfieldCode && valueCarriesMeaning(field2.tag, subfield.code, subfield.value));
|
|
252
163
|
if (subfields1.length === 0 || subfields2.length === 0) {
|
|
253
164
|
return true;
|
|
254
165
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
// When pairing we can use stronger normalizations than the generic one:
|
|
260
|
-
const subfieldValues1 = subfields1.map(sf => counterpartExtraNormalize(tag, subfieldCode, sf.value));
|
|
261
|
-
const subfieldValues2 = subfields2.map(sf => counterpartExtraNormalize(tag, subfieldCode, sf.value));
|
|
262
|
-
|
|
263
|
-
//nvdebug(`SF1 NORM: ${subfieldValues1.join(' --')}`, debugDev);
|
|
264
|
-
//nvdebug(`SF2 NORM: ${subfieldValues2.join(' --')}`, debugDev);
|
|
265
|
-
|
|
266
|
-
// If one set is a subset of the other, all is probably good (how about 653$a, 505...)
|
|
267
|
-
if (subfieldValues1.every(val => subfieldValues2.includes(val)) || subfieldValues2.every(val => subfieldValues1.includes(val))) {
|
|
166
|
+
const subfieldValues1 = subfields1.map((sf) => counterpartExtraNormalize(tag, subfieldCode, sf.value));
|
|
167
|
+
const subfieldValues2 = subfields2.map((sf) => counterpartExtraNormalize(tag, subfieldCode, sf.value));
|
|
168
|
+
if (subfieldValues1.every((val) => subfieldValues2.includes(val)) || subfieldValues2.every((val) => subfieldValues1.includes(val))) {
|
|
268
169
|
return true;
|
|
269
170
|
}
|
|
270
171
|
if (subfieldValues1.length === 1 && subfieldValues2.length === 1) {
|
|
271
|
-
return pairableValue(field1.tag, subfieldCode, subfieldValues1[0], subfieldValues2[0]) !==
|
|
172
|
+
return pairableValue(field1.tag, subfieldCode, subfieldValues1[0], subfieldValues2[0]) !== void 0;
|
|
272
173
|
}
|
|
273
174
|
return false;
|
|
274
175
|
}
|
|
275
176
|
}
|
|
276
177
|
function mandatorySubfieldComparison(originalField1, originalField2, keySubfieldsAsString) {
|
|
277
|
-
|
|
278
|
-
const
|
|
279
|
-
const field2 = (0, _normalizeFieldForComparison.cloneAndNormalizeFieldForComparison)(originalField2);
|
|
178
|
+
const field1 = cloneAndNormalizeFieldForComparison(originalField1);
|
|
179
|
+
const field2 = cloneAndNormalizeFieldForComparison(originalField2);
|
|
280
180
|
if (keySubfieldsAsString === null) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// (However, keySubfieldsAsString === '' will always succeed. Used by 040 at least.)
|
|
286
|
-
return (0, _utils.fieldToString)(field1) === (0, _utils.fieldToString)(field2);
|
|
287
|
-
}
|
|
288
|
-
const subfieldArray = keySubfieldsAsString.split('');
|
|
289
|
-
|
|
290
|
-
//const differentSubfieldCodes = differentPublisherSubfields(originalField1, originalField2);
|
|
291
|
-
|
|
292
|
-
return subfieldArray.every(subfieldCode => mandatorySingleSubfieldComparison(subfieldCode));
|
|
181
|
+
return fieldToString(field1) === fieldToString(field2);
|
|
182
|
+
}
|
|
183
|
+
const subfieldArray = keySubfieldsAsString.split("");
|
|
184
|
+
return subfieldArray.every((subfieldCode) => mandatorySingleSubfieldComparison(subfieldCode));
|
|
293
185
|
function mandatorySingleSubfieldComparison(subfieldCode) {
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
const subfieldValues2 = field2.subfields.filter(subfield => subfield.code === subfieldCode).map(sf => sf.value);
|
|
297
|
-
// Assume that at least 1 instance must exist and that all instances must match
|
|
186
|
+
const subfieldValues1 = field1.subfields.filter((subfield) => subfield.code === subfieldCode).map((sf) => sf.value);
|
|
187
|
+
const subfieldValues2 = field2.subfields.filter((subfield) => subfield.code === subfieldCode).map((sf) => sf.value);
|
|
298
188
|
if (subfieldValues1.length !== subfieldValues2.length) {
|
|
299
189
|
debugDev(`mSC: Unique key: subfield ${subfieldCode} issues...`);
|
|
300
190
|
return false;
|
|
301
191
|
}
|
|
302
|
-
return subfieldValues1.every(value => subfieldValues2.includes(value));
|
|
192
|
+
return subfieldValues1.every((value) => subfieldValues2.includes(value));
|
|
303
193
|
}
|
|
304
194
|
}
|
|
305
195
|
function tagToRegexp(tag, internalMerge = false) {
|
|
@@ -307,63 +197,53 @@ function tagToRegexp(tag, internalMerge = false) {
|
|
|
307
197
|
return counterpartRegexpsSingle[tag];
|
|
308
198
|
}
|
|
309
199
|
if (!internalMerge && tag in counterpartRegexps) {
|
|
310
|
-
// eg. 700 looks for tag /^[17]00$/...
|
|
311
200
|
const regexp = counterpartRegexps[tag];
|
|
312
|
-
//nvdebug(`regexp for ${tag} found: ${regexp}`, debugDev);
|
|
313
201
|
return regexp;
|
|
314
202
|
}
|
|
315
|
-
|
|
316
|
-
return new RegExp(`^${tag}$`, 'u');
|
|
203
|
+
return new RegExp(`^${tag}$`, "u");
|
|
317
204
|
}
|
|
318
205
|
function areRequiredSubfieldsPresent(field) {
|
|
319
|
-
const subfieldString =
|
|
206
|
+
const subfieldString = getMergeConstraintsForTag(field.tag, "required");
|
|
320
207
|
if (subfieldString === null) {
|
|
321
208
|
return true;
|
|
322
|
-
}
|
|
323
|
-
const subfieldArray = subfieldString.split(
|
|
324
|
-
return subfieldArray.every(sfcode => {
|
|
325
|
-
const result =
|
|
209
|
+
}
|
|
210
|
+
const subfieldArray = subfieldString.split("");
|
|
211
|
+
return subfieldArray.every((sfcode) => {
|
|
212
|
+
const result = fieldHasSubfield(field, sfcode);
|
|
326
213
|
if (!result) {
|
|
327
|
-
debugDev(`Required subfield
|
|
214
|
+
debugDev(`Required subfield \u2021${sfcode} not found in '${fieldToString(field)}'!`);
|
|
328
215
|
return false;
|
|
329
216
|
}
|
|
330
217
|
return true;
|
|
331
218
|
});
|
|
332
219
|
}
|
|
333
220
|
function arePairedSubfieldsInBalance(field1, field2) {
|
|
334
|
-
const subfieldString =
|
|
221
|
+
const subfieldString = getMergeConstraintsForTag(field1.tag, "paired");
|
|
335
222
|
if (subfieldString === null) {
|
|
336
223
|
return true;
|
|
337
224
|
}
|
|
338
|
-
const subfieldArray = subfieldString.split(
|
|
339
|
-
return subfieldArray.every(sfcode =>
|
|
225
|
+
const subfieldArray = subfieldString.split("");
|
|
226
|
+
return subfieldArray.every((sfcode) => fieldHasNSubfields(field1, sfcode) === fieldHasNSubfields(field2, sfcode));
|
|
340
227
|
}
|
|
341
228
|
function syntacticallyMergablePair(baseField, sourceField, config) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
(0, _utils.nvdebug)(`non-mergable (reason: indicator1): ${JSON.stringify(config)}`, debugDev);
|
|
229
|
+
if (!mergableIndicator1(baseField, sourceField, config)) {
|
|
230
|
+
nvdebug(`non-mergable (reason: indicator1): ${JSON.stringify(config)}`, debugDev);
|
|
345
231
|
return false;
|
|
346
232
|
}
|
|
347
|
-
if (!
|
|
348
|
-
|
|
233
|
+
if (!mergableIndicator2(baseField, sourceField, config)) {
|
|
234
|
+
nvdebug(`non-mergable (reason: indicator2): ${JSON.stringify(config)}`, debugDev);
|
|
349
235
|
return false;
|
|
350
236
|
}
|
|
351
|
-
if (!
|
|
352
|
-
|
|
237
|
+
if (!controlSubfieldsPermitMerge(baseField, sourceField)) {
|
|
238
|
+
nvdebug("non-mergable (reason: control subfield)", debugDev);
|
|
353
239
|
return false;
|
|
354
240
|
}
|
|
355
|
-
|
|
356
|
-
// NB! field1.tag and field2.tag might differ (1XX vs 7XX). Therefore required subfields might theoretically differ as well.
|
|
357
|
-
// Note: Theoretically 260 $efg vs 264 with IND2=3 has already been handled by the preprocessor.
|
|
358
|
-
// Thus check both:
|
|
359
241
|
if (!areRequiredSubfieldsPresent(baseField) || !areRequiredSubfieldsPresent(sourceField)) {
|
|
360
|
-
|
|
242
|
+
nvdebug("non-mergable (reason: missing subfields)", debugDev);
|
|
361
243
|
return false;
|
|
362
244
|
}
|
|
363
|
-
|
|
364
|
-
// Stuff of Hacks! Eg. require that both fields either have or have not X00$t:
|
|
365
245
|
if (!arePairedSubfieldsInBalance(baseField, sourceField)) {
|
|
366
|
-
|
|
246
|
+
nvdebug("required subfield pair check failed.", debugDev);
|
|
367
247
|
return false;
|
|
368
248
|
}
|
|
369
249
|
return true;
|
|
@@ -372,20 +252,16 @@ function mergablePair(baseField, sourceField, config) {
|
|
|
372
252
|
if (!syntacticallyMergablePair(baseField, sourceField, config)) {
|
|
373
253
|
return false;
|
|
374
254
|
}
|
|
375
|
-
|
|
376
|
-
//debug('Test semantics...');
|
|
377
255
|
if (!semanticallyMergablePair(baseField, sourceField)) {
|
|
378
|
-
|
|
256
|
+
nvdebug("non-mergable (reason: semantics)", debugDev);
|
|
379
257
|
return false;
|
|
380
258
|
}
|
|
381
|
-
|
|
259
|
+
nvdebug(`MERGABLE PAIR:
|
|
260
|
+
B: ${fieldToString(baseField)}
|
|
261
|
+
S: ${fieldToString(sourceField)}`, debugDev);
|
|
382
262
|
return true;
|
|
383
263
|
}
|
|
384
264
|
function pairableAsteriIDs(baseField, sourceField) {
|
|
385
|
-
//nvdebug(`ASTERI1 ${fieldToString(baseField)}`, debugDev); // eslint-disable-line
|
|
386
|
-
//nvdebug(`ASTERI2 ${fieldToString(sourceField)}`, debugDev); // eslint-disable-line
|
|
387
|
-
|
|
388
|
-
// Check that relevant control subfield(s) exist in both records (as controlSubfieldsPermitMerge() doesn't check it):
|
|
389
265
|
const fin11a = getAsteriIDs(baseField);
|
|
390
266
|
if (fin11a.length === 0) {
|
|
391
267
|
return false;
|
|
@@ -394,96 +270,66 @@ function pairableAsteriIDs(baseField, sourceField) {
|
|
|
394
270
|
if (fin11b.length === 0) {
|
|
395
271
|
return false;
|
|
396
272
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
// Check that found control subfields agree. Use pre-existing generic function to reduce code.
|
|
400
|
-
// (NB! We could optimize and just return true here, as control subfield check is done elsewhere as well.
|
|
401
|
-
// However, explicitly checking them here makes the code more robust.)
|
|
402
|
-
if (!(0, _controlSubfields.controlSubfieldsPermitMerge)(baseField, sourceField)) {
|
|
273
|
+
if (!controlSubfieldsPermitMerge(baseField, sourceField)) {
|
|
403
274
|
return false;
|
|
404
275
|
}
|
|
405
|
-
//console.log(`ASTERI PAIR ${fieldToString(sourceField)}`); // eslint-disable-line
|
|
406
276
|
return true;
|
|
407
|
-
|
|
408
|
-
// NB! This boldly assumes that the default prefix for Asteri is '(FIN11)', not '(FI-ASTERI-N)' nor a finaf urn...
|
|
409
277
|
function getAsteriIDs(field) {
|
|
410
|
-
return field.subfields.filter(sf => sf.code ===
|
|
278
|
+
return field.subfields.filter((sf) => sf.code === "0").map((sf) => normalizeControlSubfieldValue(sf.value)).filter((val) => val.substring(0, 7) === "(FIN11)");
|
|
411
279
|
}
|
|
412
280
|
}
|
|
413
281
|
function hasRepeatableSubfieldThatShouldBeTreatedAsNonRepeatable(field) {
|
|
414
|
-
if (field.tag ===
|
|
415
|
-
return [
|
|
282
|
+
if (field.tag === "260" || field.tag === "264") {
|
|
283
|
+
return ["a", "b", "c", "e", "f", "g"].some((subfieldCode) => fieldHasMultipleSubfields(field, subfieldCode));
|
|
416
284
|
}
|
|
417
|
-
if (field.tag ===
|
|
418
|
-
return [
|
|
285
|
+
if (field.tag === "382") {
|
|
286
|
+
return ["a", "b", "d", "e", "n", "p"].some((subfieldCode) => fieldHasMultipleSubfields(field, subfieldCode));
|
|
419
287
|
}
|
|
420
|
-
if (field.tag ===
|
|
421
|
-
return [
|
|
288
|
+
if (field.tag === "505") {
|
|
289
|
+
return ["t", "r", "g"].some((subfieldCode) => fieldHasMultipleSubfields(field, subfieldCode));
|
|
422
290
|
}
|
|
423
291
|
return false;
|
|
424
292
|
}
|
|
425
293
|
function pairableName(baseField, sourceField) {
|
|
426
|
-
// 100$a$t: remove $t and everything after that
|
|
427
294
|
const reducedField1 = fieldToNamePart(baseField);
|
|
428
295
|
const reducedField2 = fieldToNamePart(sourceField);
|
|
429
|
-
const string1 =
|
|
430
|
-
const string2 =
|
|
431
|
-
|
|
432
|
-
//nvdebug(`IN: pairableName():\n '${string1}' vs\n '${string2}'`, debugDev);
|
|
296
|
+
const string1 = fieldToString(reducedField1);
|
|
297
|
+
const string2 = fieldToString(reducedField2);
|
|
433
298
|
if (string1 === string2) {
|
|
434
299
|
return true;
|
|
435
300
|
}
|
|
436
|
-
|
|
437
|
-
// Essentially these are too hard to handle with field-merge (eg. multi-505$g)
|
|
438
301
|
if (hasRepeatableSubfieldThatShouldBeTreatedAsNonRepeatable(reducedField1) || hasRepeatableSubfieldThatShouldBeTreatedAsNonRepeatable(reducedField2)) {
|
|
439
302
|
return false;
|
|
440
303
|
}
|
|
441
|
-
|
|
442
|
-
// Compare the remaining subsets...
|
|
443
|
-
// First check that name matches...
|
|
444
304
|
if (uniqueKeyMatches(reducedField1, reducedField2)) {
|
|
445
|
-
|
|
305
|
+
nvdebug(` name match: '${fieldToString(reducedField1)}'`, debugDev);
|
|
446
306
|
return true;
|
|
447
307
|
}
|
|
448
|
-
|
|
449
|
-
// However, name mismatch is not critical! If Asteri ID matches, it's still a match! *NOT* sure whether this a good idea.
|
|
450
|
-
// 2023-01-24 Disable this. Caretaker can fix these later on. Not a job for merge. We can't be sure that $0 pair is corrent, nor which version (base or source) to use.
|
|
451
|
-
// 2023-03-07: Enable this again!
|
|
452
308
|
if (pairableAsteriIDs(baseField, sourceField)) {
|
|
453
|
-
//nvdebug(` name match based on ASTERI $0'`, debugDev);
|
|
454
309
|
return true;
|
|
455
310
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
311
|
+
nvdebug(` name mismatch:`, debugDev);
|
|
312
|
+
nvdebug(` '${fieldToString(reducedField1)}' vs`, debugDev);
|
|
313
|
+
nvdebug(` '${fieldToString(reducedField2)}'`, debugDev);
|
|
459
314
|
return false;
|
|
460
315
|
}
|
|
461
316
|
function semanticallyMergablePair(baseField, sourceField) {
|
|
462
|
-
// On rare occasions a field contains also a title part. For these name part (= normally everything) and title part
|
|
463
|
-
// must be checked separately:
|
|
464
317
|
if (!titlePartsMatch(baseField, sourceField)) {
|
|
465
|
-
|
|
318
|
+
nvdebug(` ${baseField.tag} is unmergable: Title part mismatch.`, debugDev);
|
|
466
319
|
return false;
|
|
467
320
|
}
|
|
468
|
-
|
|
469
|
-
// Hmm... we should check lifespan here, $d YYYY
|
|
470
|
-
|
|
471
|
-
// Handle the field specific "unique key" (=set of fields that make the field unique
|
|
472
321
|
if (!pairableName(baseField, sourceField)) {
|
|
473
|
-
|
|
322
|
+
nvdebug("Unmergable: Name part mismatch", debugDev);
|
|
474
323
|
return false;
|
|
475
324
|
}
|
|
476
|
-
//debug(' Semantic checks passed! We are MERGABLE!');
|
|
477
|
-
|
|
478
325
|
return true;
|
|
479
326
|
}
|
|
480
327
|
function namePartThreshold(field) {
|
|
481
|
-
// Threshold is only applicaple to some tags..
|
|
482
328
|
if (!/[10]0$/u.test(field.tag)) {
|
|
483
329
|
return -1;
|
|
484
330
|
}
|
|
485
|
-
const t = field.subfields.findIndex(currSubfield => currSubfield.code ===
|
|
486
|
-
const u = t;
|
|
331
|
+
const t = field.subfields.findIndex((currSubfield) => currSubfield.code === "t");
|
|
332
|
+
const u = t;
|
|
487
333
|
if (t === -1) {
|
|
488
334
|
return u;
|
|
489
335
|
}
|
|
@@ -494,41 +340,21 @@ function namePartThreshold(field) {
|
|
|
494
340
|
}
|
|
495
341
|
function fieldToNamePart(field) {
|
|
496
342
|
const index = namePartThreshold(field);
|
|
497
|
-
const relevantSubfields = field.subfields.filter((sf, i) => i < index || index === -1).filter(sf => !irrelevantSubfieldsInNameAndTitlePartComparison.includes(sf.code));
|
|
498
|
-
const subsetField = {
|
|
499
|
-
'tag': field.tag,
|
|
500
|
-
'ind1': field.ind1,
|
|
501
|
-
'ind2': field.ind2,
|
|
502
|
-
subfields: relevantSubfields
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
/*
|
|
506
|
-
if (index > -1) {
|
|
507
|
-
debugDev(`Name subset: ${fieldToString(subsetField)}`);
|
|
508
|
-
}
|
|
509
|
-
*/
|
|
510
|
-
|
|
511
|
-
// Ummm... Sometimes $0 comes after $t but belongs to name part
|
|
512
|
-
|
|
343
|
+
const relevantSubfields = field.subfields.filter((sf, i) => i < index || index === -1).filter((sf) => !irrelevantSubfieldsInNameAndTitlePartComparison.includes(sf.code));
|
|
344
|
+
const subsetField = { "tag": field.tag, "ind1": field.ind1, "ind2": field.ind2, subfields: relevantSubfields };
|
|
513
345
|
return subsetField;
|
|
514
346
|
}
|
|
515
347
|
function fieldToTitlePart(field) {
|
|
516
|
-
|
|
517
|
-
const
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
'tag': field.tag,
|
|
521
|
-
'ind1': field.ind1,
|
|
522
|
-
'ind2': field.ind2,
|
|
523
|
-
subfields: relevantSubfields
|
|
524
|
-
};
|
|
525
|
-
debugDev(`Title subset: ${(0, _utils.fieldToString)(subsetField)}`);
|
|
348
|
+
const index = field.subfields.findIndex((currSubfield) => currSubfield.code === "t");
|
|
349
|
+
const relevantSubfields = field.subfields.filter((sf, i) => i >= index).filter((sf) => !irrelevantSubfieldsInNameAndTitlePartComparison.includes(sf.code));
|
|
350
|
+
const subsetField = { "tag": field.tag, "ind1": field.ind1, "ind2": field.ind2, subfields: relevantSubfields };
|
|
351
|
+
debugDev(`Title subset: ${fieldToString(subsetField)}`);
|
|
526
352
|
return subsetField;
|
|
527
353
|
}
|
|
528
354
|
function containsTitlePart(field) {
|
|
529
|
-
return fieldCanHaveTitlePart(field) &&
|
|
530
|
-
function fieldCanHaveTitlePart(
|
|
531
|
-
return [
|
|
355
|
+
return fieldCanHaveTitlePart(field) && fieldHasSubfield(field, "t");
|
|
356
|
+
function fieldCanHaveTitlePart(field2) {
|
|
357
|
+
return ["100", "110", "111", "700", "710", "711"].includes(field2.tag);
|
|
532
358
|
}
|
|
533
359
|
}
|
|
534
360
|
function titlePartsMatch(field1, field2) {
|
|
@@ -539,43 +365,38 @@ function titlePartsMatch(field1, field2) {
|
|
|
539
365
|
return false;
|
|
540
366
|
}
|
|
541
367
|
debugDev(`TITLE PARTS NEED TO BE COMPARED`);
|
|
542
|
-
|
|
543
|
-
// 100$a$t: remove $t and everything after that
|
|
544
368
|
const subset1 = fieldToTitlePart(field1);
|
|
545
369
|
const subset2 = fieldToTitlePart(field2);
|
|
546
|
-
|
|
547
|
-
return mandatorySubfieldComparison(subset1, subset2, 'dfhklmnoprstxvg');
|
|
370
|
+
return mandatorySubfieldComparison(subset1, subset2, "dfhklmnoprstxvg");
|
|
548
371
|
}
|
|
549
372
|
function getAlternativeNamesFrom9XX(record, field) {
|
|
550
|
-
// Should we support 6XX and 8XX as well? Prolly not...
|
|
551
373
|
if (!field.tag.match(/^(?:100|110|111|600|610|611|700|710|711)$/u)) {
|
|
552
374
|
return [];
|
|
553
375
|
}
|
|
554
376
|
const tag = `9${field.tag.substring(1)}`;
|
|
555
|
-
const cands = record.get(tag).filter(f =>
|
|
377
|
+
const cands = record.get(tag).filter((f) => fieldHasSubfield(f, "a") && fieldHasSubfield(f, "y"));
|
|
556
378
|
if (cands.length === 0) {
|
|
557
379
|
return [];
|
|
558
380
|
}
|
|
559
|
-
const punctuationlessField =
|
|
560
|
-
const [name] = punctuationlessField.subfields.filter(sf => sf.code ===
|
|
561
|
-
return cands.map(candField => getAltName(candField)).filter(val => val !==
|
|
381
|
+
const punctuationlessField = cloneAndRemovePunctuation(field);
|
|
382
|
+
const [name] = punctuationlessField.subfields.filter((sf) => sf.code === "a").map((sf) => sf.value);
|
|
383
|
+
return cands.map((candField) => getAltName(candField)).filter((val) => val !== void 0);
|
|
562
384
|
function getAltName(altField) {
|
|
563
|
-
const [altA] = altField.subfields.filter(sf => sf.code ===
|
|
564
|
-
const [altY] = altField.subfields.filter(sf => sf.code ===
|
|
565
|
-
|
|
385
|
+
const [altA] = altField.subfields.filter((sf) => sf.code === "a").map((sf) => sf.value);
|
|
386
|
+
const [altY] = altField.subfields.filter((sf) => sf.code === "y").map((sf) => sf.value);
|
|
387
|
+
nvdebug(`Compare '${name}' vs '${altA}'/'${altY}'`, debugDev);
|
|
566
388
|
if (name === altA) {
|
|
567
389
|
return altY;
|
|
568
390
|
}
|
|
569
391
|
if (name === altY) {
|
|
570
392
|
return altA;
|
|
571
393
|
}
|
|
572
|
-
|
|
573
|
-
return
|
|
394
|
+
nvdebug(` miss`, debugDev);
|
|
395
|
+
return void 0;
|
|
574
396
|
}
|
|
575
397
|
}
|
|
576
398
|
function mergablePairWithAltName(normCandField, normalizedField, altName, config) {
|
|
577
|
-
|
|
578
|
-
const [a] = normalizedField.subfields.filter(sf => sf.code === 'a');
|
|
399
|
+
const [a] = normalizedField.subfields.filter((sf) => sf.code === "a");
|
|
579
400
|
if (!a) {
|
|
580
401
|
return false;
|
|
581
402
|
}
|
|
@@ -583,90 +404,72 @@ function mergablePairWithAltName(normCandField, normalizedField, altName, config
|
|
|
583
404
|
return mergablePair(normCandField, normalizedField, config);
|
|
584
405
|
}
|
|
585
406
|
function getCounterpartIndex(field, counterpartCands, altNames, config) {
|
|
586
|
-
const normalizedField =
|
|
587
|
-
const normalizedCounterpartCands = counterpartCands.map(f =>
|
|
588
|
-
const index = normalizedCounterpartCands.findIndex(normCandField => mergablePair(normCandField, normalizedField, config));
|
|
407
|
+
const normalizedField = cloneAndNormalizeFieldForComparison(field);
|
|
408
|
+
const normalizedCounterpartCands = counterpartCands.map((f) => cloneAndNormalizeFieldForComparison(f));
|
|
409
|
+
const index = normalizedCounterpartCands.findIndex((normCandField) => mergablePair(normCandField, normalizedField, config));
|
|
589
410
|
if (index > -1) {
|
|
590
411
|
return index;
|
|
591
412
|
}
|
|
592
|
-
return normalizedCounterpartCands.findIndex(normCandField => altNames.some(altName => mergablePairWithAltName(normCandField, normalizedField, altName, config)));
|
|
413
|
+
return normalizedCounterpartCands.findIndex((normCandField) => altNames.some((altName) => mergablePairWithAltName(normCandField, normalizedField, altName, config)));
|
|
593
414
|
}
|
|
594
415
|
function field264Exception(baseField, sourceRecord, sourceField, config) {
|
|
595
|
-
|
|
596
|
-
if (baseField.tag !==
|
|
416
|
+
nvdebug("Field 264 exception as per MET-456", debugDev);
|
|
417
|
+
if (baseField.tag !== "264") {
|
|
597
418
|
return false;
|
|
598
419
|
}
|
|
599
|
-
if (sourceField.tag !==
|
|
420
|
+
if (sourceField.tag !== "264" || sourceRecord.get("264").length !== 1) {
|
|
600
421
|
return false;
|
|
601
422
|
}
|
|
602
|
-
|
|
603
|
-
// Don't worry about semantics:
|
|
604
423
|
return syntacticallyMergablePair(sourceField, baseField, config);
|
|
605
424
|
}
|
|
606
425
|
function getCounterpartCandidates(field, record) {
|
|
607
426
|
const counterpartCands = record.get(tagToRegexp(field.tag, record.internalMerge));
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
if (field.tag === '260' && isNotCopyrightYear(field)) {
|
|
611
|
-
return counterpartCands.filter(candField => !isCopyrightField264(candField));
|
|
427
|
+
if (field.tag === "260" && isNotCopyrightYear(field)) {
|
|
428
|
+
return counterpartCands.filter((candField) => !isCopyrightField264(candField));
|
|
612
429
|
}
|
|
613
|
-
if (field.tag ===
|
|
614
|
-
|
|
615
|
-
return counterpartCands.filter(candField => !isNotCopyrightYear(candField));
|
|
430
|
+
if (field.tag === "264" && isCopyrightField264(field)) {
|
|
431
|
+
return counterpartCands.filter((candField) => !isNotCopyrightYear(candField));
|
|
616
432
|
}
|
|
617
|
-
function isCopyrightField264(
|
|
618
|
-
return
|
|
433
|
+
function isCopyrightField264(field2) {
|
|
434
|
+
return field2.tag === "264" && field2.ind2 === "4";
|
|
619
435
|
}
|
|
620
|
-
function isNotCopyrightYear(
|
|
621
|
-
if (
|
|
622
|
-
return !isCopyrightField264(
|
|
436
|
+
function isNotCopyrightYear(field2) {
|
|
437
|
+
if (field2.tag === "264") {
|
|
438
|
+
return !isCopyrightField264(field2);
|
|
623
439
|
}
|
|
624
|
-
|
|
625
|
-
return !field.subfields.some(sf => sf.code === 'a' && sf.code === 'b');
|
|
440
|
+
return !field2.subfields.some((sf) => sf.code === "a" && sf.code === "b");
|
|
626
441
|
}
|
|
627
442
|
return counterpartCands;
|
|
628
443
|
}
|
|
629
|
-
function baseIsSource(base, source) {
|
|
444
|
+
export function baseIsSource(base, source) {
|
|
630
445
|
base.localTest = true;
|
|
631
446
|
const result = source.localTest;
|
|
632
447
|
delete base.localTest;
|
|
633
448
|
return result;
|
|
634
449
|
}
|
|
635
|
-
function getCounterpart(baseRecord, sourceRecord, field, config) {
|
|
636
|
-
|
|
637
|
-
// (<= Note that self-merge behaves differently from two records here.)
|
|
638
|
-
// Hacks: 973 can merge with 773, 940 can merge with 240 (but not the other way around)
|
|
639
|
-
//nvdebug(`COUNTERPART FOR '${fieldToString(field)}'?`, debugDev);
|
|
640
|
-
const counterpartCands = getCounterpartCandidates(field, baseRecord).filter(f => !f.mergeCandidate);
|
|
450
|
+
export function getCounterpart(baseRecord, sourceRecord, field, config) {
|
|
451
|
+
const counterpartCands = getCounterpartCandidates(field, baseRecord).filter((f) => !f.mergeCandidate);
|
|
641
452
|
if (!counterpartCands || counterpartCands.length === 0) {
|
|
642
|
-
//nvdebug(`No counterpart(s) found for ${fieldToString(field)}`, debugDev);
|
|
643
453
|
return null;
|
|
644
454
|
}
|
|
645
|
-
|
|
646
|
-
const normalizedField =
|
|
647
|
-
|
|
648
|
-
(0, _utils.nvdebug)(`Norm to: '${(0, _utils.fieldToString)(normalizedField)}'`, debugDev);
|
|
455
|
+
nvdebug(`Compare incoming '${fieldToString(field)}' with (up to) ${counterpartCands.length} existing field(s)`, debugDev);
|
|
456
|
+
const normalizedField = cloneAndNormalizeFieldForComparison(field);
|
|
457
|
+
nvdebug(`Norm to: '${fieldToString(normalizedField)}'`, debugDev);
|
|
649
458
|
const uniqueAlternativeNames = getUniqueAlernativeNames();
|
|
650
459
|
function getUniqueAlernativeNames() {
|
|
651
460
|
if (baseIsSource(baseRecord, sourceRecord)) {
|
|
652
461
|
return [];
|
|
653
462
|
}
|
|
654
|
-
// Try to look for alternative names from base and source record's 9XX fields:
|
|
655
463
|
const alternativeNames = getAlternativeNamesFrom9XX(baseRecord, field).concat(getAlternativeNamesFrom9XX(sourceRecord, field));
|
|
656
464
|
return alternativeNames.filter((name, i) => alternativeNames.indexOf(name) === i);
|
|
657
465
|
}
|
|
658
|
-
|
|
659
|
-
//nvdebug(` S: ${fieldToString(normalizedField)}`, debugDev);
|
|
660
|
-
// Then find (the index of) the first mathing candidate field and return it.
|
|
661
466
|
const index = getCounterpartIndex(normalizedField, counterpartCands, uniqueAlternativeNames, config);
|
|
662
467
|
if (index > -1) {
|
|
663
468
|
return counterpartCands[index];
|
|
664
469
|
}
|
|
665
|
-
|
|
666
|
-
// MET-456 exception
|
|
667
470
|
if (counterpartCands.length === 1 && field264Exception(counterpartCands[0], sourceRecord, field, config)) {
|
|
668
471
|
return counterpartCands[0];
|
|
669
472
|
}
|
|
670
473
|
return null;
|
|
671
474
|
}
|
|
672
|
-
//# sourceMappingURL=counterpartField.js.map
|
|
475
|
+
//# sourceMappingURL=counterpartField.js.map
|