@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
package/dist/translate-terms.js
CHANGED
|
@@ -2,6 +2,7 @@ import clone from "clone";
|
|
|
2
2
|
import createDebugLogger from "debug";
|
|
3
3
|
import { fieldHasSubfield, fieldToString, nvdebug } from "./utils.js";
|
|
4
4
|
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda:translate-terms");
|
|
5
|
+
const debugDev = debug.extend("dev");
|
|
5
6
|
const defaultTags = ["648", "650", "651", "655"];
|
|
6
7
|
const swapLanguageCode = { "fin": "swe", "fi": "sv", "sv": "fi", "swe": "fin" };
|
|
7
8
|
const changeAbbrHash = { "fi": "fin", "fin": "fi", "sv": "swe", "swe": "sv" };
|
|
@@ -14,7 +15,7 @@ export default function() {
|
|
|
14
15
|
};
|
|
15
16
|
async function fix(record) {
|
|
16
17
|
const newFields = await getFields(record, defaultTags, []);
|
|
17
|
-
newFields.forEach((nf) => nvdebug(`Add new field '${fieldToString(nf)}'`,
|
|
18
|
+
newFields.forEach((nf) => nvdebug(`Add new field '${fieldToString(nf)}'`, debugDev));
|
|
18
19
|
newFields.forEach((nf) => record.insertField(nf));
|
|
19
20
|
const newFieldsAsStrings = newFields.map((f) => fieldToString(f));
|
|
20
21
|
return { message: [], fix: newFieldsAsStrings, valid: true };
|
|
@@ -42,8 +43,8 @@ export default function() {
|
|
|
42
43
|
return [];
|
|
43
44
|
}
|
|
44
45
|
const fields = record.get(tag);
|
|
45
|
-
const finnishFields = fields.filter((f) =>
|
|
46
|
-
const swedishFields = fields.filter((f) =>
|
|
46
|
+
const finnishFields = fields.filter((f) => isTranslatable(f, "fin"));
|
|
47
|
+
const swedishFields = fields.filter((f) => isTranslatable(f, "swe"));
|
|
47
48
|
const finnishOnly = getMisses(finnishFields, swedishFields);
|
|
48
49
|
const swedishOnly = getMisses(swedishFields, finnishFields);
|
|
49
50
|
return [...finnishOnly, ...swedishOnly].filter((f) => tagAndFieldAgree(f));
|
|
@@ -74,95 +75,34 @@ export default function() {
|
|
|
74
75
|
const newField = { tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0] };
|
|
75
76
|
return newField;
|
|
76
77
|
}
|
|
77
|
-
function getLexiconAndLanguage(field) {
|
|
78
|
-
const subfield2 = field.subfields.find((sf) => sf.code === "2");
|
|
79
|
-
if (subfield2.value === "slm/fin") {
|
|
80
|
-
return { "lex": "slm", "lang": "fin" };
|
|
81
|
-
}
|
|
82
|
-
if (subfield2.value === "slm/swe") {
|
|
83
|
-
return { "lex": "slm", "lang": "swe" };
|
|
84
|
-
}
|
|
85
|
-
if (subfield2.value === "yso/fin") {
|
|
86
|
-
return { "lex": "yso", "lang": "fin" };
|
|
87
|
-
}
|
|
88
|
-
if (subfield2.value === "yso/swe") {
|
|
89
|
-
return { "lex": "yso", "lang": "swe" };
|
|
90
|
-
}
|
|
91
|
-
return {};
|
|
92
|
-
}
|
|
93
78
|
async function getPrefLabel(field) {
|
|
94
79
|
const uri = fieldToUri(field);
|
|
95
80
|
if (!uri) {
|
|
96
81
|
return void 0;
|
|
97
82
|
}
|
|
98
|
-
const
|
|
99
|
-
if (!
|
|
100
|
-
nvdebug(`No labels found for ${uri}`,
|
|
83
|
+
const data = await getTermData(uri);
|
|
84
|
+
if (!data) {
|
|
85
|
+
nvdebug(`No labels found for ${uri}`, debugDev);
|
|
101
86
|
return void 0;
|
|
102
87
|
}
|
|
88
|
+
const prefLabels = data.prefLabel;
|
|
103
89
|
const lexData = getLexiconAndLanguage(field);
|
|
104
90
|
const lang = changeAbbr(lexData.lang);
|
|
105
91
|
const subfieldA = field.subfields.find((sf) => sf.code === "a");
|
|
106
|
-
|
|
107
|
-
if (prefLabel.value === subfieldA.value) {
|
|
108
|
-
nvdebug(`'${fieldToString(field)}' requires translating`, debug);
|
|
92
|
+
if (isLabel(prefLabels, subfieldA.value, lang)) {
|
|
109
93
|
return prefLabels;
|
|
110
94
|
}
|
|
111
95
|
return void 0;
|
|
112
96
|
}
|
|
113
|
-
function swapLanguageCodeBetweenLanguages(code) {
|
|
114
|
-
if (swapLanguageCode[code]) {
|
|
115
|
-
return swapLanguageCode[code];
|
|
116
|
-
}
|
|
117
|
-
return code;
|
|
118
|
-
}
|
|
119
|
-
function changeAbbr(abbr) {
|
|
120
|
-
if (changeAbbrHash[abbr]) {
|
|
121
|
-
return changeAbbrHash[abbr];
|
|
122
|
-
}
|
|
123
|
-
return abbr;
|
|
124
|
-
}
|
|
125
|
-
function swaggerQuery(uri) {
|
|
126
|
-
return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`;
|
|
127
|
-
}
|
|
128
|
-
async function getTermData(uri) {
|
|
129
|
-
if (termCache[uri]) {
|
|
130
|
-
return termCache[uri];
|
|
131
|
-
}
|
|
132
|
-
const tmp = await getTermDataFromFinto(uri);
|
|
133
|
-
termCache[uri] = tmp;
|
|
134
|
-
return tmp;
|
|
135
|
-
}
|
|
136
|
-
async function getTermDataFromFinto(uri) {
|
|
137
|
-
const headers = { "Accept": "application/json" };
|
|
138
|
-
const uri2 = swaggerQuery(uri);
|
|
139
|
-
const response = await fetch(uri2, { method: "GET", headers });
|
|
140
|
-
if (!response.ok) {
|
|
141
|
-
return void 0;
|
|
142
|
-
}
|
|
143
|
-
const json = await response.json();
|
|
144
|
-
if (!json.graph) {
|
|
145
|
-
return void 0;
|
|
146
|
-
}
|
|
147
|
-
const arr = json.graph;
|
|
148
|
-
const [hit] = arr.filter((row) => row.uri === uri);
|
|
149
|
-
return hit.prefLabel;
|
|
150
|
-
}
|
|
151
97
|
function fieldToUri(field) {
|
|
152
98
|
const lex = mapTagToLex(field.tag);
|
|
153
99
|
const subfield0 = field.subfields.find((sf) => sf.code === "0");
|
|
154
100
|
const id = subfield0.value.replace(/^[^0-9]+/u, "");
|
|
155
|
-
|
|
156
|
-
return `http://www.yso.fi/onto/yso/p${id}`;
|
|
157
|
-
}
|
|
158
|
-
if (lex === "slm") {
|
|
159
|
-
return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
|
|
160
|
-
}
|
|
161
|
-
return void 0;
|
|
101
|
+
return buildUri(lex, id);
|
|
162
102
|
}
|
|
163
|
-
function
|
|
103
|
+
function isTranslatable(field, lang) {
|
|
164
104
|
const fieldAsString = fieldToString(field);
|
|
165
|
-
if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
|
|
105
|
+
if (!fieldAsString.match(/^... #7 (?: ‡8 [^‡]+ )*‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
|
|
166
106
|
return false;
|
|
167
107
|
}
|
|
168
108
|
const lex = mapTagToLex(field.tag);
|
|
@@ -172,17 +112,6 @@ export default function() {
|
|
|
172
112
|
}
|
|
173
113
|
return fieldHasValidSubfield0(field);
|
|
174
114
|
}
|
|
175
|
-
function fieldHasValidSubfield0(field) {
|
|
176
|
-
const lex = mapTagToLex(field.tag);
|
|
177
|
-
const subfield0 = field.subfields.find((sf) => sf.code === "0");
|
|
178
|
-
if (lex === "yso" && subfield0.value.match(/^http:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
if (lex === "slm" && subfield0.value.match(/^http:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
115
|
function getMisses(fieldList1, fieldList2) {
|
|
187
116
|
return fieldList1.filter((f) => !hasSubfield0Match(f, fieldList2));
|
|
188
117
|
}
|
|
@@ -190,11 +119,119 @@ export default function() {
|
|
|
190
119
|
const subfield0 = field.subfields.find((sf) => sf.code === "0");
|
|
191
120
|
return pairFields.some((f) => f.subfields.some((sf) => sf.code === "0" && sf.value === subfield0.value));
|
|
192
121
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
122
|
+
}
|
|
123
|
+
export function fieldHasValidSubfield0(field, defaultLex = void 0) {
|
|
124
|
+
const lex = defaultLex || mapTagToLex(field.tag);
|
|
125
|
+
return field.subfields.some((sf) => isValidSubfield0(sf, lex));
|
|
126
|
+
}
|
|
127
|
+
export function isValidSubfield0(subfield, lex = "???") {
|
|
128
|
+
if (subfield.code !== "0") {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
if (["yso", "yso/fin", "yso/swe"].includes(lex) && subfield.value.match(/^https?:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
if (["slm", "slm/fin", "slm/swe"].includes(lex) && subfield.value.match(/^https?:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
export function buildUri(lex, id) {
|
|
140
|
+
if (["yso", "yso/fin", "yso/swe"].includes(lex)) {
|
|
141
|
+
return `http://www.yso.fi/onto/yso/p${id}`;
|
|
142
|
+
}
|
|
143
|
+
if (["slm", "slm/fin", "slm/swe"].includes(lex)) {
|
|
144
|
+
return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
|
|
145
|
+
}
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
function mapTagToLex(tag) {
|
|
149
|
+
if (tag === "655") {
|
|
150
|
+
return "slm";
|
|
151
|
+
}
|
|
152
|
+
return "yso";
|
|
153
|
+
}
|
|
154
|
+
export async function getTermData(uri) {
|
|
155
|
+
nvdebug(`getTermData(${uri})`, debugDev);
|
|
156
|
+
if (termCache[uri]) {
|
|
157
|
+
return termCache[uri];
|
|
158
|
+
}
|
|
159
|
+
const tmp = await getTermDataFromFinto(uri);
|
|
160
|
+
termCache[uri] = tmp;
|
|
161
|
+
return tmp;
|
|
162
|
+
}
|
|
163
|
+
async function getTermDataFromFinto(uri) {
|
|
164
|
+
const headers = { "Accept": "application/json" };
|
|
165
|
+
const uri2 = swaggerQuery(uri);
|
|
166
|
+
const response = await fetch(uri2, { method: "GET", headers });
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
return void 0;
|
|
169
|
+
}
|
|
170
|
+
const json = await response.json();
|
|
171
|
+
if (!json.graph) {
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
const arr = json.graph;
|
|
175
|
+
const [hit] = arr.filter((row) => row.uri === uri);
|
|
176
|
+
const subset = {
|
|
177
|
+
prefLabel: processLabel(hit?.prefLabel || void 0),
|
|
178
|
+
altLabel: processLabel(hit?.altLabel || void 0)
|
|
179
|
+
};
|
|
180
|
+
return subset;
|
|
181
|
+
function swaggerQuery(uri3) {
|
|
182
|
+
return `https://api.finto.fi/rest/v1/data?uri=${uri3}&format=application%2Fjson`;
|
|
183
|
+
}
|
|
184
|
+
function processLabel(label) {
|
|
185
|
+
if (typeof label === "object") {
|
|
186
|
+
if (Array.isArray(label)) {
|
|
187
|
+
return label;
|
|
188
|
+
}
|
|
189
|
+
return [label];
|
|
190
|
+
}
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export function getLexiconAndLanguage(field) {
|
|
195
|
+
const subfield2 = field.subfields.find((sf) => sf.code === "2");
|
|
196
|
+
if (subfield2) {
|
|
197
|
+
if (subfield2.value === "slm/fin") {
|
|
198
|
+
return { "lex": "slm", "lang": "fin" };
|
|
199
|
+
}
|
|
200
|
+
if (subfield2.value === "slm/swe") {
|
|
201
|
+
return { "lex": "slm", "lang": "swe" };
|
|
202
|
+
}
|
|
203
|
+
if (subfield2.value === "yso/fin") {
|
|
204
|
+
return { "lex": "yso", "lang": "fin" };
|
|
205
|
+
}
|
|
206
|
+
if (subfield2.value === "yso/swe") {
|
|
207
|
+
return { "lex": "yso", "lang": "swe" };
|
|
196
208
|
}
|
|
197
|
-
return "yso";
|
|
198
209
|
}
|
|
210
|
+
return {};
|
|
211
|
+
}
|
|
212
|
+
export function isLabel(labels, term, lang = void 0) {
|
|
213
|
+
const twoLetterLanguageCode = lang && lang.length === 3 ? changeAbbr(lang) : lang;
|
|
214
|
+
return labels.some((l) => isMatch(l));
|
|
215
|
+
function isMatch(label) {
|
|
216
|
+
if (label.value !== term) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (!twoLetterLanguageCode) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return label.lang === twoLetterLanguageCode;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function changeAbbr(abbr) {
|
|
226
|
+
if (changeAbbrHash[abbr]) {
|
|
227
|
+
return changeAbbrHash[abbr];
|
|
228
|
+
}
|
|
229
|
+
return abbr;
|
|
230
|
+
}
|
|
231
|
+
function swapLanguageCodeBetweenLanguages(code) {
|
|
232
|
+
if (swapLanguageCode[code]) {
|
|
233
|
+
return swapLanguageCode[code];
|
|
234
|
+
}
|
|
235
|
+
return code;
|
|
199
236
|
}
|
|
200
237
|
//# sourceMappingURL=translate-terms.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/translate-terms.js"],
|
|
4
|
-
"sourcesContent": ["import clone from 'clone';\nimport createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug} from './utils.js';\n\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:translate-terms');\nconst defaultTags = ['648', '650', '651', '655'];\n\nconst swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};\nconst changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};\n\nconst termCache = {};\n\n// Author(s): Nicholas Volk\nexport default function () {\n\n\n return {\n description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',\n validate, fix\n };\n\n async function fix(record) {\n const newFields = await getFields(record, defaultTags, []);\n\n newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debug));\n\n newFields.forEach(nf => record.insertField(nf));\n\n const newFieldsAsStrings = newFields.map(f => fieldToString(f));\n\n\n return {message: [], fix: newFieldsAsStrings, valid: true};\n }\n\n async function validate(record) {\n const newFields = await getFields(record, defaultTags, []);\n if (newFields.length === 0) {\n return {'message': [], 'valid': true};\n }\n const messages = newFields.map(f => fieldToString(f));\n\n return {'message': messages, 'valid': false};\n }\n\n async function getFields(record, tags, fieldsToAdd) {\n const [currTag, ...remainingTags] = tags;\n if (!currTag) {\n return fieldsToAdd;\n }\n const missingFields = await deriveMissingFields(record, currTag);\n\n const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);\n return tmp;\n }\n\n function getPairlessFinnishAndSwedishFields(record, tag) {\n const expectedLex = mapTagToLex(tag);\n if (!expectedLex) {\n return [];\n }\n const fields = record.get(tag);\n const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));\n const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));\n const finnishOnly = getMisses(finnishFields, swedishFields);\n const swedishOnly = getMisses(swedishFields, finnishFields);\n\n //console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console\n return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));\n\n function tagAndFieldAgree(field) {\n // Check that tag and $2 value are pairable:\n const lexData = getLexiconAndLanguage(field); // $2 data\n return expectedLex === lexData.lex;\n }\n }\n\n async function deriveMissingFields(record, tag) {\n const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);\n\n // Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)\n let prefLabels = [];\n for (let i=0; i < pairlessFields.length; i += 1) {\n prefLabels[i] = await getPrefLabel(pairlessFields[i]);\n }\n\n const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));\n return missingFields.filter(f => f);\n }\n\n function pairField(field, prefLabels) {\n if (!prefLabels) {\n return undefined;\n }\n //console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console\n const lexAndLang = getLexiconAndLanguage(field);\n //console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console\n const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));\n const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);\n //console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console\n const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');\n const sf0 = clone(field.subfields.find(sf => sf.code === '0'));\n const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe\n const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};\n return newField;\n }\n\n function getLexiconAndLanguage(field) {\n const subfield2 = field.subfields.find(sf => sf.code === '2');\n if (subfield2.value === 'slm/fin') {\n return {'lex': 'slm', 'lang': 'fin'};\n }\n if (subfield2.value === 'slm/swe') {\n return {'lex': 'slm', 'lang': 'swe'};\n }\n if (subfield2.value === 'yso/fin') {\n return {'lex': 'yso', 'lang': 'fin'};\n }\n if (subfield2.value === 'yso/swe') {\n return {'lex': 'yso', 'lang': 'swe'};\n }\n return {};\n }\n\n async function getPrefLabel(field) {\n // Tag vs $2 correlation has already been checked!\n const uri = fieldToUri(field);\n if (!uri) { // $0 is invalid or sumthing\n return undefined;\n }\n const prefLabels = await getTermData(uri);\n if (!prefLabels) { // Sanity check. Miss caused by illegal id etc.\n nvdebug(`No labels found for ${uri}`, debug);\n return undefined;\n }\n const lexData = getLexiconAndLanguage(field); // $2 data\n const lang = changeAbbr(lexData.lang);\n\n\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n\n const prefLabel = prefLabels.find(pl => pl.lang === lang);\n //console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console\n if (prefLabel.value === subfieldA.value) {\n nvdebug(`'${fieldToString(field)}' requires translating`, debug);\n return prefLabels;\n }\n return undefined;\n }\n\n function swapLanguageCodeBetweenLanguages(code) {\n if (swapLanguageCode[code]) {\n return swapLanguageCode[code];\n }\n return code;\n }\n\n function changeAbbr(abbr) {\n if (changeAbbrHash[abbr]) {\n return changeAbbrHash[abbr];\n }\n return abbr;\n }\n\n function swaggerQuery(uri) {\n // This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;\n return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data\n }\n\n async function getTermData(uri) {\n //console.log(`getTermData(${uri})`); // eslint-disable-line no-console\n if (termCache[uri]) { // Don't think current implementation uses the cache any more.\n //console.log(`CACHED ${uri}`); // eslint-disable-line no-console\n return termCache[uri];\n }\n const tmp = await getTermDataFromFinto(uri);\n termCache[uri] = tmp;\n return tmp;\n }\n\n async function getTermDataFromFinto(uri) {\n const headers = {'Accept': 'application/json'};\n const uri2 = swaggerQuery(uri);\n\n const response = await fetch(uri2, {method: 'GET', headers});\n if (!response.ok) {\n return undefined;\n }\n const json = await response.json();\n\n if (!json.graph) {\n return undefined;\n }\n const arr = json.graph;\n const [hit] = arr.filter(row => row.uri === uri);\n //console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console\n return hit.prefLabel;\n }\n\n\n function fieldToUri(field) {\n const lex = mapTagToLex(field.tag);\n\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n const id = subfield0.value.replace(/^[^0-9]+/u, '');\n if (lex === 'yso') {\n //return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;\n return `http://www.yso.fi/onto/yso/p${id}`;\n }\n if (lex === 'slm') {\n return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;\n }\n return undefined;\n }\n\n function isRelevantField(field, lang) {\n const fieldAsString = fieldToString(field);\n\n // We should probably allow an optional $8 as the first subfield.\n if (!fieldAsString.match(/^... #7 \u2021a [^\u2021]+ \u20212 [^\u2021]+ \u20210 [^\u2021]+(?: \u20219 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {\n return false;\n }\n const lex = mapTagToLex(field.tag);\n const lexLang = `${lex}/${lang}`;\n if (!fieldHasSubfield(field, '2', lexLang)) {\n return false;\n }\n return fieldHasValidSubfield0(field);\n }\n\n function fieldHasValidSubfield0(field) {\n const lex = mapTagToLex(field.tag);\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n if (lex === 'yso' && subfield0.value.match(/^http:\\/\\/www\\.yso\\.fi\\/onto\\/yso\\/p[0-9]+$/u)) {\n return true;\n }\n if (lex === 'slm' && subfield0.value.match(/^http:\\/\\/urn\\.fi\\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {\n return true;\n }\n return false;\n }\n\n function getMisses(fieldList1, fieldList2) {\n return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));\n }\n\n function hasSubfield0Match(field, pairFields) {\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));\n }\n\n\n function mapTagToLex(tag) {\n if (tag === '655') {\n return 'slm';\n }\n return 'yso';\n }\n\n\n /*\n function getValidIdentifiers(record, tag, lang) {\n const lex = mapTagToLex(tag);\n const subfield2Value = `${lex}/${lang}`;\n const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter\n return [];\n }\n */\n\n}\n\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,WAAW;AAClB,OAAO,uBAAuB;AAC9B,SAAQ,kBAAkB,eAAe,eAAc;AAGvD,MAAM,QAAQ,kBAAkB,0DAA0D;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import clone from 'clone';\nimport createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug} from './utils.js';\n\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:translate-terms');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nconst defaultTags = ['648', '650', '651', '655'];\n\nconst swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};\nconst changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};\n\nconst termCache = {};\n\n// Author(s): Nicholas Volk\n// eslint-disable-next-line max-lines-per-function\nexport default function () {\n\n\n return {\n description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',\n validate, fix\n };\n\n async function fix(record) {\n const newFields = await getFields(record, defaultTags, []);\n\n newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debugDev));\n\n newFields.forEach(nf => record.insertField(nf));\n\n const newFieldsAsStrings = newFields.map(f => fieldToString(f));\n\n\n return {message: [], fix: newFieldsAsStrings, valid: true};\n }\n\n async function validate(record) {\n const newFields = await getFields(record, defaultTags, []);\n if (newFields.length === 0) {\n return {'message': [], 'valid': true};\n }\n const messages = newFields.map(f => fieldToString(f));\n\n return {'message': messages, 'valid': false};\n }\n\n async function getFields(record, tags, fieldsToAdd) {\n const [currTag, ...remainingTags] = tags;\n if (!currTag) {\n return fieldsToAdd;\n }\n const missingFields = await deriveMissingFields(record, currTag);\n\n const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);\n return tmp;\n }\n\n function getPairlessFinnishAndSwedishFields(record, tag) {\n const expectedLex = mapTagToLex(tag);\n if (!expectedLex) {\n return [];\n }\n const fields = record.get(tag);\n const finnishFields = fields.filter(f => isTranslatable(f, 'fin'));\n const swedishFields = fields.filter(f => isTranslatable(f, 'swe'));\n const finnishOnly = getMisses(finnishFields, swedishFields);\n const swedishOnly = getMisses(swedishFields, finnishFields);\n\n //nvdebug(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`, debugDev);\n return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));\n\n function tagAndFieldAgree(field) {\n // Check that tag and $2 value are pairable:\n const lexData = getLexiconAndLanguage(field); // $2 data\n return expectedLex === lexData.lex;\n }\n }\n\n async function deriveMissingFields(record, tag) {\n const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);\n\n // Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)\n // Did a proper implementation in drop-terms.js...\n let prefLabels = [];\n for (let i=0; i < pairlessFields.length; i += 1) {\n prefLabels[i] = await getPrefLabel(pairlessFields[i]);\n }\n\n const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));\n return missingFields.filter(f => f);\n }\n\n function pairField(field, prefLabels) {\n if (!prefLabels) {\n return undefined;\n }\n //nvdebug(`pairField() WP 1: ${fieldToString(field)}`, debugDev);\n const lexAndLang = getLexiconAndLanguage(field);\n //nvdebug(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`, debugDev);\n const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));\n const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);\n //nvdebug(`pairField() WP 4: ${JSON.stringify(prefLabel)}`, debugDev);\n const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');\n const sf0 = clone(field.subfields.find(sf => sf.code === '0'));\n const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe\n const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};\n return newField;\n }\n\n\n\n async function getPrefLabel(field) {\n // Pre-requisite: tag vs $2 correlation has already been checked!\n const uri = fieldToUri(field);\n if (!uri) { // $0 is invalid or sumthing\n return undefined;\n }\n\n const data = await getTermData(uri);\n\n if (!data) { // Sanity check. Miss caused by illegal id etc.\n nvdebug(`No labels found for ${uri}`, debugDev);\n return undefined;\n }\n\n const prefLabels = data.prefLabel;\n\n const lexData = getLexiconAndLanguage(field); // $2 data\n const lang = changeAbbr(lexData.lang); // fi <=> fin (finto use 2 chars, we use 3-letters)\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n\n if (isLabel(prefLabels, subfieldA.value, lang)) {\n return prefLabels;\n }\n return undefined;\n }\n\n\n function fieldToUri(field) {\n const lex = mapTagToLex(field.tag);\n\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n const id = subfield0.value.replace(/^[^0-9]+/u, '');\n return buildUri(lex, id);\n }\n\n function isTranslatable(field, lang) {\n const fieldAsString = fieldToString(field);\n\n // We should probably allow an optional $8 as the first subfield.\n if (!fieldAsString.match(/^... #7 (?: \u20218 [^\u2021]+ )*\u2021a [^\u2021]+ \u20212 [^\u2021]+ \u20210 [^\u2021]+(?: \u20219 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {\n return false;\n }\n const lex = mapTagToLex(field.tag);\n const lexLang = `${lex}/${lang}`;\n if (!fieldHasSubfield(field, '2', lexLang)) {\n return false;\n }\n return fieldHasValidSubfield0(field);\n }\n\n\n function getMisses(fieldList1, fieldList2) {\n return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));\n }\n\n function hasSubfield0Match(field, pairFields) {\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));\n }\n\n\n\n\n\n /*\n function getValidIdentifiers(record, tag, lang) {\n const lex = mapTagToLex(tag);\n const subfield2Value = `${lex}/${lang}`;\n const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter\n return [];\n }\n */\n\n}\n\nexport function fieldHasValidSubfield0(field, defaultLex = undefined) {\n const lex = defaultLex || mapTagToLex(field.tag);\n return field.subfields.some(sf => isValidSubfield0(sf, lex));\n}\n\nexport function isValidSubfield0(subfield, lex = '???') {\n if (subfield.code !== '0') {\n return false;\n }\n // 2025-12-10: supports both http and https as well. Note that translation will copy the original $0 idenfifier even though it might be non-standard.\n // Note that currently 'http' is teh standard!!!\n if (['yso', 'yso/fin', 'yso/swe'].includes(lex) && subfield.value.match(/^https?:\\/\\/www\\.yso\\.fi\\/onto\\/yso\\/p[0-9]+$/u)) {\n return true;\n }\n if (['slm', 'slm/fin', 'slm/swe'].includes(lex) && subfield.value.match(/^https?:\\/\\/urn\\.fi\\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {\n return true;\n }\n return false;\n}\n\n\nexport function buildUri(lex, id) {\n if (['yso', 'yso/fin', 'yso/swe'].includes(lex)) {\n //return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;\n return `http://www.yso.fi/onto/yso/p${id}`;\n }\n if (['slm', 'slm/fin', 'slm/swe'].includes(lex)) {\n return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;\n }\n return undefined;\n}\n\nfunction mapTagToLex(tag) {\n if (tag === '655') {\n return 'slm';\n }\n return 'yso';\n}\n\nexport async function getTermData(uri) {\n nvdebug(`getTermData(${uri})`, debugDev);\n if (termCache[uri]) { // Don't think current implementation uses the cache any more.\n //nvdebug(`CACHED ${uri}`, debugDev);\n return termCache[uri];\n }\n const tmp = await getTermDataFromFinto(uri);\n termCache[uri] = tmp;\n return tmp;\n}\n\nasync function getTermDataFromFinto(uri) {\n const headers = {'Accept': 'application/json'};\n const uri2 = swaggerQuery(uri);\n\n const response = await fetch(uri2, {method: 'GET', headers});\n if (!response.ok) {\n return undefined;\n }\n const json = await response.json();\n\n if (!json.graph) {\n return undefined;\n }\n const arr = json.graph;\n const [hit] = arr.filter(row => row.uri === uri);\n const subset = {\n prefLabel: processLabel(hit?.prefLabel || undefined),\n altLabel: processLabel(hit?.altLabel || undefined)\n };\n //nvdebug(`NEW JSON: ${JSON.stringify(hit)}`, debugDev);\n\n return subset;\n\n function swaggerQuery(uri) {\n // This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;\n return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data\n }\n\n function processLabel(label) {\n if (typeof label === 'object') {\n if (Array.isArray(label)) {\n return label;\n }\n return [label];\n }\n return [];\n }\n}\n\nexport function getLexiconAndLanguage(field) {\n // Assumes that field has exactly one $2\n const subfield2 = field.subfields.find(sf => sf.code === '2');\n if (subfield2) {\n if (subfield2.value === 'slm/fin') {\n return {'lex': 'slm', 'lang': 'fin'};\n }\n if (subfield2.value === 'slm/swe') {\n return {'lex': 'slm', 'lang': 'swe'};\n }\n if (subfield2.value === 'yso/fin') {\n return {'lex': 'yso', 'lang': 'fin'};\n }\n if (subfield2.value === 'yso/swe') {\n return {'lex': 'yso', 'lang': 'swe'};\n }\n }\n return {};\n}\n\n\n\nexport function isLabel(labels, term, lang = undefined) {\n const twoLetterLanguageCode = lang && lang.length === 3 ? changeAbbr(lang) : lang;\n return labels.some(l => isMatch(l));\n\n function isMatch(label) {\n if (label.value !== term) {\n return false;\n }\n if (!twoLetterLanguageCode) { // If language code is not defined, any hit will do\n return true;\n }\n return label.lang === twoLetterLanguageCode;\n }\n}\n\n\n function changeAbbr(abbr) {\n if (changeAbbrHash[abbr]) {\n return changeAbbrHash[abbr];\n }\n return abbr;\n }\n\n\n function swapLanguageCodeBetweenLanguages(code) {\n if (swapLanguageCode[code]) {\n return swapLanguageCode[code];\n }\n return code;\n }"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["uri"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
|
-
import createDebugLogger from "debug";
|
|
3
2
|
import fetchMock from "fetch-mock";
|
|
4
3
|
import validatorFactory from "./translate-terms.js";
|
|
5
4
|
import { MarcRecord } from "@natlibfi/marc-record";
|
|
@@ -13,6 +12,7 @@ const uris = [
|
|
|
13
12
|
"http://www.yso.fi/onto/yso/p6196061969",
|
|
14
13
|
"http://urn.fi/URN:NBN:fi:au:slm:s161"
|
|
15
14
|
];
|
|
15
|
+
const useMock = false;
|
|
16
16
|
generateTests({
|
|
17
17
|
callback,
|
|
18
18
|
path: [import.meta.dirname, "..", "test-fixtures", "translate-terms"],
|
|
@@ -23,23 +23,20 @@ generateTests({
|
|
|
23
23
|
},
|
|
24
24
|
hooks: {
|
|
25
25
|
before: async () => {
|
|
26
|
-
|
|
26
|
+
if (useMock) {
|
|
27
|
+
fetchMock.mockGlobal().get(`https://api.finto.fi/rest/v1/data?uri=${uris[0]}&format=application%2Fjson`, { status: 200, headers: {}, body: fakeData }).get(`https://api.finto.fi/rest/v1/data?uri=${uris[1]}&format=application%2Fjson`, { status: 200, headers: {}, body: fakeData }).get(`https://api.finto.fi/rest/v1/data?uri=${uris[2]}&format=application%2Fjson`, { status: 200, headers: {}, body: fakeData }).get(`https://api.finto.fi/rest/v1/data?uri=${uris[3]}&format=application%2Fjson`, { status: 200, headers: {}, body: fakeData }).get(`https://api.finto.fi/rest/v1/data?uri=${uris[4]}&format=application%2Fjson`, { status: 200, headers: {}, body: fakeData });
|
|
28
|
+
}
|
|
27
29
|
testValidatorFactory();
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
});
|
|
31
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/translate-terms:test");
|
|
32
33
|
async function testValidatorFactory() {
|
|
33
34
|
const validator = await validatorFactory();
|
|
34
35
|
assert.equal(typeof validator, "object");
|
|
35
36
|
assert.equal(typeof validator.description, "string");
|
|
36
37
|
assert.equal(typeof validator.validate, "function");
|
|
37
38
|
}
|
|
38
|
-
async function callback({ getFixture,
|
|
39
|
-
if (enabled === false) {
|
|
40
|
-
debug("TEST SKIPPED!");
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
39
|
+
async function callback({ getFixture, fix = false }) {
|
|
43
40
|
const validator = await validatorFactory();
|
|
44
41
|
const record = new MarcRecord(getFixture("record.json"));
|
|
45
42
|
const expectedResult = getFixture("expectedResult.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/translate-terms.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\n//import createDebugLogger from 'debug';\nimport fetchMock from 'fetch-mock';\n\nimport validatorFactory from './translate-terms.js';\n\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport {fakeData} from '../test-fixtures/translate-terms-data.js';\n\nconst uris = [\n 'http://www.yso.fi/onto/yso/p13299',\n 'http://www.yso.fi/onto/yso/p111739',\n 'http://www.yso.fi/onto/yso/p6197061979',\n 'http://www.yso.fi/onto/yso/p6196061969',\n 'http://urn.fi/URN:NBN:fi:au:slm:s161'\n];\n\nconst useMock = false;\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'translate-terms'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n\n if (useMock){ \n fetchMock.mockGlobal()\n .get(`https://api.finto.fi/rest/v1/data?uri=${uris[0]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})\n .get(`https://api.finto.fi/rest/v1/data?uri=${uris[1]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})\n .get(`https://api.finto.fi/rest/v1/data?uri=${uris[2]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})\n .get(`https://api.finto.fi/rest/v1/data?uri=${uris[3]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})\n .get(`https://api.finto.fi/rest/v1/data?uri=${uris[4]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData});\n }\n\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-terms:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AAEnB,OAAO,eAAe;AAEtB,OAAO,sBAAsB;AAE7B,SAAQ,kBAAiB;AACzB,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,SAAQ,gBAAe;AAEvB,MAAM,OAAO;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,UAAU;AAEhB,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,iBAAiB;AAAA,EACpE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAElB,UAAI,SAAQ;AACV,kBAAU,WAAW,EACpB,IAAI,yCAAyC,KAAK,CAAC,CAAC,8BAA8B,EAAC,QAAQ,KAAK,SAAS,CAAC,GAAG,MAAM,SAAQ,CAAC,EAC5H,IAAI,yCAAyC,KAAK,CAAC,CAAC,8BAA8B,EAAC,QAAQ,KAAK,SAAS,CAAC,GAAG,MAAM,SAAQ,CAAC,EAC5H,IAAI,yCAAyC,KAAK,CAAC,CAAC,8BAA8B,EAAC,QAAQ,KAAK,SAAS,CAAC,GAAG,MAAM,SAAQ,CAAC,EAC5H,IAAI,yCAAyC,KAAK,CAAC,CAAC,8BAA8B,EAAC,QAAQ,KAAK,SAAS,CAAC,GAAG,MAAM,SAAQ,CAAC,EAC5H,IAAI,yCAAyC,KAAK,CAAC,CAAC,8BAA8B,EAAC,QAAQ,KAAK,SAAS,CAAC,GAAG,MAAM,SAAQ,CAAC;AAAA,MAC/H;AAEA,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/typeOfDate-008.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import createDebugLogger from "debug";
|
|
2
|
+
import { nvdebug } from "./utils.js";
|
|
2
3
|
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/typeOfDate-008");
|
|
4
|
+
const debugDev = debug.extend("dev");
|
|
3
5
|
export default function() {
|
|
4
6
|
return {
|
|
5
7
|
description: "Validates 008 06",
|
|
@@ -11,7 +13,7 @@ export default function() {
|
|
|
11
13
|
const c06 = f008.value.substring(6, 7);
|
|
12
14
|
const c1114 = f008.value.substring(11, 15);
|
|
13
15
|
if (c06 === "t" && !/[0-9u]{4}/u.test(c1114)) {
|
|
14
|
-
|
|
16
|
+
nvdebug("is t and not valid 1114", debugDev);
|
|
15
17
|
return { valid: false, message: "Invalid 008 06" };
|
|
16
18
|
}
|
|
17
19
|
return { valid: true };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/typeOfDate-008.js"],
|
|
4
|
-
"sourcesContent": ["import createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/typeOfDate-008');\n\nexport default function () {\n return {\n description: 'Validates 008 06',\n validate,\n fix\n };\n\n function validate(record) {\n const [f008] = record.get(/008/u);\n const c06 = f008.value.substring(6, 7);\n const c1114 = f008.value.substring(11, 15);\n // if 008 06 = s, and 11-14 = #### (not year/digits)\n if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {\n
|
|
5
|
-
"mappings": "AAAA,OAAO,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import createDebugLogger from 'debug';\nimport { nvdebug } from './utils.js';\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/typeOfDate-008');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nexport default function () {\n return {\n description: 'Validates 008 06',\n validate,\n fix\n };\n\n function validate(record) {\n const [f008] = record.get(/008/u);\n const c06 = f008.value.substring(6, 7);\n const c1114 = f008.value.substring(11, 15);\n // if 008 06 = s, and 11-14 = #### (not year/digits)\n if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {\n nvdebug('is t and not valid 1114', debugDev);\n return {valid: false, message: 'Invalid 008 06'};\n }\n\n return {valid: true};\n }\n\n function fix(record) {\n // LDR/06=t ja 11-14=####, niin LDR/06 muutetaan s:ksi\n const [f008] = record.pop(/008/u);\n const c06 = f008.value.substring(6, 7);\n const c1114 = f008.value.substring(11, 15);\n // if 008 06 = s, and 11-14 = #### (not year/digits)\n if (c06 === 't' && !(/[0-9u]{4}/u).test(c1114)) {\n f008.value = `${f008.value.substring(0, 6)}s${f008.value.substring(7)}`;\n record.insertField(f008);\n return true;\n }\n\n record.insertField(f008);\n return true;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,uBAAuB;AAC9B,SAAS,eAAe;AAExB,MAAM,QAAQ,kBAAkB,yDAAyD;AAEzF,MAAM,WAAW,MAAM,OAAO,KAAK;AAEnC,0BAA2B;AACzB,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAEA,WAAS,SAAS,QAAQ;AACxB,UAAM,CAAC,IAAI,IAAI,OAAO,IAAI,MAAM;AAChC,UAAM,MAAM,KAAK,MAAM,UAAU,GAAG,CAAC;AACrC,UAAM,QAAQ,KAAK,MAAM,UAAU,IAAI,EAAE;AAEzC,QAAI,QAAQ,OAAO,CAAE,aAAc,KAAK,KAAK,GAAG;AAC9C,cAAQ,2BAA2B,QAAQ;AAC3C,aAAO,EAAC,OAAO,OAAO,SAAS,iBAAgB;AAAA,IACjD;AAEA,WAAO,EAAC,OAAO,KAAI;AAAA,EACrB;AAEA,WAAS,IAAI,QAAQ;AAEnB,UAAM,CAAC,IAAI,IAAI,OAAO,IAAI,MAAM;AAChC,UAAM,MAAM,KAAK,MAAM,UAAU,GAAG,CAAC;AACrC,UAAM,QAAQ,KAAK,MAAM,UAAU,IAAI,EAAE;AAEzC,QAAI,QAAQ,OAAO,CAAE,aAAc,KAAK,KAAK,GAAG;AAC9C,WAAK,QAAQ,GAAG,KAAK,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,UAAU,CAAC,CAAC;AACrE,aAAO,YAAY,IAAI;AACvB,aAAO;AAAA,IACT;AAEA,WAAO,YAAY,IAAI;AACvB,WAAO;AAAA,EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/update-field-540.js"],
|
|
4
|
-
"sourcesContent": ["//import createDebugLogger from 'debug';\nimport {fieldToString} from './utils.js';\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540');\n\n// Author(s): Nicholas Volk\nexport default function () {\n\n return {\n description: 'Validator for field 540 (modernization as per MELKEHITYS-2431)',\n validate, fix\n };\n\n function fix(record) {\n const fixedFields = getFieldsThatUseOldFormat(record, true);\n\n const fixedFieldsAsStrings = fixedFields.map(f => fieldToString(f));\n\n return {message: [], fix: fixedFieldsAsStrings, valid: true};\n }\n\n function validate(record) {\n const yeOldeFields = getFieldsThatUseOldFormat(record, false);\n if (yeOldeFields.length === 0) {\n return {'message': [], 'valid': true};\n }\n const messages = yeOldeFields.map(f => fieldToString(f));\n\n return {'message': messages, 'valid': false};\n }\n\n}\n\n\nconst licences = [\n {'license': 'CC BY 4.0', 'url': 'https://creativecommons.org/licenses/by/4.0/deed.fi'},\n {'license': 'CC BY-NC 4.0', 'url': 'https://creativecommons.org/licenses/by-nc/4.0/deed.fi'},\n {'license': 'CC BY-NC-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fi'},\n {'license': 'CC BY-NC-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-sa/4.0/deed.fi'},\n {'license': 'CC BY-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nd/4.0/deed.fi'},\n {'license': 'CC BY-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-sa/4.0/deed.fi'},\n {'license': 'CC0 1.0', 'url': 'https://creativecommons.org/publicdomain/zero/1.0/deed.fi'}, // not seen/unused\n {'license': 'Public domain', 'url': 'https://creativecommons.org/publicdomain/mark/1.0/deed.fi'}\n];\n\nfunction findSubfieldIndex(field, subfield) {\n subfield.nvtmp = 1;\n const index = field.subfields.findIndex(sf => sf.nvtmp === 1);\n delete subfield.nvtmp;\n return index;\n}\n\nfunction validLicenseInSubfieldC(subfieldC, license) {\n if (subfieldC.code !== 'c') {\n return false;\n }\n //nvdebug(`Compare ${subfieldC.value} vs ${license.license}
|
|
5
|
-
"mappings": "AACA,SAAQ,
|
|
4
|
+
"sourcesContent": ["//import createDebugLogger from 'debug';\nimport {fieldToString /*, nvdebug*/} from './utils.js';\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540');\n//const debugData = debug.extend('data');\n//const debugDev = debug.extend('dev');\n\n// Author(s): Nicholas Volk\nexport default function () {\n\n return {\n description: 'Validator for field 540 (modernization as per MELKEHITYS-2431)',\n validate, fix\n };\n\n function fix(record) {\n const fixedFields = getFieldsThatUseOldFormat(record, true);\n\n const fixedFieldsAsStrings = fixedFields.map(f => fieldToString(f));\n\n return {message: [], fix: fixedFieldsAsStrings, valid: true};\n }\n\n function validate(record) {\n const yeOldeFields = getFieldsThatUseOldFormat(record, false);\n if (yeOldeFields.length === 0) {\n return {'message': [], 'valid': true};\n }\n const messages = yeOldeFields.map(f => fieldToString(f));\n\n return {'message': messages, 'valid': false};\n }\n\n}\n\n\nconst licences = [\n {'license': 'CC BY 4.0', 'url': 'https://creativecommons.org/licenses/by/4.0/deed.fi'},\n {'license': 'CC BY-NC 4.0', 'url': 'https://creativecommons.org/licenses/by-nc/4.0/deed.fi'},\n {'license': 'CC BY-NC-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fi'},\n {'license': 'CC BY-NC-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-sa/4.0/deed.fi'},\n {'license': 'CC BY-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nd/4.0/deed.fi'},\n {'license': 'CC BY-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-sa/4.0/deed.fi'},\n {'license': 'CC0 1.0', 'url': 'https://creativecommons.org/publicdomain/zero/1.0/deed.fi'}, // not seen/unused\n {'license': 'Public domain', 'url': 'https://creativecommons.org/publicdomain/mark/1.0/deed.fi'}\n];\n\nfunction findSubfieldIndex(field, subfield) {\n subfield.nvtmp = 1;\n const index = field.subfields.findIndex(sf => sf.nvtmp === 1);\n delete subfield.nvtmp;\n return index;\n}\n\nfunction validLicenseInSubfieldC(subfieldC, license) {\n if (subfieldC.code !== 'c') {\n return false;\n }\n //nvdebug(`Compare ${subfieldC.value} vs ${license.license}`, debugDev);\n return license.license === subfieldC.value;\n}\n\nfunction validUrlInSubfieldU(subfieldU, license) {\n if (subfieldU.code !== 'u') {\n return false;\n }\n //nvdebug(`Compare ${subfieldU.value} vs ${license.url}`, debugDev);\n return license.url === subfieldU.value;\n}\n\n\nfunction fixC(field, subfieldC) {\n // MELINDA-2431_\n subfieldC.code = 'f';\n const index = findSubfieldIndex(field, subfieldC);\n field.subfields.splice(index + 1, 0, {'code': '2', 'value': 'cc'});\n}\n\nfunction fieldHasOldCcLicense(field, fix) {\n if (field.tag !== '540') {\n return false;\n }\n //nvdebug(`NORM 540: ${fieldToString(field)}`, debugDev);\n const validLicense = licences.find(license => field.subfields.some(sf => validLicenseInSubfieldC(sf, license)) && field.subfields.some(sf => validUrlInSubfieldU(sf, license)));\n if (!validLicense) {\n return false;\n }\n //nvdebug(` Found valid license`, debugDev);\n if (fix) {\n const subfieldsC = field.subfields.filter(sf => validLicenseInSubfieldC(sf, validLicense));\n subfieldsC.forEach(c => fixC(field, c));\n }\n\n return true;\n}\n\n\nfunction getFieldsThatUseOldFormat(record, fix) {\n return record.fields.filter(f => fieldHasOldCcLicense(f, fix));\n}\n\n"],
|
|
5
|
+
"mappings": "AACA,SAAQ,qBAAkC;AAO1C,0BAA2B;AAEzB,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IAAU;AAAA,EACZ;AAEA,WAAS,IAAI,QAAQ;AACnB,UAAM,cAAc,0BAA0B,QAAQ,IAAI;AAE1D,UAAM,uBAAuB,YAAY,IAAI,OAAK,cAAc,CAAC,CAAC;AAElE,WAAO,EAAC,SAAS,CAAC,GAAG,KAAK,sBAAsB,OAAO,KAAI;AAAA,EAC7D;AAEA,WAAS,SAAS,QAAQ;AACxB,UAAM,eAAe,0BAA0B,QAAQ,KAAK;AAC5D,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAC,WAAW,CAAC,GAAG,SAAS,KAAI;AAAA,IACtC;AACA,UAAM,WAAW,aAAa,IAAI,OAAK,cAAc,CAAC,CAAC;AAEvD,WAAO,EAAC,WAAW,UAAU,SAAS,MAAK;AAAA,EAC7C;AAEF;AAGA,MAAM,WAAW;AAAA,EACf,EAAC,WAAW,aAAa,OAAO,sDAAqD;AAAA,EACrF,EAAC,WAAW,gBAAgB,OAAO,yDAAwD;AAAA,EAC3F,EAAC,WAAW,mBAAmB,OAAO,4DAA2D;AAAA,EACjG,EAAC,WAAW,mBAAmB,OAAO,4DAA2D;AAAA,EACjG,EAAC,WAAW,gBAAgB,OAAO,yDAAwD;AAAA,EAC3F,EAAC,WAAW,gBAAgB,OAAO,yDAAwD;AAAA,EAC3F,EAAC,WAAW,WAAW,OAAO,4DAA2D;AAAA;AAAA,EACzF,EAAC,WAAW,iBAAiB,OAAO,4DAA2D;AACjG;AAEA,SAAS,kBAAkB,OAAO,UAAU;AAC1C,WAAS,QAAQ;AACjB,QAAM,QAAQ,MAAM,UAAU,UAAU,QAAM,GAAG,UAAU,CAAC;AAC5D,SAAO,SAAS;AAChB,SAAO;AACT;AAEA,SAAS,wBAAwB,WAAW,SAAS;AACnD,MAAI,UAAU,SAAS,KAAK;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,YAAY,UAAU;AACvC;AAEA,SAAS,oBAAoB,WAAW,SAAS;AAC/C,MAAI,UAAU,SAAS,KAAK;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,QAAQ,UAAU;AACnC;AAGA,SAAS,KAAK,OAAO,WAAW;AAE9B,YAAU,OAAO;AACjB,QAAM,QAAQ,kBAAkB,OAAO,SAAS;AAChD,QAAM,UAAU,OAAO,QAAQ,GAAG,GAAG,EAAC,QAAQ,KAAK,SAAS,KAAI,CAAC;AACnE;AAEA,SAAS,qBAAqB,OAAO,KAAK;AACxC,MAAI,MAAM,QAAQ,OAAO;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,SAAS,KAAK,aAAW,MAAM,UAAU,KAAK,QAAM,wBAAwB,IAAI,OAAO,CAAC,KAAK,MAAM,UAAU,KAAK,QAAM,oBAAoB,IAAI,OAAO,CAAC,CAAC;AAC9K,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,KAAK;AACP,UAAM,aAAa,MAAM,UAAU,OAAO,QAAM,wBAAwB,IAAI,YAAY,CAAC;AACzF,eAAW,QAAQ,OAAK,KAAK,OAAO,CAAC,CAAC;AAAA,EACxC;AAEA,SAAO;AACT;AAGA,SAAS,0BAA0B,QAAQ,KAAK;AAC9C,SAAO,OAAO,OAAO,OAAO,OAAK,qBAAqB,GAAG,GAAG,CAAC;AAC/D;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
|
|
|
3
3
|
import validatorFactory from "./update-field-540.js";
|
|
4
4
|
import { READERS } from "@natlibfi/fixura";
|
|
5
5
|
import generateTests from "@natlibfi/fixugen";
|
|
6
|
-
import createDebugLogger from "debug";
|
|
7
6
|
generateTests({
|
|
8
7
|
callback,
|
|
9
8
|
path: [import.meta.dirname, "..", "test-fixtures", "update-field-540"],
|
|
@@ -18,18 +17,13 @@ generateTests({
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/update-field-540:test");
|
|
22
20
|
async function testValidatorFactory() {
|
|
23
21
|
const validator = await validatorFactory();
|
|
24
22
|
assert(validator).to.be.an("object").that.has.any.keys("description", "validate");
|
|
25
23
|
assert(validator.description).to.be.a("string");
|
|
26
24
|
assert(validator.validate).to.be.a("function");
|
|
27
25
|
}
|
|
28
|
-
async function callback({ getFixture,
|
|
29
|
-
if (enabled === false) {
|
|
30
|
-
debug("TEST SKIPPED!");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
33
27
|
const validator = await validatorFactory();
|
|
34
28
|
const record = new MarcRecord(getFixture("record.json"));
|
|
35
29
|
const expectedResult = getFixture("expectedResult.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/update-field-540.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './update-field-540.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './update-field-540.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'update-field-540'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert(validator)\n .to.be.an('object')\n .that.has.any.keys('description', 'validate');\n\n assert(validator.description).to.be.a('string');\n assert(validator.validate).to.be.a('function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,kBAAkB;AAAA,EACrE,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,SAAS,EACb,GAAG,GAAG,GAAG,QAAQ,EACjB,KAAK,IAAI,IAAI,KAAK,eAAe,UAAU;AAE9C,SAAO,UAAU,WAAW,EAAE,GAAG,GAAG,EAAE,QAAQ;AAC9C,SAAO,UAAU,QAAQ,EAAE,GAAG,GAAG,EAAE,UAAU;AAC/C;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|