@natlibfi/marc-record-validators-melinda 13.0.3 → 13.0.4-alpha.1
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/dist/index.js
CHANGED
|
@@ -49,7 +49,6 @@ import SanitizeVocabularySourceCodes from "./sanitize-vocabulary-source-codes.js
|
|
|
49
49
|
import SortFields from "./sortFields.js";
|
|
50
50
|
import SortRelatorTerms from "./sortRelatorTerms.js";
|
|
51
51
|
import SortSubfields from "./sortSubfields.js";
|
|
52
|
-
import SortTags from "./sort-tags.js";
|
|
53
52
|
import SubfieldValueNormalizations from "./subfieldValueNormalizations.js";
|
|
54
53
|
import SubfieldExclusion from "./subfield-exclusion.js";
|
|
55
54
|
import Sync007And300 from "./sync-007-and-300.js";
|
|
@@ -139,7 +138,6 @@ export {
|
|
|
139
138
|
SanitizeVocabularySourceCodes,
|
|
140
139
|
SortRelatorTerms,
|
|
141
140
|
SortSubfields,
|
|
142
|
-
SortTags,
|
|
143
141
|
SubfieldExclusion,
|
|
144
142
|
SubfieldValueNormalizations,
|
|
145
143
|
Sync007And300,
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.js"],
|
|
4
|
-
"sourcesContent": ["import AccessRights from './access-rights.js';\nimport AddMissingField041 from './addMissingField041.js';\nimport AddMissingField336 from './addMissingField336.js';\nimport AddMissingField337 from './addMissingField337.js';\nimport AddMissingField338 from './addMissingField338.js';\nimport Cyrillux from './cyrillux.js';\nimport CyrilluxUsemarconReplacement from './cyrillux-usemarcon-replacement.js';\nimport DisambiguateSeriesStatements from './disambiguateSeriesStatements.js';\nimport DoubleCommas from './double-commas.js';\nimport DuplicatesInd1 from './duplicates-ind1.js';\nimport EmptyFields from './empty-fields.js';\nimport EndingPunctuation from './ending-punctuation.js';\nimport EndingWhitespace from './ending-whitespace.js';\nimport Field008CharacterGroups from './field-008-18-34-character-groups.js';\nimport Field505Separators from './field-505-separators.js';\nimport Field521Fix from './field-521-fix.js';\nimport FieldExclusion from './field-exclusion.js';\nimport FieldStructure from './field-structure.js';\nimport FieldsPresent from './fields-present.js';\nimport Fix33X from './fix-33X.js';\nimport FixCountryCodes from './fix-country-codes.js';\nimport FixLanguageCodes from './fix-language-codes.js';\nimport FixRelatorTerms from './fixRelatorTerms.js';\nimport FixSami041 from './fix-sami-041.js';\nimport FixedFields from './fixed-fields.js';\nimport IdenticalFields from './identical-fields.js';\nimport IndicatorFixes from './indicator-fixes.js';\nimport IsbnIssn from './isbn-issn.js';\nimport ItemLanguage from './item-language.js';\nimport MergeField500Lisapainokset from './mergeField500Lisapainokset.js';\nimport MergeFields from './merge-fields/index.js';\nimport MergeRelatorTermFields from './mergeRelatorTermFields.js';\nimport Modernize502 from './modernize-502.js';\nimport MultipleSubfield0s from './multiple-subfield-0.js';\nimport NonBreakingSpace from './non-breaking-space.js';\nimport NormalizeDashes from './normalize-dashes.js';\nimport NormalizeIdentifiers from './normalize-identifiers.js';\nimport NormalizeQualifyingInformation from './normalize-qualifying-information.js';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics.js';\nimport Punctuation from './punctuation/index.js';\nimport Punctuation2 from './punctuation2.js';\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers.js';\nimport Remove041zxx from './remove-041-zxx.js';\nimport RemoveDuplicateDataFields from './removeDuplicateDataFields.js';\nimport RemoveInferiorDataFields from './removeInferiorDataFields.js';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda.js';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s.js';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes.js';\nimport SortFields from './sortFields.js';\nimport SortRelatorTerms from './sortRelatorTerms.js';\nimport SortSubfields from './sortSubfields.js';\
|
|
5
|
-
"mappings": "AAAA,OAAO,kBAAkB;AACzB,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,cAAc;AACrB,OAAO,kCAAkC;AACzC,OAAO,kCAAkC;AACzC,OAAO,kBAAkB;AACzB,OAAO,oBAAoB;AAC3B,OAAO,iBAAiB;AACxB,OAAO,uBAAuB;AAC9B,OAAO,sBAAsB;AAC7B,OAAO,6BAA6B;AACpC,OAAO,wBAAwB;AAC/B,OAAO,iBAAiB;AACxB,OAAO,oBAAoB;AAC3B,OAAO,oBAAoB;AAC3B,OAAO,mBAAmB;AAC1B,OAAO,YAAY;AACnB,OAAO,qBAAqB;AAC5B,OAAO,sBAAsB;AAC7B,OAAO,qBAAqB;AAC5B,OAAO,gBAAgB;AACvB,OAAO,iBAAiB;AACxB,OAAO,qBAAqB;AAC5B,OAAO,oBAAoB;AAC3B,OAAO,cAAc;AACrB,OAAO,kBAAkB;AACzB,OAAO,gCAAgC;AACvC,OAAO,iBAAiB;AACxB,OAAO,4BAA4B;AACnC,OAAO,kBAAkB;AACzB,OAAO,wBAAwB;AAC/B,OAAO,sBAAsB;AAC7B,OAAO,qBAAqB;AAC5B,OAAO,0BAA0B;AACjC,OAAO,oCAAoC;AAC3C,OAAO,6BAA6B;AACpC,OAAO,iBAAiB;AACxB,OAAO,kBAAkB;AACzB,OAAO,sCAAsC;AAC7C,OAAO,kBAAkB;AACzB,OAAO,+BAA+B;AACtC,OAAO,8BAA8B;AACrC,OAAO,6BAA6B;AACpC,OAAO,+BAA+B;AACtC,OAAO,mCAAmC;AAC1C,OAAO,gBAAgB;AACvB,OAAO,sBAAsB;AAC7B,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import AccessRights from './access-rights.js';\nimport AddMissingField041 from './addMissingField041.js';\nimport AddMissingField336 from './addMissingField336.js';\nimport AddMissingField337 from './addMissingField337.js';\nimport AddMissingField338 from './addMissingField338.js';\nimport Cyrillux from './cyrillux.js';\nimport CyrilluxUsemarconReplacement from './cyrillux-usemarcon-replacement.js';\nimport DisambiguateSeriesStatements from './disambiguateSeriesStatements.js';\nimport DoubleCommas from './double-commas.js';\nimport DuplicatesInd1 from './duplicates-ind1.js';\nimport EmptyFields from './empty-fields.js';\nimport EndingPunctuation from './ending-punctuation.js';\nimport EndingWhitespace from './ending-whitespace.js';\nimport Field008CharacterGroups from './field-008-18-34-character-groups.js';\nimport Field505Separators from './field-505-separators.js';\nimport Field521Fix from './field-521-fix.js';\nimport FieldExclusion from './field-exclusion.js';\nimport FieldStructure from './field-structure.js';\nimport FieldsPresent from './fields-present.js';\nimport Fix33X from './fix-33X.js';\nimport FixCountryCodes from './fix-country-codes.js';\nimport FixLanguageCodes from './fix-language-codes.js';\nimport FixRelatorTerms from './fixRelatorTerms.js';\nimport FixSami041 from './fix-sami-041.js';\nimport FixedFields from './fixed-fields.js';\nimport IdenticalFields from './identical-fields.js';\nimport IndicatorFixes from './indicator-fixes.js';\nimport IsbnIssn from './isbn-issn.js';\nimport ItemLanguage from './item-language.js';\nimport MergeField500Lisapainokset from './mergeField500Lisapainokset.js';\nimport MergeFields from './merge-fields/index.js';\nimport MergeRelatorTermFields from './mergeRelatorTermFields.js';\nimport Modernize502 from './modernize-502.js';\nimport MultipleSubfield0s from './multiple-subfield-0.js';\nimport NonBreakingSpace from './non-breaking-space.js';\nimport NormalizeDashes from './normalize-dashes.js';\nimport NormalizeIdentifiers from './normalize-identifiers.js';\nimport NormalizeQualifyingInformation from './normalize-qualifying-information.js';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics.js';\nimport Punctuation from './punctuation/index.js';\nimport Punctuation2 from './punctuation2.js';\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers.js';\nimport Remove041zxx from './remove-041-zxx.js';\nimport RemoveDuplicateDataFields from './removeDuplicateDataFields.js';\nimport RemoveInferiorDataFields from './removeInferiorDataFields.js';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda.js';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s.js';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes.js';\nimport SortFields from './sortFields.js';\nimport SortRelatorTerms from './sortRelatorTerms.js';\nimport SortSubfields from './sortSubfields.js';\n// import StripPunctuation from './stripPunctuation'; // Can we add this here? Should be used very cautiosly!\nimport SubfieldValueNormalizations from './subfieldValueNormalizations.js';\nimport SubfieldExclusion from './subfield-exclusion.js';\nimport Sync007And300 from './sync-007-and-300.js';\nimport SyncLanguage from './sync-language.js';\nimport TranslateTerms from './translate-terms.js';\nimport TypeOfDateF008 from './typeOfDate-008.js';\nimport UnicodeDecomposition from './unicode-decomposition.js';\nimport UpdateField540 from './update-field-540.js';\nimport Urn from './urn.js';\n\nimport {getCounterpart} from './merge-fields/counterpartField.js';\n\nimport {postprocessRecords} from './merge-fields/mergeOrAddPostprocess.js';\nimport {mergeField} from './merge-fields/mergeField.js';\nimport {fieldGetOccurrenceNumberPairs, fieldGetUnambiguousOccurrenceNumber, fieldHasValidSubfield6, fieldToNormalizedString, fieldsToNormalizedString, get6s,\n isSubfield6Pair, isValidSubfield6, intToOccurrenceNumberString,\n recordGetMaxSubfield6OccurrenceNumberAsInteger, resetSubfield6Tag, subfield6ResetOccurrenceNumber, subfield6GetOccurrenceNumber,\n subfield6GetOccurrenceNumberAsInteger} from './subfield6Utils.js';\n\nimport {getSubfield8LinkingNumber, isValidSubfield8, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils.js';\n\nimport {recordFixRelatorTerms} from './fixRelatorTerms.js';\nimport {fieldTrimSubfieldValues} from './normalizeFieldForComparison.js';\nimport {baseHasEqualOrHigherEncodingLevel, deleteAllPrepublicationNotesFromField500InNonPubRecord, encodingLevelIsBetterThanPrepublication, getEncodingLevel, isEnnakkotietoField, isEnnakkotietoSubfield} from './prepublicationUtils.js';\nimport {melindaFieldSpecs} from './melindaCustomMergeFields.js';\n\nimport {cloneAndRemovePunctuation} from './normalizeFieldForComparison.js';\nimport {removeWorsePrepubField500s, removeWorsePrepubField594s} from './prepublicationUtils.js';\nimport {fieldFixPunctuation} from './punctuation2.js';\nimport {recordResetSubfield6OccurrenceNumbers} from './reindexSubfield6OccurenceNumbers.js';\nimport {sortAdjacentSubfields} from './sortSubfields.js';\nimport {fieldHasSubfield, fieldToString, fieldsToString, isContentSubfieldCode, tagIsRepeatable} from './utils.js';\n\nexport {\n AccessRights,\n AddMissingField041,\n AddMissingField336,\n AddMissingField337,\n AddMissingField338,\n Cyrillux,\n CyrilluxUsemarconReplacement,\n DisambiguateSeriesStatements,\n DoubleCommas,\n DuplicatesInd1,\n EmptyFields,\n EndingPunctuation,\n EndingWhitespace,\n Field008CharacterGroups,\n Field505Separators,\n Field521Fix,\n FieldExclusion,\n FieldsPresent,\n FieldStructure,\n Fix33X,\n FixCountryCodes,\n FixLanguageCodes,\n FixRelatorTerms,\n FixSami041,\n FixedFields,\n IdenticalFields,\n IndicatorFixes,\n IsbnIssn,\n ItemLanguage,\n\n MergeField500Lisapainokset,\n MergeRelatorTermFields,\n Modernize502, //\n MultipleSubfield0s,\n NonBreakingSpace,\n NormalizeDashes,\n NormalizeIdentifiers,\n NormalizeQualifyingInformation,\n NormalizeUTF8Diacritics,\n Punctuation,\n Punctuation2,\n ResolveOrphanedSubfield6s, // Do this before reindexing! (thus I'm not sticking with alphabetical order here)\n ReindexSubfield6OccurenceNumbers,\n Remove041zxx,\n RemoveDuplicateDataFields,\n RemoveInferiorDataFields,\n ResolvableExtReferences,\n SanitizeVocabularySourceCodes,\n SortRelatorTerms,\n SortSubfields,\n SubfieldExclusion,\n SubfieldValueNormalizations,\n Sync007And300,\n SyncLanguage,\n TranslateTerms,\n TypeOfDateF008,\n UnicodeDecomposition,\n UpdateField540,\n Urn,\n SortFields, // Keep this penultimate\n MergeFields, // Run this last *iff* you want to use this at all\n\n // Functions for processing record... These should probably go to some other project.\n // Too specific for marc-record-js though...\n // 1. generic low level stuff\n getEncodingLevel,\n\n // 2. text normalizations + other generic utils (eg. for similarity comparisons, field merge)\n cloneAndRemovePunctuation,\n fieldFixPunctuation,\n fieldHasSubfield,\n fieldToNormalizedString,\n fieldToString,\n fieldTrimSubfieldValues,\n fieldsToNormalizedString,\n fieldsToString,\n isContentSubfieldCode,\n recordFixRelatorTerms,\n sortAdjacentSubfields,\n tagIsRepeatable,\n\n // 3. prepublication stuff\n baseHasEqualOrHigherEncodingLevel,\n deleteAllPrepublicationNotesFromField500InNonPubRecord,\n encodingLevelIsBetterThanPrepublication,\n isEnnakkotietoField,\n isEnnakkotietoSubfield,\n removeWorsePrepubField500s,\n removeWorsePrepubField594s,\n\n // 4. subfield $6 related functions\n fieldGetOccurrenceNumberPairs,\n get6s,\n fieldGetUnambiguousOccurrenceNumber,\n fieldHasValidSubfield6,\n intToOccurrenceNumberString,\n isSubfield6Pair,\n isValidSubfield6,\n recordGetMaxSubfield6OccurrenceNumberAsInteger,\n recordResetSubfield6OccurrenceNumbers,\n resetSubfield6Tag,\n subfield6ResetOccurrenceNumber,\n subfield6GetOccurrenceNumber,\n subfield6GetOccurrenceNumberAsInteger,\n\n // 5. subfield $8 related functions\n getSubfield8LinkingNumber,\n isValidSubfield8,\n recordGetAllSubfield8LinkingNumbers,\n recordGetFieldsWithSubfield8LinkingNumber,\n\n // 6. merge, other\n getCounterpart, // field merge: finds a similar field with which a field can merge\n melindaFieldSpecs, // contains information about the legal fields and subfields, and their repeatability\n mergeField,\n postprocessRecords // clean-up function that cleans up both base and source record (which may be the same)\n\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,7 +13,7 @@ function subfieldsAreEqual(field1, field2, subfieldCode) {
|
|
|
13
13
|
}
|
|
14
14
|
const sfSet1 = field1.subfields.filter((subfield) => subfield.code === subfieldCode);
|
|
15
15
|
const sfSet2 = field2.subfields.filter((subfield) => subfield.code === subfieldCode);
|
|
16
|
-
return
|
|
16
|
+
return JSON.stringify(sfSet1) === JSON.stringify(sfSet2);
|
|
17
17
|
}
|
|
18
18
|
function subfieldsAreEmpty(field1, field2, subfieldCode) {
|
|
19
19
|
if (!fieldHasSubfield(field1, subfieldCode) && !fieldHasSubfield(field2, subfieldCode)) {
|
|
@@ -80,7 +80,7 @@ function controlSubfield9PermitsMerge(baseField, sourceField) {
|
|
|
80
80
|
const trans1 = baseFieldSubfields9.filter((sf) => subfieldHasTrans(sf));
|
|
81
81
|
const trans2 = sourceFieldSubfields9.filter((sf) => subfieldHasTrans(sf));
|
|
82
82
|
if (trans1.length > 0 && trans2.length > 0) {
|
|
83
|
-
if (
|
|
83
|
+
if (JSON.stringify(trans1) !== JSON.stringify(trans2)) {
|
|
84
84
|
return true;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -134,7 +134,7 @@ function controlSubfield9PermitsMerge(baseField, sourceField) {
|
|
|
134
134
|
}
|
|
135
135
|
return false;
|
|
136
136
|
}
|
|
137
|
-
if (
|
|
137
|
+
if (JSON.stringify(sf9lessField1) === JSON.stringify(sf9lessField2)) {
|
|
138
138
|
return false;
|
|
139
139
|
}
|
|
140
140
|
return true;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/merge-fields/controlSubfields.js"],
|
|
4
|
-
"sourcesContent": ["import {MarcRecord} from '@natlibfi/marc-record';\nimport createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug, nvdebugSubfieldArray, subfieldIsRepeatable, subfieldsAreIdentical} from '../utils.js';\n\nimport {normalizeControlSubfieldValue} from '../normalize-identifiers.js';\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:controlSubfields');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nfunction subfieldsAreEqual(field1, field2, subfieldCode) {\n // Check OK if neither one has given subfield.\n // Check fails if one field has given subfield and the other one does not\n if (!fieldHasSubfield(field1, subfieldCode)) {\n return !fieldHasSubfield(field2, subfieldCode);\n }\n if (!fieldHasSubfield(field2, subfieldCode)) {\n return false;\n }\n // Compare $3 subfields. If everything matches, OK, else FAIL:\n const sfSet1 = field1.subfields.filter(subfield => subfield.code === subfieldCode);\n const sfSet2 = field2.subfields.filter(subfield => subfield.code === subfieldCode);\n return MarcRecord.isEqual(sfSet1, sfSet2);\n}\n\nfunction subfieldsAreEmpty(field1, field2, subfieldCode) {\n if (!fieldHasSubfield(field1, subfieldCode) && !fieldHasSubfield(field2, subfieldCode)) {\n return true;\n }\n return false;\n}\n\n\nfunction sixlessIsSubset(fieldWith6, fieldWithout6) {\n // Remove $0 and $1, and then check that remaining $6-less field is a subset of the one with $6.\n // No need to check indicators.\n // NB! We could use punctuation-stripping here.\n const subset = fieldWithout6.subfields.filter(subfield => !['0', '1'].includes(subfield.code));\n return subset.every(sf => fieldWith6.subfields.some(sf2 => subfieldsAreIdentical(sf, sf2)));\n //return MarcRecord.isEqual(strippedField1, strippedField2);\n}\n\nfunction controlSubfield6PermitsMerge(field1, field2) {\n if (subfieldsAreEmpty(field1, field2, '6')) {\n return true;\n }\n\n // Handle cases where one has a $6 and the other has not:\n // Should this accept $0 (FI-ASTERI-N) vs none?\n if (!fieldHasSubfield(field1, '6') && fieldHasSubfield(field2, '6') && sixlessIsSubset(field2, field1)) {\n return true;\n }\n if (!fieldHasSubfield(field2, '6') && fieldHasSubfield(field1, '6') && sixlessIsSubset(field1, field2)) {\n return true;\n }\n\n // There are at least two (plus) fields involved (Field XXX (one) and field 880 (one plus).\n // Thus this generic solution can't handle them. Postprocess step removes some chains instead!\n debugDev(` controlSubfield6PermitsMerge() fails always on generic part (feature).`);\n return false;\n}\n\nfunction controlSubfield5PermitsMerge(field1, field2) {\n // field1.$5 XOR field2.$5 means false, NEITHER and BOTH mean true, regardless of value\n if (!fieldHasSubfield(field1, '5')) {\n if (!fieldHasSubfield(field2, '5')) {\n return true; // If neither one has $5, it's ok to merge\n }\n // If $5 contents are same, merge can be perfomed:\n const fives1 = field1.subfields.filter(sf => sf.code === '5');\n const fives2 = field2.subfields.filter(sf => sf.code === '5');\n if (fives1.every(sf1 => fives2.some(sf2 => sf1.value === sf2.value)) && fives2.every(sf2 => fives1.some(sf1 => sf1.value === sf2.value))) {\n return true;\n }\n return false;\n }\n if (!fieldHasSubfield(field2, '5')) {\n return false;\n }\n return true;\n}\n\nfunction controlSubfield9PermitsMerge(baseField, sourceField) {\n const baseFieldSubfields9 = baseField.subfields.filter(sf => sf.code === '9');\n const sourceFieldSubfields9 = sourceField.subfields.filter(sf => sf.code === '9');\n\n //nvdebug('CHECK $9', debugDev);\n // There are no $9s. Skip:\n if (baseFieldSubfields9.length === 0 && sourceFieldSubfields9.length === 0) {\n //nvdebug(` No subfield $9 detected`, debugDev);\n return true;\n }\n\n if (keepOrDropPreventsMerge()) {\n nvdebug(` Subfield $9 KEEPs and DROPs disallow merge`, debugDev);\n return false;\n }\n\n if (transPreventsMerge()) {\n nvdebug(` Subfield $9 <TRANS> mismatch disallows merge`, debugDev);\n return false;\n }\n\n //nvdebug('CHECK $9 OK', debugDev);\n\n return true;\n\n function subfieldHasKeepOrDrop(subfield) {\n // nvdebug(`Has <KEEP>? ${subfieldToString(subfield)}`, debugDev);\n return subfield.code === '9' && (/(?:<KEEP>|<DROP>)/u).test(subfield.value);\n }\n\n function subfieldHasTrans(subfield) {\n return subfield.code === '9' && (/<TRANS>/u).test(subfield.value);\n }\n\n function transPreventsMerge() {\n const trans1 = baseFieldSubfields9.filter(sf => subfieldHasTrans(sf));\n const trans2 = sourceFieldSubfields9.filter(sf => subfieldHasTrans(sf));\n if (trans1.length > 0 && trans2.length > 0) {\n if (!MarcRecord.isEqual(trans1, trans2)) {\n return true;\n }\n }\n return false;\n }\n\n function retainSubfieldForKeepComparison(subfield) {\n // Don't compare <KEEP>, <DROP> nor <TRANS> here (<TRANS> has it's own check)\n if (subfieldHasKeepOrDrop(subfield) || subfieldHasTrans(subfield)) {\n return false;\n }\n\n if (['0', '1'].includes(subfield.code)) {\n return false;\n }\n if (['100', '600', '700', '800'].includes(baseField.tag)) {\n // Despite $9 KEEP/DROP, we are interested in merging $d years (better than two separate fields)\n if (['d'].includes(subfield.code)) {\n return false;\n }\n }\n\n\n return true;\n }\n\n function acceptKeeplessSourceSubfield(sourceSubfield, tag, subfieldCode, subfieldValue) {\n if (sourceSubfield.code !== subfieldCode) {\n return false;\n }\n // In this context, there's no need to check the value of a non-repeatable subfield.\n // If value is different, pairing will fail when comparing the subfield itself.\n // This allows us to tolerate little differences in punctuation: different punctuation does not get copied to base,\n // so they don't alter base and and thus redundant when comparing.\n if (!subfieldIsRepeatable(tag, subfieldCode)) {\n return true;\n }\n return sourceSubfield.value === subfieldValue;\n }\n\n function keepOrDropPreventsMerge() {\n const keepOrDrop1 = baseFieldSubfields9.filter(sf => subfieldHasKeepOrDrop(sf));\n const keepOrDrop2 = sourceFieldSubfields9.filter(sf => subfieldHasKeepOrDrop(sf));\n\n if (keepOrDrop1.length === 0 && keepOrDrop2.length === 0) {\n return false;\n }\n\n if (baseField.tag.charAt(0) === '1' && !keepOrDrop2.some(sf => (/<DROP>/u).test(sf.value))) {\n return false;\n }\n\n const sf9lessField1 = baseField.subfields.filter(subfield => retainSubfieldForKeepComparison(subfield));\n const sf9lessField2 = sourceField.subfields.filter(subfield => retainSubfieldForKeepComparison(subfield));\n\n nvdebugSubfieldArray(baseField.subfields, 'FIELD ', debugDev);\n nvdebugSubfieldArray(sf9lessField1, 'FILTER ', debugDev);\n\n nvdebugSubfieldArray(sourceField.subfields, 'FIELD2 ', debugDev);\n nvdebugSubfieldArray(sf9lessField2, 'FILTER2 ', debugDev);\n\n // Keepless field can be a subset field with <KEEP>/<DROP>! Note that punctuation still causes remnants to fail.\n if (keepOrDrop1.length === 0) {\n return !sf9lessField1.every(sf => sf9lessField2.some(sf2 => subfieldsAreIdentical(sf, sf2)));\n }\n // However, to alleviate the above-mentioned punctuation problem, we can check keep/drop-less *source* subfields\n if (keepOrDrop2.length === 0) {\n const unhandledSubfield = sf9lessField2.find(sf2 => !sf9lessField1.some(sf => acceptKeeplessSourceSubfield(sf2, baseField.tag, sf.code, sf.value)));\n if (unhandledSubfield) {\n //nvdebug(`Failed to pair ${subfieldToString(unhandledSubfield)}`, debugDev);\n return true;\n }\n //return !sf9lessField2.every(sf2 => sf9lessField1.some(sf => subfieldsAreIdentical(sf, sf2)));\n return false;\n }\n\n //nvdebugSubfieldArray(sf9lessField2, 'SOURCE(?)', debugDev);\n //nvdebugSubfieldArray(sf9lessField1, 'BASE(?) ', debugDev);\n\n // $9 <KEEP> or <DROP> detected on both fields.\n // Non-keeps and non-drops must be equal, otherwise fail:\n if (MarcRecord.isEqual(sf9lessField1, sf9lessField2)) {\n return false;\n }\n // Prevent:\n return true;\n }\n}\n\nfunction getPrefix(value) {\n const normalizedValue = normalizeControlSubfieldValue(value);\n\n if (normalizedValue.match(/^\\([^)]+\\)[0-9]+$/u)) {\n return normalizedValue.substr(0, normalizedValue.indexOf(')') + 1);\n }\n\n if (value.match(/^https?:\\/\\//u)) {\n return normalizedValue.substr(0, normalizedValue.lastIndexOf('/') + 1);\n }\n\n return '';\n}\n\nfunction isMatchAfterNormalization(currSubfield, otherField) {\n // NB! Add implement isni normalizations (to normalize.js) and apply here:\n const normalizedCurrSubfieldValue = normalizeControlSubfieldValue(currSubfield.value);\n const prefix = getPrefix(normalizedCurrSubfieldValue);\n\n //debug(`FFS-PREFIX '${prefix}'`);\n // Look for same prefix + different identifier\n const hits = otherField.subfields.filter(sf2 => sf2.code === currSubfield.code && normalizeControlSubfieldValue(sf2.value).indexOf(prefix) === 0);\n if (hits.length === 0 || // <-- Nothing found, so it can't be a mismatch\n // Every opposing subfields match:\n hits.every(sf2 => normalizedCurrSubfieldValue === normalizeControlSubfieldValue(sf2.value))) {\n debugDev(`Subfield \u2021${currSubfield.code} check OK: No opposing ${prefix} prefixes found.`);\n return true;\n }\n\n debugDev(`Subfield \u2021${currSubfield.code} check FAILED: \u2021${currSubfield.code} '${currSubfield.value}' vs \u2021${currSubfield.code} '${hits[0].value}'.`);\n return false;\n}\n\nfunction controlSubfieldContainingIdentifierPermitsMerge(field1, field2, subfieldCode) {\n if (!fieldHasSubfield(field1, subfieldCode, null) || !fieldHasSubfield(field2, subfieldCode, null)) {\n return true;\n }\n\n const result = field1.subfields.every(subfield => {\n if (subfield.code !== subfieldCode) {\n return true;\n }\n\n debugDev(`Compare \u2021${subfieldCode} '${subfield.value}' with '${fieldToString(field2)}'.`);\n if (fieldHasSubfield(field2, field1.code, field1.value)) {\n return true;\n }\n\n return isMatchAfterNormalization(subfield, field2, subfieldCode);\n });\n\n if (!result) {\n debugDev(`Control subfield '${subfieldCode}' check failed.`);\n return false;\n }\n return true;\n}\n\nconst controlSubfieldsContainingIdentifier = ['w', '0', '1', '2']; // 2 ain't identifier, but the logic can be applied here as well\n\nexport function controlSubfieldsPermitMerge(baseField, sourceField) {\n // Check $w, $0, $1, $2 (which isn't an identifier per se, but the sama logic can be applied)\n if (!controlSubfieldsContainingIdentifier.every(subfieldCode => controlSubfieldContainingIdentifierPermitsMerge(baseField, sourceField, subfieldCode))) {\n //debug(' control subfields with identifiers failed');\n return false;\n }\n\n if (!subfieldsAreEqual(baseField, sourceField, '3')) {\n //debug(' similar control subfield fails');\n return false;\n }\n\n if (!controlSubfield5PermitsMerge(baseField, sourceField) || !controlSubfield6PermitsMerge(baseField, sourceField) || !controlSubfield9PermitsMerge(baseField, sourceField)) {\n return false;\n }\n // We fully prevent merging $8 subfields here, as they affect multiple fields! Also these would get screwed:\n // 38211 |8 3\\u |a kuoro |2 seko\n // 38211 |8 6\\u |a kuoro |2 seko |9 VIOLA<DROP>\n // Thus only copy works with $8...\n if (!subfieldsAreEmpty(baseField, sourceField, '8')) {\n // We could alleviate this a bit esp. for non-repeatable fields.\n // At least, if the source has '8' and otherwise the two fields are identical...\n const subsetOfSourceField = {\n 'tag': sourceField.tag,\n 'ind1': sourceField.ind1,\n 'ind2': sourceField.ind2, subfields: sourceField.subfields.filter(sf => sf.code !== '8')\n };\n if (fieldToString(baseField) === fieldToString(subsetOfSourceField)) {\n return true;\n }\n //debug(' csf8 failed');\n return false;\n }\n\n return true;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAQ,kBAAiB;AACzB,OAAO,uBAAuB;AAC9B,SAAQ,kBAAkB,eAAe,SAAS,sBAAsB,sBAAsB,6BAA4B;AAE1H,SAAQ,qCAAoC;AAE5C,MAAM,QAAQ,kBAAkB,wEAAwE;AAExG,MAAM,WAAW,MAAM,OAAO,KAAK;AAEnC,SAAS,kBAAkB,QAAQ,QAAQ,cAAc;AAGvD,MAAI,CAAC,iBAAiB,QAAQ,YAAY,GAAG;AAC3C,WAAO,CAAC,iBAAiB,QAAQ,YAAY;AAAA,EAC/C;AACA,MAAI,CAAC,iBAAiB,QAAQ,YAAY,GAAG;AAC3C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,OAAO,UAAU,OAAO,cAAY,SAAS,SAAS,YAAY;AACjF,QAAM,SAAS,OAAO,UAAU,OAAO,cAAY,SAAS,SAAS,YAAY;AACjF,SAAO,
|
|
4
|
+
"sourcesContent": ["import {MarcRecord} from '@natlibfi/marc-record';\nimport createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug, nvdebugSubfieldArray, subfieldIsRepeatable, subfieldsAreIdentical} from '../utils.js';\n\nimport {normalizeControlSubfieldValue} from '../normalize-identifiers.js';\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:controlSubfields');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nfunction subfieldsAreEqual(field1, field2, subfieldCode) {\n // Check OK if neither one has given subfield.\n // Check fails if one field has given subfield and the other one does not\n if (!fieldHasSubfield(field1, subfieldCode)) {\n return !fieldHasSubfield(field2, subfieldCode);\n }\n if (!fieldHasSubfield(field2, subfieldCode)) {\n return false;\n }\n // Compare $3 subfields. If everything matches, OK, else FAIL:\n const sfSet1 = field1.subfields.filter(subfield => subfield.code === subfieldCode);\n const sfSet2 = field2.subfields.filter(subfield => subfield.code === subfieldCode);\n return JSON.stringify(sfSet1) === JSON.stringify(sfSet2);\n}\n\nfunction subfieldsAreEmpty(field1, field2, subfieldCode) {\n if (!fieldHasSubfield(field1, subfieldCode) && !fieldHasSubfield(field2, subfieldCode)) {\n return true;\n }\n return false;\n}\n\n\nfunction sixlessIsSubset(fieldWith6, fieldWithout6) {\n // Remove $0 and $1, and then check that remaining $6-less field is a subset of the one with $6.\n // No need to check indicators.\n // NB! We could use punctuation-stripping here.\n const subset = fieldWithout6.subfields.filter(subfield => !['0', '1'].includes(subfield.code));\n return subset.every(sf => fieldWith6.subfields.some(sf2 => subfieldsAreIdentical(sf, sf2)));\n}\n\nfunction controlSubfield6PermitsMerge(field1, field2) {\n if (subfieldsAreEmpty(field1, field2, '6')) {\n return true;\n }\n\n // Handle cases where one has a $6 and the other has not:\n // Should this accept $0 (FI-ASTERI-N) vs none?\n if (!fieldHasSubfield(field1, '6') && fieldHasSubfield(field2, '6') && sixlessIsSubset(field2, field1)) {\n return true;\n }\n if (!fieldHasSubfield(field2, '6') && fieldHasSubfield(field1, '6') && sixlessIsSubset(field1, field2)) {\n return true;\n }\n\n // There are at least two (plus) fields involved (Field XXX (one) and field 880 (one plus).\n // Thus this generic solution can't handle them. Postprocess step removes some chains instead!\n debugDev(` controlSubfield6PermitsMerge() fails always on generic part (feature).`);\n return false;\n}\n\nfunction controlSubfield5PermitsMerge(field1, field2) {\n // field1.$5 XOR field2.$5 means false, NEITHER and BOTH mean true, regardless of value\n if (!fieldHasSubfield(field1, '5')) {\n if (!fieldHasSubfield(field2, '5')) {\n return true; // If neither one has $5, it's ok to merge\n }\n // If $5 contents are same, merge can be perfomed:\n const fives1 = field1.subfields.filter(sf => sf.code === '5');\n const fives2 = field2.subfields.filter(sf => sf.code === '5');\n if (fives1.every(sf1 => fives2.some(sf2 => sf1.value === sf2.value)) && fives2.every(sf2 => fives1.some(sf1 => sf1.value === sf2.value))) {\n return true;\n }\n return false;\n }\n if (!fieldHasSubfield(field2, '5')) {\n return false;\n }\n return true;\n}\n\nfunction controlSubfield9PermitsMerge(baseField, sourceField) {\n const baseFieldSubfields9 = baseField.subfields.filter(sf => sf.code === '9');\n const sourceFieldSubfields9 = sourceField.subfields.filter(sf => sf.code === '9');\n\n //nvdebug('CHECK $9', debugDev);\n // There are no $9s. Skip:\n if (baseFieldSubfields9.length === 0 && sourceFieldSubfields9.length === 0) {\n //nvdebug(` No subfield $9 detected`, debugDev);\n return true;\n }\n\n if (keepOrDropPreventsMerge()) {\n nvdebug(` Subfield $9 KEEPs and DROPs disallow merge`, debugDev);\n return false;\n }\n\n if (transPreventsMerge()) {\n nvdebug(` Subfield $9 <TRANS> mismatch disallows merge`, debugDev);\n return false;\n }\n\n //nvdebug('CHECK $9 OK', debugDev);\n\n return true;\n\n function subfieldHasKeepOrDrop(subfield) {\n // nvdebug(`Has <KEEP>? ${subfieldToString(subfield)}`, debugDev);\n return subfield.code === '9' && (/(?:<KEEP>|<DROP>)/u).test(subfield.value);\n }\n\n function subfieldHasTrans(subfield) {\n return subfield.code === '9' && (/<TRANS>/u).test(subfield.value);\n }\n\n function transPreventsMerge() {\n const trans1 = baseFieldSubfields9.filter(sf => subfieldHasTrans(sf));\n const trans2 = sourceFieldSubfields9.filter(sf => subfieldHasTrans(sf));\n if (trans1.length > 0 && trans2.length > 0) {\n if (JSON.stringify(trans1) !== JSON.stringify(trans2)) {\n return true;\n }\n }\n return false;\n }\n\n function retainSubfieldForKeepComparison(subfield) {\n // Don't compare <KEEP>, <DROP> nor <TRANS> here (<TRANS> has it's own check)\n if (subfieldHasKeepOrDrop(subfield) || subfieldHasTrans(subfield)) {\n return false;\n }\n\n if (['0', '1'].includes(subfield.code)) {\n return false;\n }\n if (['100', '600', '700', '800'].includes(baseField.tag)) {\n // Despite $9 KEEP/DROP, we are interested in merging $d years (better than two separate fields)\n if (['d'].includes(subfield.code)) {\n return false;\n }\n }\n\n\n return true;\n }\n\n function acceptKeeplessSourceSubfield(sourceSubfield, tag, subfieldCode, subfieldValue) {\n if (sourceSubfield.code !== subfieldCode) {\n return false;\n }\n // In this context, there's no need to check the value of a non-repeatable subfield.\n // If value is different, pairing will fail when comparing the subfield itself.\n // This allows us to tolerate little differences in punctuation: different punctuation does not get copied to base,\n // so they don't alter base and and thus redundant when comparing.\n if (!subfieldIsRepeatable(tag, subfieldCode)) {\n return true;\n }\n return sourceSubfield.value === subfieldValue;\n }\n\n function keepOrDropPreventsMerge() {\n const keepOrDrop1 = baseFieldSubfields9.filter(sf => subfieldHasKeepOrDrop(sf));\n const keepOrDrop2 = sourceFieldSubfields9.filter(sf => subfieldHasKeepOrDrop(sf));\n\n if (keepOrDrop1.length === 0 && keepOrDrop2.length === 0) {\n return false;\n }\n\n if (baseField.tag.charAt(0) === '1' && !keepOrDrop2.some(sf => (/<DROP>/u).test(sf.value))) {\n return false;\n }\n\n const sf9lessField1 = baseField.subfields.filter(subfield => retainSubfieldForKeepComparison(subfield));\n const sf9lessField2 = sourceField.subfields.filter(subfield => retainSubfieldForKeepComparison(subfield));\n\n nvdebugSubfieldArray(baseField.subfields, 'FIELD ', debugDev);\n nvdebugSubfieldArray(sf9lessField1, 'FILTER ', debugDev);\n\n nvdebugSubfieldArray(sourceField.subfields, 'FIELD2 ', debugDev);\n nvdebugSubfieldArray(sf9lessField2, 'FILTER2 ', debugDev);\n\n // Keepless field can be a subset field with <KEEP>/<DROP>! Note that punctuation still causes remnants to fail.\n if (keepOrDrop1.length === 0) {\n return !sf9lessField1.every(sf => sf9lessField2.some(sf2 => subfieldsAreIdentical(sf, sf2)));\n }\n // However, to alleviate the above-mentioned punctuation problem, we can check keep/drop-less *source* subfields\n if (keepOrDrop2.length === 0) {\n const unhandledSubfield = sf9lessField2.find(sf2 => !sf9lessField1.some(sf => acceptKeeplessSourceSubfield(sf2, baseField.tag, sf.code, sf.value)));\n if (unhandledSubfield) {\n //nvdebug(`Failed to pair ${subfieldToString(unhandledSubfield)}`, debugDev);\n return true;\n }\n //return !sf9lessField2.every(sf2 => sf9lessField1.some(sf => subfieldsAreIdentical(sf, sf2)));\n return false;\n }\n\n //nvdebugSubfieldArray(sf9lessField2, 'SOURCE(?)', debugDev);\n //nvdebugSubfieldArray(sf9lessField1, 'BASE(?) ', debugDev);\n\n // $9 <KEEP> or <DROP> detected on both fields.\n // Non-keeps and non-drops must be equal, otherwise fail:\n if (JSON.stringify(sf9lessField1) === JSON.stringify(sf9lessField2)) {\n return false;\n }\n // Prevent:\n return true;\n }\n}\n\nfunction getPrefix(value) {\n const normalizedValue = normalizeControlSubfieldValue(value);\n\n if (normalizedValue.match(/^\\([^)]+\\)[0-9]+$/u)) {\n return normalizedValue.substr(0, normalizedValue.indexOf(')') + 1);\n }\n\n if (value.match(/^https?:\\/\\//u)) {\n return normalizedValue.substr(0, normalizedValue.lastIndexOf('/') + 1);\n }\n\n return '';\n}\n\nfunction isMatchAfterNormalization(currSubfield, otherField) {\n // NB! Add implement isni normalizations (to normalize.js) and apply here:\n const normalizedCurrSubfieldValue = normalizeControlSubfieldValue(currSubfield.value);\n const prefix = getPrefix(normalizedCurrSubfieldValue);\n\n //debug(`FFS-PREFIX '${prefix}'`);\n // Look for same prefix + different identifier\n const hits = otherField.subfields.filter(sf2 => sf2.code === currSubfield.code && normalizeControlSubfieldValue(sf2.value).indexOf(prefix) === 0);\n if (hits.length === 0 || // <-- Nothing found, so it can't be a mismatch\n // Every opposing subfields match:\n hits.every(sf2 => normalizedCurrSubfieldValue === normalizeControlSubfieldValue(sf2.value))) {\n debugDev(`Subfield \u2021${currSubfield.code} check OK: No opposing ${prefix} prefixes found.`);\n return true;\n }\n\n debugDev(`Subfield \u2021${currSubfield.code} check FAILED: \u2021${currSubfield.code} '${currSubfield.value}' vs \u2021${currSubfield.code} '${hits[0].value}'.`);\n return false;\n}\n\nfunction controlSubfieldContainingIdentifierPermitsMerge(field1, field2, subfieldCode) {\n if (!fieldHasSubfield(field1, subfieldCode, null) || !fieldHasSubfield(field2, subfieldCode, null)) {\n return true;\n }\n\n const result = field1.subfields.every(subfield => {\n if (subfield.code !== subfieldCode) {\n return true;\n }\n\n debugDev(`Compare \u2021${subfieldCode} '${subfield.value}' with '${fieldToString(field2)}'.`);\n if (fieldHasSubfield(field2, field1.code, field1.value)) {\n return true;\n }\n\n return isMatchAfterNormalization(subfield, field2, subfieldCode);\n });\n\n if (!result) {\n debugDev(`Control subfield '${subfieldCode}' check failed.`);\n return false;\n }\n return true;\n}\n\nconst controlSubfieldsContainingIdentifier = ['w', '0', '1', '2']; // 2 ain't identifier, but the logic can be applied here as well\n\nexport function controlSubfieldsPermitMerge(baseField, sourceField) {\n // Check $w, $0, $1, $2 (which isn't an identifier per se, but the sama logic can be applied)\n if (!controlSubfieldsContainingIdentifier.every(subfieldCode => controlSubfieldContainingIdentifierPermitsMerge(baseField, sourceField, subfieldCode))) {\n //debug(' control subfields with identifiers failed');\n return false;\n }\n\n if (!subfieldsAreEqual(baseField, sourceField, '3')) {\n //debug(' similar control subfield fails');\n return false;\n }\n\n if (!controlSubfield5PermitsMerge(baseField, sourceField) || !controlSubfield6PermitsMerge(baseField, sourceField) || !controlSubfield9PermitsMerge(baseField, sourceField)) {\n return false;\n }\n // We fully prevent merging $8 subfields here, as they affect multiple fields! Also these would get screwed:\n // 38211 |8 3\\u |a kuoro |2 seko\n // 38211 |8 6\\u |a kuoro |2 seko |9 VIOLA<DROP>\n // Thus only copy works with $8...\n if (!subfieldsAreEmpty(baseField, sourceField, '8')) {\n // We could alleviate this a bit esp. for non-repeatable fields.\n // At least, if the source has '8' and otherwise the two fields are identical...\n const subsetOfSourceField = {\n 'tag': sourceField.tag,\n 'ind1': sourceField.ind1,\n 'ind2': sourceField.ind2, subfields: sourceField.subfields.filter(sf => sf.code !== '8')\n };\n if (fieldToString(baseField) === fieldToString(subsetOfSourceField)) {\n return true;\n }\n //debug(' csf8 failed');\n return false;\n }\n\n return true;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/NatLibFi/marc-record-validators-melinda"
|
|
15
15
|
},
|
|
16
16
|
"license": "MIT",
|
|
17
|
-
"version": "13.0.
|
|
17
|
+
"version": "13.0.4-alpha.1",
|
|
18
18
|
"main": "./dist/index.js",
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public"
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@natlibfi/iso9-1995": "^1.1.4",
|
|
39
|
-
"@natlibfi/issn-verify": "^2.0.
|
|
39
|
+
"@natlibfi/issn-verify": "^2.0.4",
|
|
40
40
|
"@natlibfi/marc-record": "^11.0.3",
|
|
41
|
-
"@natlibfi/marc-record-serializers": "^11.0.
|
|
41
|
+
"@natlibfi/marc-record-serializers": "^11.0.4",
|
|
42
42
|
"@natlibfi/marc-record-validate": "^9.0.1",
|
|
43
43
|
"@natlibfi/melinda-commons": "^15.0.2",
|
|
44
44
|
"@natlibfi/sfs-4900": "^2.0.0",
|
|
45
|
-
"@natlibfi/sru-client": "^7.0.
|
|
45
|
+
"@natlibfi/sru-client": "^7.0.4",
|
|
46
46
|
"clone": "^2.1.2",
|
|
47
47
|
"debug": "^4.4.3",
|
|
48
48
|
"franc": "^6.2.0",
|
package/src/index.js
CHANGED
|
@@ -49,7 +49,6 @@ import SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes.js
|
|
|
49
49
|
import SortFields from './sortFields.js';
|
|
50
50
|
import SortRelatorTerms from './sortRelatorTerms.js';
|
|
51
51
|
import SortSubfields from './sortSubfields.js';
|
|
52
|
-
import SortTags from './sort-tags.js';
|
|
53
52
|
// import StripPunctuation from './stripPunctuation'; // Can we add this here? Should be used very cautiosly!
|
|
54
53
|
import SubfieldValueNormalizations from './subfieldValueNormalizations.js';
|
|
55
54
|
import SubfieldExclusion from './subfield-exclusion.js';
|
|
@@ -135,7 +134,6 @@ export {
|
|
|
135
134
|
SanitizeVocabularySourceCodes,
|
|
136
135
|
SortRelatorTerms,
|
|
137
136
|
SortSubfields,
|
|
138
|
-
SortTags,
|
|
139
137
|
SubfieldExclusion,
|
|
140
138
|
SubfieldValueNormalizations,
|
|
141
139
|
Sync007And300,
|
|
@@ -20,7 +20,7 @@ function subfieldsAreEqual(field1, field2, subfieldCode) {
|
|
|
20
20
|
// Compare $3 subfields. If everything matches, OK, else FAIL:
|
|
21
21
|
const sfSet1 = field1.subfields.filter(subfield => subfield.code === subfieldCode);
|
|
22
22
|
const sfSet2 = field2.subfields.filter(subfield => subfield.code === subfieldCode);
|
|
23
|
-
return
|
|
23
|
+
return JSON.stringify(sfSet1) === JSON.stringify(sfSet2);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function subfieldsAreEmpty(field1, field2, subfieldCode) {
|
|
@@ -37,7 +37,6 @@ function sixlessIsSubset(fieldWith6, fieldWithout6) {
|
|
|
37
37
|
// NB! We could use punctuation-stripping here.
|
|
38
38
|
const subset = fieldWithout6.subfields.filter(subfield => !['0', '1'].includes(subfield.code));
|
|
39
39
|
return subset.every(sf => fieldWith6.subfields.some(sf2 => subfieldsAreIdentical(sf, sf2)));
|
|
40
|
-
//return MarcRecord.isEqual(strippedField1, strippedField2);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
function controlSubfield6PermitsMerge(field1, field2) {
|
|
@@ -118,7 +117,7 @@ function controlSubfield9PermitsMerge(baseField, sourceField) {
|
|
|
118
117
|
const trans1 = baseFieldSubfields9.filter(sf => subfieldHasTrans(sf));
|
|
119
118
|
const trans2 = sourceFieldSubfields9.filter(sf => subfieldHasTrans(sf));
|
|
120
119
|
if (trans1.length > 0 && trans2.length > 0) {
|
|
121
|
-
if (
|
|
120
|
+
if (JSON.stringify(trans1) !== JSON.stringify(trans2)) {
|
|
122
121
|
return true;
|
|
123
122
|
}
|
|
124
123
|
}
|
|
@@ -200,7 +199,7 @@ function controlSubfield9PermitsMerge(baseField, sourceField) {
|
|
|
200
199
|
|
|
201
200
|
// $9 <KEEP> or <DROP> detected on both fields.
|
|
202
201
|
// Non-keeps and non-drops must be equal, otherwise fail:
|
|
203
|
-
if (
|
|
202
|
+
if (JSON.stringify(sf9lessField1) === JSON.stringify(sf9lessField2)) {
|
|
204
203
|
return false;
|
|
205
204
|
}
|
|
206
205
|
// Prevent:
|