@natlibfi/marc-record-validators-melinda 12.0.6 → 12.0.7

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.
Files changed (120) hide show
  1. package/dist/cyrillux.js +11 -11
  2. package/dist/cyrillux.js.map +2 -2
  3. package/dist/dataProvenanceUtils.js +19 -0
  4. package/dist/dataProvenanceUtils.js.map +7 -0
  5. package/dist/index.js +3 -1
  6. package/dist/index.js.map +2 -2
  7. package/dist/merge-fields/controlSubfields.js.map +2 -2
  8. package/dist/merge-fields/counterpartField.js +149 -152
  9. package/dist/merge-fields/counterpartField.js.map +3 -3
  10. package/dist/merge-fields/dataProvenance.js +6 -20
  11. package/dist/merge-fields/dataProvenance.js.map +2 -2
  12. package/dist/merge-fields/index.js +1 -1
  13. package/dist/merge-fields/index.js.map +2 -2
  14. package/dist/merge-fields/mergableIndicator.js +1 -2
  15. package/dist/merge-fields/mergableIndicator.js.map +2 -2
  16. package/dist/merge-fields/mergeConfig.js +2 -0
  17. package/dist/merge-fields/mergeConfig.js.map +2 -2
  18. package/dist/merge-fields/mergeConstraints.js +35 -32
  19. package/dist/merge-fields/mergeConstraints.js.map +3 -3
  20. package/dist/merge-fields/mergeField.js +4 -3
  21. package/dist/merge-fields/mergeField.js.map +2 -2
  22. package/dist/merge-fields/mergeOrAddSubfield.js +8 -7
  23. package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
  24. package/dist/merge-fields/mergeSubfield.js +5 -1
  25. package/dist/merge-fields/mergeSubfield.js.map +2 -2
  26. package/dist/merge-fields/worldKnowledge.js +52 -0
  27. package/dist/merge-fields/worldKnowledge.js.map +2 -2
  28. package/dist/merge-fields.test.js +2 -2
  29. package/dist/merge-fields.test.js.map +2 -2
  30. package/dist/normalize-dashes.js +2 -2
  31. package/dist/normalize-dashes.js.map +2 -2
  32. package/dist/normalizeFieldForComparison.js +8 -14
  33. package/dist/normalizeFieldForComparison.js.map +2 -2
  34. package/dist/prepublicationUtils.js +1 -1
  35. package/dist/prepublicationUtils.js.map +2 -2
  36. package/dist/punctuation2.js +10 -10
  37. package/dist/punctuation2.js.map +2 -2
  38. package/dist/removeDuplicateDataFields.js +1 -24
  39. package/dist/removeDuplicateDataFields.js.map +2 -2
  40. package/dist/removeInferiorDataFields.js +3 -2
  41. package/dist/removeInferiorDataFields.js.map +2 -2
  42. package/dist/sortSubfields.js +19 -19
  43. package/dist/sortSubfields.js.map +2 -2
  44. package/dist/subfield6Utils.js +0 -1
  45. package/dist/subfield6Utils.js.map +2 -2
  46. package/dist/subfield8Utils.js +0 -5
  47. package/dist/subfield8Utils.js.map +2 -2
  48. package/dist/utils.js +29 -3
  49. package/dist/utils.js.map +2 -2
  50. package/package.json +4 -4
  51. package/src/cyrillux.js +11 -11
  52. package/src/dataProvenanceUtils.js +21 -0
  53. package/src/index.js +3 -1
  54. package/src/merge-fields/controlSubfields.js +0 -1
  55. package/src/merge-fields/counterpartField.js +191 -290
  56. package/src/merge-fields/dataProvenance.js +8 -25
  57. package/src/merge-fields/index.js +1 -1
  58. package/src/merge-fields/mergableIndicator.js +1 -2
  59. package/src/merge-fields/mergeConfig.js +2 -1
  60. package/src/merge-fields/mergeConstraints.js +39 -34
  61. package/src/merge-fields/mergeField.js +4 -7
  62. package/src/merge-fields/mergeOrAddSubfield.js +8 -7
  63. package/src/merge-fields/mergeSubfield.js +11 -2
  64. package/src/merge-fields/worldKnowledge.js +72 -3
  65. package/src/merge-fields.test.js +2 -2
  66. package/src/normalize-dashes.js +2 -2
  67. package/src/normalizeFieldForComparison.js +19 -20
  68. package/src/prepublicationUtils.js +1 -1
  69. package/src/punctuation2.js +10 -10
  70. package/src/removeDuplicateDataFields.js +24 -24
  71. package/src/removeInferiorDataFields.js +3 -2
  72. package/src/sortSubfields.js +19 -19
  73. package/src/subfield6Utils.js +1 -1
  74. package/src/subfield8Utils.js +5 -5
  75. package/src/utils.js +39 -12
  76. package/test-fixtures/cyrillux/f14/expectedResult.json +32 -0
  77. package/test-fixtures/cyrillux/f14/metadata.json +10 -0
  78. package/test-fixtures/cyrillux/f14/record.json +14 -0
  79. package/test-fixtures/merge-fields/f042_01/expectedResult.json +12 -0
  80. package/test-fixtures/merge-fields/f042_01/metadata.json +6 -0
  81. package/test-fixtures/merge-fields/f042_01/record.json +13 -0
  82. package/test-fixtures/merge-fields/f06/expectedResult.json +42 -0
  83. package/test-fixtures/merge-fields/f06/metadata.json +6 -0
  84. package/test-fixtures/merge-fields/f06/record.json +41 -0
  85. package/test-fixtures/merge-fields/f07/expectedResult.json +18 -0
  86. package/test-fixtures/merge-fields/f07/metadata.json +6 -0
  87. package/test-fixtures/merge-fields/f07/record.json +18 -0
  88. package/test-fixtures/merge-fields/f08/expectedResult.json +12 -0
  89. package/test-fixtures/merge-fields/f08/metadata.json +7 -0
  90. package/test-fixtures/merge-fields/f08/record.json +10 -0
  91. package/test-fixtures/merge-fields/f09/expectedResult.json +14 -0
  92. package/test-fixtures/merge-fields/f09/metadata.json +6 -0
  93. package/test-fixtures/merge-fields/f09/record.json +14 -0
  94. package/test-fixtures/merge-fields/f10/expectedResult.json +25 -0
  95. package/test-fixtures/merge-fields/f10/metadata.json +6 -0
  96. package/test-fixtures/merge-fields/f10/record.json +25 -0
  97. package/test-fixtures/merge-fields/f11/expectedResult.json +40 -0
  98. package/test-fixtures/merge-fields/f11/metadata.json +7 -0
  99. package/test-fixtures/merge-fields/f11/record.json +50 -0
  100. package/test-fixtures/merge-fields/f12/expectedResult.json +17 -0
  101. package/test-fixtures/merge-fields/f12/metadata.json +6 -0
  102. package/test-fixtures/merge-fields/f12/record.json +25 -0
  103. package/test-fixtures/merge-fields/f13/expectedResult.json +18 -0
  104. package/test-fixtures/merge-fields/f13/metadata.json +6 -0
  105. package/test-fixtures/merge-fields/f13/record.json +28 -0
  106. package/test-fixtures/merge-fields/f14/expectedResult.json +25 -0
  107. package/test-fixtures/merge-fields/f14/metadata.json +6 -0
  108. package/test-fixtures/merge-fields/f14/record.json +25 -0
  109. package/test-fixtures/merge-fields/f300_01/expectedResult.json +9 -0
  110. package/test-fixtures/merge-fields/f300_01/metadata.json +6 -0
  111. package/test-fixtures/merge-fields/f300_01/record.json +8 -0
  112. package/test-fixtures/merge-fields/f300_02/expectedResult.json +13 -0
  113. package/test-fixtures/merge-fields/f300_02/metadata.json +6 -0
  114. package/test-fixtures/merge-fields/f300_02/record.json +16 -0
  115. package/test-fixtures/merge-fields/f490_01/expectedResult.json +13 -0
  116. package/test-fixtures/merge-fields/f490_01/metadata.json +6 -0
  117. package/test-fixtures/merge-fields/f490_01/record.json +16 -0
  118. package/test-fixtures/remove-inferior-datafields/f17/expectedResult.json +11 -0
  119. package/test-fixtures/remove-inferior-datafields/f17/metadata.json +5 -0
  120. package/test-fixtures/remove-inferior-datafields/f17/record.json +15 -0
package/dist/utils.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/utils.js"],
4
- "sourcesContent": ["import createDebugLogger from 'debug';\n\n//import fs from 'fs';\n//import path from 'path';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:utils');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nimport {melindaFieldSpecs} from './melindaCustomMergeFields.js';\n\n//JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'src', 'melindaCustomMergeFields.json'), 'utf8'));\n\nexport function isElectronicMaterial(record) {\n const f337s = record.get('337');\n\n return f337s.length > 0 && f337s.some(f => fieldHasSubfield(f, 'b', 'c') && fieldHasSubfield(f, '2', 'rdamedia'));\n}\n\nexport function nvdebug(message, func = undefined) {\n if (func) {\n func(message);\n }\n //console.info(message); // eslint-disable-line no-console\n}\n\nexport function fieldHasSubfield(field, subfieldCode, subfieldValue = null) {\n if (!field.subfields) {\n return false;\n }\n if (subfieldValue === null) {\n return field.subfields.some(sf => sf.code === subfieldCode);\n }\n return field.subfields.some(sf => sf.code === subfieldCode && subfieldValue === sf.value);\n}\n\nexport function subfieldToString(sf) {\n if (!sf.value) {\n return `\u2021${sf.code}`;\n }\n return `\u2021${sf.code} ${sf.value}`;\n}\n\nfunction normalizeIndicatorValue(val) {\n if (val === ' ') {\n return '#';\n }\n return val;\n}\n\nexport function recordToString(record) {\n const ldr = `LDR ${record.leader}`;\n const fields = record.fields.map(f => fieldToString(f));\n return `${ldr}\\n${fields.join('\\n')}`;\n}\n\nexport function removeSubfield(record, tag, subfieldCode) {\n record.fields = record.fields.map(field => {\n if (field.tag !== tag || !field.subfields) { // Don't procss irrelevant fields\n return field;\n }\n field.subfields = field.subfields.filter(sf => sf.code !== subfieldCode);\n if (field.subfields.length === 0) {\n return false;\n }\n return field;\n }).filter(field => field);\n}\n\nexport function recordRemoveValuelessSubfields(record) {\n record.fields = record.fields.map(field => {\n if (!field.subfields) { // Keep control fields\n return field;\n }\n // Remove empty subfields from datafields:\n field.subfields = field.subfields.filter(sf => sf.value);\n\n if (field.subfields && field.subfields.length === 0) {\n return false; // Return false instead of a field if field has no subfields left. These will soon be filtered out.\n }\n\n return field; //if field has subfields return it\n }).filter(field => field); // Filter those falses out\n}\n\nexport function fieldToString(f) {\n if ('subfields' in f) {\n return `${f.tag} ${normalizeIndicatorValue(f.ind1)}${normalizeIndicatorValue(f.ind2)}${formatSubfields(f)}`;\n }\n return `${f.tag} ${f.value}`;\n\n function formatSubfields(field) {\n return field.subfields.map(sf => ` ${subfieldToString(sf)}`).join('');\n }\n}\n\nexport function fieldsToString(fields) {\n return fields.map(f => fieldToString(f)).join('\\t__SEPARATOR__\\t');\n}\n\nexport function nvdebugFieldArray(fields, prefix = ' ', func = undefined) {\n fields.forEach(field => nvdebug(`${prefix}${fieldToString(field)}`, func));\n}\n\nexport function isControlSubfieldCode(subfieldCode) {\n // NB! Only $w, $0, $1, $5, $6 and $8 are really control subfields. In Finland $9 is oft a control subfield\n // $3 material (part of the whole thing)\n // $4 means 'relationship' (similar to relator terms at least in X00 and similar)\n // $7 is usually provinance subfield. However, it can be stored in other subfields as well. See merge-fields/dataProvenance.js for details\n // However, change this only if needed. Maybe all provinance subfields should return true?\n // This may become relevant when AI starts to create stuff...\n if (['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'w'].includes(subfieldCode)) {\n return true;\n }\n return false;\n}\n\nexport function getCatalogingLanguage(record, defaultCatalogingLanguage = undefined) {\n const [field040] = record.get(/^040$/u);\n if (!field040) {\n return defaultCatalogingLanguage;\n }\n const [b] = field040.subfields.filter(sf => sf.code === 'b');\n if (!b) {\n return defaultCatalogingLanguage;\n }\n return b.value;\n}\n\n\nexport function uniqArray(arr) {\n return arr.filter((val, i) => arr.indexOf(val) === i);\n}\n\nexport function fieldsAreIdentical(field1, field2) {\n if (field1.tag !== field2.tag) { // NB! We are skipping normalizations here on purpose! They should be done beforehand...\n return false;\n }\n return fieldToString(field1) === fieldToString(field2);\n\n // The order of subfields is relevant! Bloody JS idiotisms make people use conditions such as:\n // return field1.subfields.every(sf => field2.subfields.some(sf2 => sf.code === sf2.code && sf.value === sf2.value));\n}\n\nexport function fieldHasNSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n const relevantSubfields = field.subfields.filter(sf => sf.code === subfieldCode);\n //if (subfieldValue === null) {\n return relevantSubfields.length;\n //}\n //const subset = relevantSubfields.filter(value => value === subfieldValue);\n //return subset.length;\n}\n\nexport function removeCopyright(value) {\n return value.replace(/^(?:c|p|\u00A9|\u2117|Cop\\. ?) ?((?:1[0-9][0-9][0-9]|20[012][0-9])\\.?)$/ui, '$1');\n}\n\nfunction isNonStandardNonrepeatableSubfield(tag, subfieldCode) {\n // Put these into config or so...\n if (tag === '264') {\n return ['a', 'b', 'c'].includes(subfieldCode);\n }\n\n if (['336', '337', '338'].includes(tag)) {\n return ['a', 'b', '2'].includes(subfieldCode);\n }\n\n return false;\n}\n\n\nexport function subfieldIsRepeatable(tag, subfieldCode) {\n\n if (isNonStandardNonrepeatableSubfield(tag, subfieldCode)) {\n return false;\n }\n\n // These we know or \"know\":\n // NB! $5 is (according to MARC21 format) non-repeatable, and not usable in all fields, but Melinda has a local exception to this, see MET-300\n if ('0159'.indexOf(subfieldCode) > -1) {\n // Uh, can $0 appear on any field?\n return true;\n }\n\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n nvdebug(` WARNING! Getting field ${tag} data failed! ${fieldSpecs.length} hits. Default value true is used for'${subfieldCode}' .`, debugDev);\n return true;\n }\n\n const subfieldSpecs = fieldSpecs[0].subfields.filter(subfield => subfield.code === subfieldCode);\n // Currently we don't support multiple $6 fields due to re-indexing limitations...\n // Well, $6 is non-repeatable, isn't it?!?\n // (This might actually already be fixed... Marginal issue, but check eventually.)\n if (subfieldSpecs.length !== 1 || subfieldCode === '6') {\n return false; // repeatable if not specified, I guess. Maybe add log or warn?\n }\n return subfieldSpecs[0].repeatable;\n}\n\nfunction marc21GetTagsLegalIndicators(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length === 0) {\n return undefined;\n }\n return fieldSpecs[0].indicators;\n}\n\nexport function marc21GetTagsLegalInd1Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind1;\n}\n\nexport function marc21GetTagsLegalInd2Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind2;\n}\n\nexport function nvdebugSubfieldArray(subfields, prefix = ' ', func = undefined) {\n subfields.forEach(subfield => nvdebug(`${prefix}${subfieldToString(subfield)}`, func));\n}\n\nexport function subfieldsAreIdentical(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code && subfieldA.value === subfieldB.value;\n}\n\nexport function fieldHasMultipleSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n return fieldHasNSubfields(field, subfieldCode) > 1;\n}\n\nexport function hasCopyright(value) {\n const modValue = removeCopyright(value);\n return value !== modValue;\n}\n\n\n\nexport function subfieldArraysContainSameData(arr1, arr2) {\n if ( !arr1.every(sf => arr2.some(sf2 => subfieldsAreIdentical(sf, sf2))) ) {\n return false;\n }\n\n return arr2.every(sf2 => arr1.some(sf => subfieldsAreIdentical(sf, sf2)));\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import createDebugLogger from 'debug';\nimport {melindaFieldSpecs} from './melindaCustomMergeFields.js';\nimport {isDataProvenanceSubfieldCode} from './dataProvenanceUtils.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:utils');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n\n\n//JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'src', 'melindaCustomMergeFields.json'), 'utf8'));\n\nexport function isElectronicMaterial(record) {\n const f337s = record.get('337');\n\n return f337s.length > 0 && f337s.some(f => fieldHasSubfield(f, 'b', 'c') && fieldHasSubfield(f, '2', 'rdamedia'));\n}\n\nexport function nvdebug(message, func = undefined) {\n if (func) {\n func(message);\n }\n //console.info(message); // eslint-disable-line no-console\n}\n\nexport function fieldHasSubfield(field, subfieldCode, subfieldValue = null) {\n if (!field.subfields) {\n return false;\n }\n if (subfieldValue === null) {\n return field.subfields.some(sf => sf.code === subfieldCode);\n }\n return field.subfields.some(sf => sf.code === subfieldCode && subfieldValue === sf.value);\n}\n\nexport function subfieldToString(sf) {\n if (!sf.value) {\n return `\u2021${sf.code}`;\n }\n return `\u2021${sf.code} ${sf.value}`;\n}\n\nfunction normalizeIndicatorValue(val) {\n if (val === ' ') {\n return '#';\n }\n return val;\n}\n\nexport function recordToString(record) {\n const ldr = `LDR ${record.leader}`;\n const fields = record.fields.map(f => fieldToString(f));\n return `${ldr}\\n${fields.join('\\n')}`;\n}\n\nexport function removeSubfield(record, tag, subfieldCode) {\n record.fields = record.fields.map(field => {\n if (field.tag !== tag || !field.subfields) { // Don't procss irrelevant fields\n return field;\n }\n field.subfields = field.subfields.filter(sf => sf.code !== subfieldCode);\n if (field.subfields.length === 0) {\n return false;\n }\n return field;\n }).filter(field => field);\n}\n\nexport function recordRemoveValuelessSubfields(record) {\n record.fields = record.fields.map(field => {\n if (!field.subfields) { // Keep control fields\n return field;\n }\n // Remove empty subfields from datafields:\n field.subfields = field.subfields.filter(sf => sf.value);\n\n if (field.subfields && field.subfields.length === 0) {\n return false; // Return false instead of a field if field has no subfields left. These will soon be filtered out.\n }\n\n return field; //if field has subfields return it\n }).filter(field => field); // Filter those falses out\n}\n\nexport function fieldToString(f) {\n if ('subfields' in f) {\n return `${f.tag} ${normalizeIndicatorValue(f.ind1)}${normalizeIndicatorValue(f.ind2)}${formatSubfields(f)}`;\n }\n return `${f.tag} ${f.value}`;\n\n function formatSubfields(field) {\n return field.subfields.map(sf => ` ${subfieldToString(sf)}`).join('');\n }\n}\n\nexport function fieldsToString(fields) {\n return fields.map(f => fieldToString(f)).join('\\t__SEPARATOR__\\t');\n}\n\nexport function nvdebugFieldArray(fields, prefix = ' ', func = undefined) {\n fields.forEach(field => nvdebug(`${prefix}${fieldToString(field)}`, func));\n}\n\nfunction isControlSubfieldCode(subfieldCode, tag = undefined) {\n // NB! Only $w, $0, $1, $5, $6 and $8 are really control subfields. In Finland $9 is oft a control subfield\n if (['0', '1', '2', '5', '6', '8', 'w'].includes(subfieldCode)) {\n return true;\n }\n // Subfield '7' is control subfield for some tags:\n if (tag && subfieldCode === '7') {\n if ( tag.match(/^7[678]/u) || ['800', '810', '811', '830'].includes(tag) ) {\n return true;\n }\n }\n return false;\n}\n\nexport function isContentSubfieldCode(subfieldCode, tag = undefined) {\n if (isControlSubfieldCode(subfieldCode, tag)) { // 'w', '0', '1', '5', '6' and '8'. (Also '7' for ....)\n return false;\n }\n if (tag && isDataProvenanceSubfieldCode(subfieldCode, tag)) { // Note that default '7' is handled below\n return false;\n }\n // $7 contains typically data provenance, sometimes it's a control field, and for f533, f856 ja f857 it's something else, but it's never content!\n if (['2', '3', '4', '7', '9'].includes(subfieldCode)) {\n return false;\n }\n\n\n return true;\n}\n\n\n\nexport function getCatalogingLanguage(record, defaultCatalogingLanguage = undefined) {\n const [field040] = record.get(/^040$/u);\n if (!field040) {\n return defaultCatalogingLanguage;\n }\n const [b] = field040.subfields.filter(sf => sf.code === 'b');\n if (!b) {\n return defaultCatalogingLanguage;\n }\n return b.value;\n}\n\n\nexport function uniqArray(arr) {\n return arr.filter((val, i) => arr.indexOf(val) === i);\n}\n\nexport function fieldsAreIdentical(field1, field2) {\n if (field1.tag !== field2.tag) { // NB! We are skipping normalizations here on purpose! They should be done beforehand...\n return false;\n }\n return fieldToString(field1) === fieldToString(field2);\n\n // The order of subfields is relevant! Bloody JS idiotisms make people use conditions such as:\n // return field1.subfields.every(sf => field2.subfields.some(sf2 => sf.code === sf2.code && sf.value === sf2.value));\n}\n\nexport function fieldHasNSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n const relevantSubfields = field.subfields.filter(sf => sf.code === subfieldCode);\n //if (subfieldValue === null) {\n return relevantSubfields.length;\n //}\n //const subset = relevantSubfields.filter(value => value === subfieldValue);\n //return subset.length;\n}\n\nexport function removeCopyright(value) {\n return value.replace(/^(?:c|p|\u00A9|\u2117|Cop\\. ?) ?((?:1[0-9][0-9][0-9]|20[012][0-9])\\.?)$/ui, '$1');\n}\n\nfunction isNonStandardNonrepeatableSubfield(tag, subfieldCode) {\n // Put these into config or so...\n if (tag === '264') {\n return ['a', 'b', 'c'].includes(subfieldCode);\n }\n\n if (['336', '337', '338'].includes(tag)) {\n return ['a', 'b', '2'].includes(subfieldCode);\n }\n\n return false;\n}\n\n\nexport function subfieldIsRepeatable(tag, subfieldCode) {\n\n if (isNonStandardNonrepeatableSubfield(tag, subfieldCode)) {\n return false;\n }\n\n // These we know or \"know\":\n // NB! $5 is (according to MARC21 format) non-repeatable, and not usable in all fields, but Melinda has a local exception to this, see MET-300\n if ('0159'.indexOf(subfieldCode) > -1) {\n // Uh, can $0 appear on any field?\n return true;\n }\n\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n nvdebug(` WARNING! Getting field ${tag} data failed! ${fieldSpecs.length} hits. Default value true is used for'${subfieldCode}' .`, debugDev);\n return true;\n }\n\n const subfieldSpecs = fieldSpecs[0].subfields.filter(subfield => subfield.code === subfieldCode);\n // Currently we don't support multiple $6 fields due to re-indexing limitations...\n // Well, $6 is non-repeatable, isn't it?!?\n // (This might actually already be fixed... Marginal issue, but check eventually.)\n if (subfieldSpecs.length !== 1 || subfieldCode === '6') {\n return false; // repeatable if not specified, I guess. Maybe add log or warn?\n }\n return subfieldSpecs[0].repeatable;\n}\n\nfunction marc21GetTagsLegalIndicators(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length === 0) {\n return undefined;\n }\n return fieldSpecs[0].indicators;\n}\n\nexport function marc21GetTagsLegalInd1Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind1;\n}\n\nexport function marc21GetTagsLegalInd2Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind2;\n}\n\nexport function nvdebugSubfieldArray(subfields, prefix = ' ', func = undefined) {\n subfields.forEach(subfield => nvdebug(`${prefix}${subfieldToString(subfield)}`, func));\n}\n\nexport function subfieldsAreIdentical(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code && subfieldA.value === subfieldB.value;\n}\n\nexport function fieldHasMultipleSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n return fieldHasNSubfields(field, subfieldCode) > 1;\n}\n\nexport function hasCopyright(value) {\n const modValue = removeCopyright(value);\n return value !== modValue;\n}\n\n\n\nexport function subfieldArraysContainSameData(arr1, arr2) {\n if ( !arr1.every(sf => arr2.some(sf2 => subfieldsAreIdentical(sf, sf2))) ) {\n return false;\n }\n\n return arr2.every(sf2 => arr1.some(sf => subfieldsAreIdentical(sf, sf2)));\n}\n\nexport function tagIsRepeatable(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n debugDev(` WARNING! Getting field ${tag} data failed! Default to repeatable field.`);\n return true;\n }\n return fieldSpecs[0].repeatable;\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": "12.0.6",
17
+ "version": "12.0.7",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -46,7 +46,7 @@
46
46
  "cld3-asm": "^4.0.0",
47
47
  "clone": "^2.1.2",
48
48
  "debug": "^4.4.3",
49
- "isbn3": "^2.0.3",
49
+ "isbn3": "^2.0.5",
50
50
  "langs": "^2.0.0",
51
51
  "xml2js": "^0.6.2",
52
52
  "xregexp": "^5.1.2"
@@ -58,8 +58,8 @@
58
58
  "@natlibfi/fixugen": "^3.0.0",
59
59
  "@natlibfi/fixura": "^4.0.0",
60
60
  "cross-env": "^10.1.0",
61
- "esbuild": "^0.27.2",
62
- "eslint": "^9.39.2",
61
+ "esbuild": "^0.27.3",
62
+ "eslint": "^10.0.0",
63
63
  "fetch-mock": "^12.6.0"
64
64
  },
65
65
  "overrides": {
package/src/cyrillux.js CHANGED
@@ -3,7 +3,7 @@ import clone from 'clone';
3
3
  import XRegExp from 'xregexp';
4
4
  import * as iso9 from '@natlibfi/iso9-1995';
5
5
  import * as sfs4900 from '@natlibfi/sfs-4900';
6
- import {fieldHasSubfield, fieldToString, fieldsToString, isControlSubfieldCode, nvdebug} from './utils.js';
6
+ import {fieldHasSubfield, fieldToString, fieldsToString, isContentSubfieldCode, nvdebug} from './utils.js';
7
7
  import {fieldGetMaxSubfield6OccurrenceNumberAsInteger, fieldGetOccurrenceNumberPairs, fieldGetUnambiguousOccurrenceNumber, intToOccurrenceNumberString, recordGetMaxSubfield6OccurrenceNumberAsInteger, resetSubfield6Tag} from './subfield6Utils.js';
8
8
  import {default as sortFields} from './sortFields.js';
9
9
  import {default as reindexSubfield6OccurenceNumbers} from './reindexSubfield6OccurenceNumbers.js';
@@ -111,11 +111,11 @@ export default function (config = {}) {
111
111
  }
112
112
 
113
113
  function fieldContainsCyrillicCharacters(field) { // based on melinda-ui-cyrillux
114
- return field.subfields && field.subfields.some(sf => subfieldRequiresTransliteration(sf));
114
+ return field.subfields && field.subfields.some(sf => subfieldRequiresTransliteration(sf, field.tag));
115
115
  }
116
116
 
117
- function subfieldRequiresTransliteration(subfield) {
118
- if (isControlSubfieldCode(subfield.code)) {
117
+ function subfieldRequiresTransliteration(subfield, tag = undefined) {
118
+ if (!isContentSubfieldCode(subfield.code, tag)) {
119
119
  return false;
120
120
  }
121
121
  return containsCyrillicCharacters(subfield.value);
@@ -158,8 +158,8 @@ export default function (config = {}) {
158
158
  }
159
159
 
160
160
 
161
- function mapSubfieldToIso9(subfield) {
162
- if (!subfieldRequiresTransliteration(subfield)) {
161
+ function mapSubfieldToIso9(subfield, tag) {
162
+ if (!subfieldRequiresTransliteration(subfield, tag)) {
163
163
  return {code: subfield.code, value: subfield.value}; // just clone
164
164
  }
165
165
 
@@ -168,9 +168,9 @@ export default function (config = {}) {
168
168
  return {code: subfield.code, value: conversionResult.result};
169
169
  }
170
170
 
171
- function mapSubfieldToSfs4900(subfield, lang = 'rus') {
171
+ function mapSubfieldToSfs4900(subfield, tag, lang = 'rus') {
172
172
  const inputLang = lang === 'ukr' ? 'ukr' : 'rus'; // Support 'ukr' and 'rus', default to 'rus'
173
- if (!subfieldRequiresTransliteration(subfield)) {
173
+ if (!subfieldRequiresTransliteration(subfield, tag)) {
174
174
  return {code: subfield.code, value: subfield.value};
175
175
  }
176
176
  const conversionResult = sfs4900.convertToLatin(subfield.value, inputLang);
@@ -190,7 +190,7 @@ export default function (config = {}) {
190
190
  const transliterationFunc = iso9 ? mapSubfieldToIso9 : mapSubfieldToSfs4900;
191
191
 
192
192
  // NB! iso9 won't use lang
193
- const subfields = field.subfields.filter(sf => sf.code !== '6').map(sf => transliterationFunc(sf, lang));
193
+ const subfields = field.subfields.filter(sf => sf.code !== '6').map(sf => transliterationFunc(sf, field.tag, lang));
194
194
 
195
195
  const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [subfield6, ...subfields, ...subfield9]};
196
196
 
@@ -216,7 +216,7 @@ export default function (config = {}) {
216
216
  }
217
217
  // Just converts the field to ISO-9 latinitsa, does not create any field-880s, so don't bother with $6 or $9 either
218
218
  if (!config.retainCyrillic && !config.preferSFS4900) {
219
- const subfields = field.subfields.map(sf => mapSubfieldToIso9(sf));
219
+ const subfields = field.subfields.map(sf => mapSubfieldToIso9(sf, field.tag));
220
220
  return {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields};
221
221
  }
222
222
 
@@ -230,7 +230,7 @@ export default function (config = {}) {
230
230
  }
231
231
  // Just converts the field to SFS-4900 latinitsa, does not create any field-880s, so don't bother with $6 or $9 either
232
232
  if (!config.retainCyrillic && config.preferSFS4900) {
233
- const subfields = field.subfields.map(sf => mapSubfieldToSfs4900(sf, lang));
233
+ const subfields = field.subfields.map(sf => mapSubfieldToSfs4900(sf, field.tag, lang));
234
234
  return {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields};
235
235
  }
236
236
 
@@ -0,0 +1,21 @@
1
+ export function tagToDataProvenanceSubfieldCode(tag) {
2
+ if ( ['533', '800', '810', '811', '830'].includes(tag)) {
3
+ return 'y';
4
+ }
5
+ if ( tag === '856' || tag === '857' ) {
6
+ return 'e';
7
+ }
8
+
9
+ if ( tag.match(/^7[678]/u) ) {
10
+ return 'l'
11
+ }
12
+
13
+ if ( tag.match(/^00/u)) {
14
+ return undefined;
15
+ }
16
+ return '7';
17
+ }
18
+
19
+ export function isDataProvenanceSubfieldCode(subfieldCode, tag) {
20
+ return subfieldCode === tagToDataProvenanceSubfieldCode(tag);
21
+ }
package/src/index.js CHANGED
@@ -82,7 +82,7 @@ import {removeWorsePrepubField500s, removeWorsePrepubField594s} from './prepubli
82
82
  import {fieldFixPunctuation} from './punctuation2.js';
83
83
  import {recordResetSubfield6OccurrenceNumbers} from './reindexSubfield6OccurenceNumbers.js';
84
84
  import {sortAdjacentSubfields} from './sortSubfields.js';
85
- import {fieldHasSubfield, fieldToString, fieldsToString} from './utils.js';
85
+ import {fieldHasSubfield, fieldToString, fieldsToString, isContentSubfieldCode, tagIsRepeatable} from './utils.js';
86
86
 
87
87
  export {
88
88
  AccessRights,
@@ -162,8 +162,10 @@ export {
162
162
  fieldTrimSubfieldValues,
163
163
  fieldsToNormalizedString,
164
164
  fieldsToString,
165
+ isContentSubfieldCode,
165
166
  recordFixRelatorTerms,
166
167
  sortAdjacentSubfields,
168
+ tagIsRepeatable,
167
169
 
168
170
  // 3. prepublication stuff
169
171
  baseHasEqualOrHigherEncodingLevel,
@@ -2,7 +2,6 @@ import {MarcRecord} from '@natlibfi/marc-record';
2
2
  import createDebugLogger from 'debug';
3
3
  import {fieldHasSubfield, fieldToString, nvdebug, nvdebugSubfieldArray, subfieldIsRepeatable, subfieldsAreIdentical} from '../utils.js';
4
4
 
5
- //import {normalizeControlSubfieldValue} from './normalizeIdentifier';
6
5
  import {normalizeControlSubfieldValue} from '../normalize-identifiers.js';
7
6
 
8
7
  const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:merge-fields:controlSubfields');