@natlibfi/marc-record-validators-melinda 10.7.0 → 10.8.0-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.
Files changed (28) hide show
  1. package/dist/index.js +7 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/mergeRelatorTermFields.js +140 -0
  4. package/dist/mergeRelatorTermFields.js.map +1 -0
  5. package/dist/mergeRelatorTermFields.spec.js +51 -0
  6. package/dist/mergeRelatorTermFields.spec.js.map +1 -0
  7. package/dist/sortRelatorTerms.js +3 -1
  8. package/dist/sortRelatorTerms.js.map +1 -1
  9. package/dist/update-field-540.js +7 -1
  10. package/dist/update-field-540.js.map +1 -1
  11. package/package.json +2 -2
  12. package/src/index.js +2 -0
  13. package/src/mergeRelatorTermFields.js +143 -0
  14. package/src/mergeRelatorTermFields.spec.js +52 -0
  15. package/src/sortRelatorTerms.js +4 -1
  16. package/src/update-field-540.js +2 -1
  17. package/test-fixtures/mergeRelatorTermFields/fixer/01/expectedResult.json +14 -0
  18. package/test-fixtures/mergeRelatorTermFields/fixer/01/metadata.json +6 -0
  19. package/test-fixtures/mergeRelatorTermFields/fixer/01/record.json +16 -0
  20. package/test-fixtures/mergeRelatorTermFields/fixer/02/expectedResult.json +17 -0
  21. package/test-fixtures/mergeRelatorTermFields/fixer/02/metadata.json +6 -0
  22. package/test-fixtures/mergeRelatorTermFields/fixer/02/record.json +23 -0
  23. package/test-fixtures/mergeRelatorTermFields/validator/01/expectedResult.json +6 -0
  24. package/test-fixtures/mergeRelatorTermFields/validator/01/metadata.json +6 -0
  25. package/test-fixtures/mergeRelatorTermFields/validator/01/record.json +16 -0
  26. package/test-fixtures/mergeRelatorTermFields/validator/02/expectedResult.json +4 -0
  27. package/test-fixtures/mergeRelatorTermFields/validator/02/metadata.json +6 -0
  28. package/test-fixtures/mergeRelatorTermFields/validator/02/record.json +16 -0
package/dist/index.js CHANGED
@@ -141,6 +141,12 @@ Object.defineProperty(exports, "SubfieldExclusion", {
141
141
  return _subfieldExclusion.default;
142
142
  }
143
143
  });
144
+ Object.defineProperty(exports, "TypeOfDateF008", {
145
+ enumerable: true,
146
+ get: function () {
147
+ return _typeOfDate.default;
148
+ }
149
+ });
144
150
  Object.defineProperty(exports, "UnicodeDecomposition", {
145
151
  enumerable: true,
146
152
  get: function () {
@@ -183,6 +189,7 @@ var _updateField = _interopRequireDefault(require("./update-field-540"));
183
189
  var _sortSubfields = _interopRequireDefault(require("./sortSubfields"));
184
190
  var _sortTags = _interopRequireDefault(require("./sort-tags"));
185
191
  var _subfieldExclusion = _interopRequireDefault(require("./subfield-exclusion"));
192
+ var _typeOfDate = _interopRequireDefault(require("./typeOfDate-008"));
186
193
  var _unicodeDecomposition = _interopRequireDefault(require("./unicode-decomposition"));
187
194
  var _urn = _interopRequireDefault(require("./urn"));
188
195
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_accessRights","_interopRequireDefault","require","_doubleCommas","_duplicatesInd","_emptyFields","_endingPunctuation","_endingWhitespace","_fieldsPresent","_fieldStructure","_fixedFields","_fieldExclusion","_identicalFields","_isbnIssn","_itemLanguage","_nonBreakingSpace","_normalizeUtf8Diacritics","_punctuation","_resolveOrphanedSubfield6s","_reindexSubfield6OccurenceNumbers","_resolvableExtReferencesMelinda","_sanitizeVocabularySourceCodes","_updateField","_sortSubfields","_sortTags","_subfieldExclusion","_unicodeDecomposition","_urn","obj","__esModule","default"],"sources":["../src/index.js"],"sourcesContent":["import AccessRights from './access-rights';\nimport DoubleCommas from './double-commas';\nimport DuplicatesInd1 from './duplicates-ind1';\nimport EmptyFields from './empty-fields';\nimport EndingPunctuation from './ending-punctuation';\nimport EndingWhitespace from './ending-whitespace';\nimport FieldsPresent from './fields-present';\nimport FieldStructure from './field-structure';\nimport FixedFields from './fixed-fields';\nimport FieldExclusion from './field-exclusion';\nimport IdenticalFields from './identical-fields';\nimport IsbnIssn from './isbn-issn';\nimport ItemLanguage from './item-language';\nimport NonBreakingSpace from './non-breaking-space';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics';\nimport Punctuation from './punctuation/';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s'; // Do this before reindexing!\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes';\nimport UpdateField540 from './update-field-540';\nimport SortSubfields from './sortSubfields';\nimport SortTags from './sort-tags';\nimport SubfieldExclusion from './subfield-exclusion';\nimport UnicodeDecomposition from './unicode-decomposition';\nimport Urn from './urn';\n\nexport {\n AccessRights,\n DoubleCommas,\n DuplicatesInd1,\n EmptyFields,\n EndingPunctuation,\n EndingWhitespace,\n FieldExclusion,\n FieldsPresent,\n FieldStructure,\n FixedFields,\n IdenticalFields,\n IsbnIssn,\n ItemLanguage,\n NonBreakingSpace,\n NormalizeUTF8Diacritics,\n Punctuation,\n ResolveOrphanedSubfield6s,\n ReindexSubfield6OccurenceNumbers,\n ResolvableExtReferences,\n SanitizeVocabularySourceCodes,\n SortSubfields,\n SortTags,\n SubfieldExclusion,\n UnicodeDecomposition,\n UpdateField540,\n Urn\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,aAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,cAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,YAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,kBAAA,GAAAL,sBAAA,CAAAC,OAAA;AACA,IAAAK,iBAAA,GAAAN,sBAAA,CAAAC,OAAA;AACA,IAAAM,cAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,eAAA,GAAAR,sBAAA,CAAAC,OAAA;AACA,IAAAQ,YAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,eAAA,GAAAV,sBAAA,CAAAC,OAAA;AACA,IAAAU,gBAAA,GAAAX,sBAAA,CAAAC,OAAA;AACA,IAAAW,SAAA,GAAAZ,sBAAA,CAAAC,OAAA;AACA,IAAAY,aAAA,GAAAb,sBAAA,CAAAC,OAAA;AACA,IAAAa,iBAAA,GAAAd,sBAAA,CAAAC,OAAA;AACA,IAAAc,wBAAA,GAAAf,sBAAA,CAAAC,OAAA;AACA,IAAAe,YAAA,GAAAhB,sBAAA,CAAAC,OAAA;AACA,IAAAgB,0BAAA,GAAAjB,sBAAA,CAAAC,OAAA;AACA,IAAAiB,iCAAA,GAAAlB,sBAAA,CAAAC,OAAA;AACA,IAAAkB,+BAAA,GAAAnB,sBAAA,CAAAC,OAAA;AACA,IAAAmB,8BAAA,GAAApB,sBAAA,CAAAC,OAAA;AACA,IAAAoB,YAAA,GAAArB,sBAAA,CAAAC,OAAA;AACA,IAAAqB,cAAA,GAAAtB,sBAAA,CAAAC,OAAA;AACA,IAAAsB,SAAA,GAAAvB,sBAAA,CAAAC,OAAA;AACA,IAAAuB,kBAAA,GAAAxB,sBAAA,CAAAC,OAAA;AACA,IAAAwB,qBAAA,GAAAzB,sBAAA,CAAAC,OAAA;AACA,IAAAyB,IAAA,GAAA1B,sBAAA,CAAAC,OAAA;AAAwB,SAAAD,uBAAA2B,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA"}
1
+ {"version":3,"file":"index.js","names":["_accessRights","_interopRequireDefault","require","_doubleCommas","_duplicatesInd","_emptyFields","_endingPunctuation","_endingWhitespace","_fieldsPresent","_fieldStructure","_fixedFields","_fieldExclusion","_identicalFields","_isbnIssn","_itemLanguage","_nonBreakingSpace","_normalizeUtf8Diacritics","_punctuation","_resolveOrphanedSubfield6s","_reindexSubfield6OccurenceNumbers","_resolvableExtReferencesMelinda","_sanitizeVocabularySourceCodes","_updateField","_sortSubfields","_sortTags","_subfieldExclusion","_typeOfDate","_unicodeDecomposition","_urn","obj","__esModule","default"],"sources":["../src/index.js"],"sourcesContent":["import AccessRights from './access-rights';\nimport DoubleCommas from './double-commas';\nimport DuplicatesInd1 from './duplicates-ind1';\nimport EmptyFields from './empty-fields';\nimport EndingPunctuation from './ending-punctuation';\nimport EndingWhitespace from './ending-whitespace';\nimport FieldsPresent from './fields-present';\nimport FieldStructure from './field-structure';\nimport FixedFields from './fixed-fields';\nimport FieldExclusion from './field-exclusion';\nimport IdenticalFields from './identical-fields';\nimport IsbnIssn from './isbn-issn';\nimport ItemLanguage from './item-language';\nimport NonBreakingSpace from './non-breaking-space';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics';\nimport Punctuation from './punctuation/';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s'; // Do this before reindexing!\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes';\nimport UpdateField540 from './update-field-540';\nimport SortSubfields from './sortSubfields';\nimport SortTags from './sort-tags';\nimport SubfieldExclusion from './subfield-exclusion';\nimport TypeOfDateF008 from './typeOfDate-008';\nimport UnicodeDecomposition from './unicode-decomposition';\nimport Urn from './urn';\n\nexport {\n AccessRights,\n DoubleCommas,\n DuplicatesInd1,\n EmptyFields,\n EndingPunctuation,\n EndingWhitespace,\n FieldExclusion,\n FieldsPresent,\n FieldStructure,\n FixedFields,\n IdenticalFields,\n IsbnIssn,\n ItemLanguage,\n NonBreakingSpace,\n NormalizeUTF8Diacritics,\n Punctuation,\n ResolveOrphanedSubfield6s,\n ReindexSubfield6OccurenceNumbers,\n ResolvableExtReferences,\n SanitizeVocabularySourceCodes,\n SortSubfields,\n SortTags,\n SubfieldExclusion,\n TypeOfDateF008,\n UnicodeDecomposition,\n UpdateField540,\n Urn\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,aAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,cAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,YAAA,GAAAJ,sBAAA,CAAAC,OAAA;AACA,IAAAI,kBAAA,GAAAL,sBAAA,CAAAC,OAAA;AACA,IAAAK,iBAAA,GAAAN,sBAAA,CAAAC,OAAA;AACA,IAAAM,cAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,eAAA,GAAAR,sBAAA,CAAAC,OAAA;AACA,IAAAQ,YAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,eAAA,GAAAV,sBAAA,CAAAC,OAAA;AACA,IAAAU,gBAAA,GAAAX,sBAAA,CAAAC,OAAA;AACA,IAAAW,SAAA,GAAAZ,sBAAA,CAAAC,OAAA;AACA,IAAAY,aAAA,GAAAb,sBAAA,CAAAC,OAAA;AACA,IAAAa,iBAAA,GAAAd,sBAAA,CAAAC,OAAA;AACA,IAAAc,wBAAA,GAAAf,sBAAA,CAAAC,OAAA;AACA,IAAAe,YAAA,GAAAhB,sBAAA,CAAAC,OAAA;AACA,IAAAgB,0BAAA,GAAAjB,sBAAA,CAAAC,OAAA;AACA,IAAAiB,iCAAA,GAAAlB,sBAAA,CAAAC,OAAA;AACA,IAAAkB,+BAAA,GAAAnB,sBAAA,CAAAC,OAAA;AACA,IAAAmB,8BAAA,GAAApB,sBAAA,CAAAC,OAAA;AACA,IAAAoB,YAAA,GAAArB,sBAAA,CAAAC,OAAA;AACA,IAAAqB,cAAA,GAAAtB,sBAAA,CAAAC,OAAA;AACA,IAAAsB,SAAA,GAAAvB,sBAAA,CAAAC,OAAA;AACA,IAAAuB,kBAAA,GAAAxB,sBAAA,CAAAC,OAAA;AACA,IAAAwB,WAAA,GAAAzB,sBAAA,CAAAC,OAAA;AACA,IAAAyB,qBAAA,GAAA1B,sBAAA,CAAAC,OAAA;AACA,IAAA0B,IAAA,GAAA3B,sBAAA,CAAAC,OAAA;AAAwB,SAAAD,uBAAA4B,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = _default;
7
+ var _clone = _interopRequireDefault(require("clone"));
8
+ var _punctuation = require("./punctuation2");
9
+ var _utils = require("./utils");
10
+ var _sortSubfields = require("./sortSubfields");
11
+ var _sortRelatorTerms = require("./sortRelatorTerms");
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ // Merge author/agent fields
14
+ //
15
+ // Rationale: Same author can appear in one 1XX and multiple 7XX fields having only different $e subfields.
16
+ // These fields can be merged (and $e-subfields can then be sorted)...
17
+ //
18
+ // Author(s): Nicholas Volk
19
+
20
+ //import createDebugLogger from 'debug';
21
+ /*
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');
23
+ //const debugData = debug.extend('data');
24
+ */
25
+ function _default() {
26
+ return {
27
+ description: 'Merge author fields that only differ in $e relator terms',
28
+ validate,
29
+ fix
30
+ };
31
+ function fix(record) {
32
+ const msg = mergeRelatorTermFields(record, true);
33
+ const res = {
34
+ message: msg,
35
+ fix: msg,
36
+ valid: true
37
+ };
38
+ return res;
39
+ }
40
+ function validate(record) {
41
+ const msg = mergeRelatorTermFields(record, false);
42
+ const res = {
43
+ message: msg
44
+ };
45
+ res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
46
+ return res;
47
+ }
48
+ }
49
+ function createNormalizedClone(field) {
50
+ const clonedField = (0, _clone.default)(field);
51
+ // Normalize
52
+ (0, _punctuation.fieldStripPunctuation)(clonedField);
53
+ return clonedField;
54
+ }
55
+ function createNormalizedCloneWithoutRelatorTerms(field) {
56
+ const clonedField = createNormalizedClone(field);
57
+ // Remove relator terms $e subfi:
58
+ clonedField.subfields = clonedField.subfields.filter(sf => sf.code !== 'e'); // eslint-disable-line functional/immutable-data
59
+ return clonedField;
60
+ }
61
+ function fieldToRelatorTermSubfieldCode(field) {
62
+ if (['100', '110', '700', '710', '720', '751', '752'].includes(field.tag)) {
63
+ return 'e';
64
+ }
65
+ if (field.tag === '111' || field.tag === '711') {
66
+ return 'j';
67
+ }
68
+ return '?'; // No need to complain. Nothing is found.
69
+ }
70
+
71
+ function getRelatorTermStrings(relatorTermSubfieldCode, field) {
72
+ return field.subfields.filter(sf => sf.code === relatorTermSubfieldCode).map(sf => sf.value);
73
+ }
74
+ function extractAddableRelatorTerms(fromField, toField) {
75
+ const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);
76
+ const normalizedFromFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, fromField);
77
+ if (normalizedFromFieldRelatorTerms.length === 0) {
78
+ return [];
79
+ }
80
+ // Remove values that already exist:
81
+ const normalizedToFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, toField);
82
+ return normalizedFromFieldRelatorTerms.filter(str => !normalizedToFieldRelatorTerms.includes(str));
83
+ }
84
+ function copyRelatorSubfields(fromField, toField) {
85
+ const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);
86
+ const newRelatorTerms = extractAddableRelatorTerms(fromField, toField);
87
+ newRelatorTerms.forEach(term => toField.subfields.push({
88
+ code: relatorTermSubfieldCode,
89
+ value: term
90
+ })); // eslint-disable-line functional/immutable-data
91
+ }
92
+
93
+ function mergeRelatorTermFields(record, fix = false) {
94
+ /* eslint-disable */
95
+ // NV: 111/711, 751 and 752 where so rare that I did not add them here
96
+ let fields = record.get('(?:[17][01]0|720)');
97
+ let result = [];
98
+ const comparisonFieldsAsString = fields.map(f => (0, _utils.fieldToString)(createNormalizedCloneWithoutRelatorTerms(f)));
99
+ (0, _utils.nvdebug)(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`);
100
+ for (let i = 0; i < fields.length - 1; i++) {
101
+ let currField = fields[i];
102
+ if (currField.deleted) {
103
+ continue;
104
+ }
105
+ (0, _utils.nvdebug)(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`);
106
+ for (let j = i + 1; j < fields.length; j++) {
107
+ (0, _utils.nvdebug)(` Compare with ${comparisonFieldsAsString[j]}/${j}`);
108
+ let mergableField = fields[j];
109
+ // Skip 1/7 from 1XX/7XX for similarity check:
110
+ if (comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {
111
+ (0, _utils.nvdebug)(" NOT PAIR");
112
+ continue;
113
+ }
114
+ if (mergableField.deleted) {
115
+ (0, _utils.nvdebug)(" DELETED");
116
+ continue;
117
+ }
118
+ const str = `MERGE RELATOR TERM FIELD: ${(0, _utils.fieldToString)(mergableField)}`;
119
+ (0, _utils.nvdebug)(str);
120
+ if (!result.includes(str)) {
121
+ result.push(str);
122
+ }
123
+ if (fix) {
124
+ mergableField.deleted = 1;
125
+ copyRelatorSubfields(mergableField, currField);
126
+ (0, _punctuation.fieldFixPunctuation)(currField);
127
+ (0, _sortSubfields.sortAdjacentSubfields)(currField); // Put the added $e subfield to proper places.
128
+ (0, _sortRelatorTerms.sortAdjacentESubfields)(currField); // Sort $e subfields with each other
129
+ (0, _punctuation.fieldFixPunctuation)(currField);
130
+ }
131
+ }
132
+ }
133
+ if (!fix) {
134
+ fields.forEach(f => delete f.deleted);
135
+ }
136
+ record.fields = record.fields.filter(f => !f.deleted);
137
+ /* eslint-enable */
138
+ return result;
139
+ }
140
+ //# sourceMappingURL=mergeRelatorTermFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeRelatorTermFields.js","names":["_clone","_interopRequireDefault","require","_punctuation","_utils","_sortSubfields","_sortRelatorTerms","obj","__esModule","default","_default","description","validate","fix","record","msg","mergeRelatorTermFields","res","message","valid","length","createNormalizedClone","field","clonedField","clone","fieldStripPunctuation","createNormalizedCloneWithoutRelatorTerms","subfields","filter","sf","code","fieldToRelatorTermSubfieldCode","includes","tag","getRelatorTermStrings","relatorTermSubfieldCode","map","value","extractAddableRelatorTerms","fromField","toField","normalizedFromFieldRelatorTerms","normalizedToFieldRelatorTerms","str","copyRelatorSubfields","newRelatorTerms","forEach","term","push","fields","get","result","comparisonFieldsAsString","f","fieldToString","nvdebug","i","currField","deleted","j","mergableField","substring","fieldFixPunctuation","sortAdjacentSubfields","sortAdjacentESubfields"],"sources":["../src/mergeRelatorTermFields.js"],"sourcesContent":["// Merge author/agent fields\n//\n// Rationale: Same author can appear in one 1XX and multiple 7XX fields having only different $e subfields.\n// These fields can be merged (and $e-subfields can then be sorted)...\n//\n// Author(s): Nicholas Volk\n\n\nimport clone from 'clone';\nimport {fieldFixPunctuation, fieldStripPunctuation} from './punctuation2';\nimport {fieldToString, nvdebug} from './utils';\nimport {sortAdjacentSubfields} from './sortSubfields';\nimport {sortAdjacentESubfields} from './sortRelatorTerms';\n//import createDebugLogger from 'debug';\n/*\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');\n//const debugData = debug.extend('data');\n*/\n\nexport default function () {\n\n return {\n description: 'Merge author fields that only differ in $e relator terms',\n validate, fix\n };\n\n function fix(record) {\n const msg = mergeRelatorTermFields(record, true);\n const res = {message: msg, fix: msg, valid: true};\n return res;\n }\n\n function validate(record) {\n const msg = mergeRelatorTermFields(record, false);\n const res = {message: msg};\n\n res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n}\n\nfunction createNormalizedClone(field) {\n const clonedField = clone(field);\n // Normalize\n fieldStripPunctuation(clonedField);\n return clonedField;\n}\n\nfunction createNormalizedCloneWithoutRelatorTerms(field) {\n const clonedField = createNormalizedClone(field);\n // Remove relator terms $e subfi:\n clonedField.subfields = clonedField.subfields.filter(sf => sf.code !== 'e'); // eslint-disable-line functional/immutable-data\n return clonedField;\n}\n\nfunction fieldToRelatorTermSubfieldCode(field) {\n if (['100', '110', '700', '710', '720', '751', '752'].includes(field.tag)) {\n return 'e';\n }\n if (field.tag === '111' || field.tag === '711') {\n return 'j';\n }\n return '?'; // No need to complain. Nothing is found.\n}\n\nfunction getRelatorTermStrings(relatorTermSubfieldCode, field) {\n return field.subfields.filter(sf => sf.code === relatorTermSubfieldCode).map(sf => sf.value);\n\n}\n\nfunction extractAddableRelatorTerms(fromField, toField) {\n const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);\n const normalizedFromFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, fromField);\n if (normalizedFromFieldRelatorTerms.length === 0) {\n return [];\n }\n // Remove values that already exist:\n const normalizedToFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, toField);\n return normalizedFromFieldRelatorTerms.filter(str => !normalizedToFieldRelatorTerms.includes(str));\n}\n\n\nfunction copyRelatorSubfields(fromField, toField) {\n const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);\n const newRelatorTerms = extractAddableRelatorTerms(fromField, toField);\n\n newRelatorTerms.forEach(term => toField.subfields.push({code: relatorTermSubfieldCode, value: term})); // eslint-disable-line functional/immutable-data\n\n}\n\nfunction mergeRelatorTermFields(record, fix = false) {\n /* eslint-disable */\n // NV: 111/711, 751 and 752 where so rare that I did not add them here\n let fields = record.get('(?:[17][01]0|720)'); \n let result = [];\n const comparisonFieldsAsString = fields.map(f => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));\n\n nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`);\n for(let i=0; i < fields.length-1; i++) {\n let currField = fields[i];\n if (currField.deleted) {\n continue;\n }\n nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`);\n for (let j=i+1; j < fields.length; j++) {\n nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`);\n let mergableField = fields[j];\n // Skip 1/7 from 1XX/7XX for similarity check:\n if ( comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {\n nvdebug(\" NOT PAIR\");\n continue;\n }\n if (mergableField.deleted) {\n nvdebug(\" DELETED\");\n continue;\n }\n const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;\n nvdebug(str);\n\n if(!result.includes(str)) {\n result.push(str)\n }\n\n if (fix) {\n mergableField.deleted = 1;\n copyRelatorSubfields(mergableField, currField);\n fieldFixPunctuation(currField);\n sortAdjacentSubfields(currField); // Put the added $e subfield to proper places.\n sortAdjacentESubfields(currField); // Sort $e subfields with each other\n fieldFixPunctuation(currField);\n\n }\n }\n }\n\n if(!fix) {\n fields.forEach(f => delete f.deleted);\n }\n\n record.fields = record.fields.filter(f => !f.deleted);\n /* eslint-enable */\n return result;\n}\n"],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _chai = require("chai");
4
+ var _marcRecord = require("@natlibfi/marc-record");
5
+ var _mergeRelatorTermFields = _interopRequireDefault(require("./mergeRelatorTermFields"));
6
+ var _fixura = require("@natlibfi/fixura");
7
+ var _fixugen = _interopRequireDefault(require("@natlibfi/fixugen"));
8
+ var _debug = _interopRequireDefault(require("debug"));
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ (0, _fixugen.default)({
11
+ callback,
12
+ path: [__dirname, '..', 'test-fixtures', 'mergeRelatorTermFields'],
13
+ useMetadataFile: true,
14
+ recurse: true,
15
+ fixura: {
16
+ reader: _fixura.READERS.JSON
17
+ },
18
+ mocha: {
19
+ before: () => testValidatorFactory()
20
+ }
21
+ });
22
+ const debug = (0, _debug.default)('@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test');
23
+ async function testValidatorFactory() {
24
+ const validator = await (0, _mergeRelatorTermFields.default)();
25
+ (0, _chai.expect)(validator).to.be.an('object').that.has.any.keys('description', 'validate');
26
+ (0, _chai.expect)(validator.description).to.be.a('string');
27
+ (0, _chai.expect)(validator.validate).to.be.a('function');
28
+ }
29
+ async function callback({
30
+ getFixture,
31
+ enabled = true,
32
+ fix = false
33
+ }) {
34
+ if (enabled === false) {
35
+ debug('TEST SKIPPED!');
36
+ return;
37
+ }
38
+ const validator = await (0, _mergeRelatorTermFields.default)();
39
+ const record = new _marcRecord.MarcRecord(getFixture('record.json'));
40
+ const expectedResult = getFixture('expectedResult.json');
41
+ // console.log(expectedResult); // eslint-disable-line
42
+
43
+ if (!fix) {
44
+ const result = await validator.validate(record);
45
+ (0, _chai.expect)(result).to.eql(expectedResult);
46
+ return;
47
+ }
48
+ await validator.fix(record);
49
+ (0, _chai.expect)(record).to.eql(expectedResult);
50
+ }
51
+ //# sourceMappingURL=mergeRelatorTermFields.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeRelatorTermFields.spec.js","names":["_chai","require","_marcRecord","_mergeRelatorTermFields","_interopRequireDefault","_fixura","_fixugen","_debug","obj","__esModule","default","generateTests","callback","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","mocha","before","testValidatorFactory","debug","createDebugLogger","validator","validatorFactory","expect","to","be","an","that","has","any","keys","description","a","validate","getFixture","enabled","fix","record","MarcRecord","expectedResult","result","eql"],"sources":["../src/mergeRelatorTermFields.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './mergeRelatorTermFields';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [__dirname, '..', 'test-fixtures', 'mergeRelatorTermFields'],\n useMetadataFile: true,\n recurse: true,\n fixura: {\n reader: READERS.JSON\n },\n mocha: {\n before: () => testValidatorFactory()\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n expect(validator)\n .to.be.an('object')\n .that.has.any.keys('description', 'validate');\n\n expect(validator.description).to.be.a('string');\n expect(validator.validate).to.be.a('function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\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 expect(result).to.eql(expectedResult);\n return;\n }\n\n await validator.fix(record);\n expect(record).to.eql(expectedResult);\n}\n"],"mappings":";;AAAA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,WAAA,GAAAD,OAAA;AACA,IAAAE,uBAAA,GAAAC,sBAAA,CAAAH,OAAA;AACA,IAAAI,OAAA,GAAAJ,OAAA;AACA,IAAAK,QAAA,GAAAF,sBAAA,CAAAH,OAAA;AACA,IAAAM,MAAA,GAAAH,sBAAA,CAAAH,OAAA;AAAsC,SAAAG,uBAAAI,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAEtC,IAAAG,gBAAa,EAAC;EACZC,QAAQ;EACRC,IAAI,EAAE,CAACC,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,wBAAwB,CAAC;EAClEC,eAAe,EAAE,IAAI;EACrBC,OAAO,EAAE,IAAI;EACbC,MAAM,EAAE;IACNC,MAAM,EAAEC,eAAO,CAACC;EAClB,CAAC;EACDC,KAAK,EAAE;IACLC,MAAM,EAAEA,CAAA,KAAMC,oBAAoB,CAAC;EACrC;AACF,CAAC,CAAC;AACF,MAAMC,KAAK,GAAG,IAAAC,cAAiB,EAAC,sEAAsE,CAAC;AAEvG,eAAeF,oBAAoBA,CAAA,EAAG;EACpC,MAAMG,SAAS,GAAG,MAAM,IAAAC,+BAAgB,EAAC,CAAC;EAE1C,IAAAC,YAAM,EAACF,SAAS,CAAC,CACdG,EAAE,CAACC,EAAE,CAACC,EAAE,CAAC,QAAQ,CAAC,CAClBC,IAAI,CAACC,GAAG,CAACC,GAAG,CAACC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC;EAE/C,IAAAP,YAAM,EAACF,SAAS,CAACU,WAAW,CAAC,CAACP,EAAE,CAACC,EAAE,CAACO,CAAC,CAAC,QAAQ,CAAC;EAC/C,IAAAT,YAAM,EAACF,SAAS,CAACY,QAAQ,CAAC,CAACT,EAAE,CAACC,EAAE,CAACO,CAAC,CAAC,UAAU,CAAC;AAChD;AAEA,eAAezB,QAAQA,CAAC;EAAC2B,UAAU;EAAEC,OAAO,GAAG,IAAI;EAAEC,GAAG,GAAG;AAAK,CAAC,EAAE;EACjE,IAAID,OAAO,KAAK,KAAK,EAAE;IACrBhB,KAAK,CAAC,eAAe,CAAC;IACtB;EACF;EAEA,MAAME,SAAS,GAAG,MAAM,IAAAC,+BAAgB,EAAC,CAAC;EAC1C,MAAMe,MAAM,GAAG,IAAIC,sBAAU,CAACJ,UAAU,CAAC,aAAa,CAAC,CAAC;EACxD,MAAMK,cAAc,GAAGL,UAAU,CAAC,qBAAqB,CAAC;EACxD;;EAEA,IAAI,CAACE,GAAG,EAAE;IACR,MAAMI,MAAM,GAAG,MAAMnB,SAAS,CAACY,QAAQ,CAACI,MAAM,CAAC;IAC/C,IAAAd,YAAM,EAACiB,MAAM,CAAC,CAAChB,EAAE,CAACiB,GAAG,CAACF,cAAc,CAAC;IACrC;EACF;EAEA,MAAMlB,SAAS,CAACe,GAAG,CAACC,MAAM,CAAC;EAC3B,IAAAd,YAAM,EAACc,MAAM,CAAC,CAACb,EAAE,CAACiB,GAAG,CAACF,cAAc,CAAC;AACvC"}
@@ -37,7 +37,9 @@ const relatorTermValues = {
37
37
  'lukija': 61,
38
38
  // manifestaatio
39
39
  'esittäjä': 60,
40
- 'johtaja': 50
40
+ 'johtaja': 50,
41
+ 'kustantaja': 41,
42
+ 'julkaisija': 40
41
43
  };
42
44
  function scoreRelatorTerm(term) {
43
45
  const normalizedTerm = normalizeValue(term);
@@ -1 +1 @@
1
- {"version":3,"file":"sortRelatorTerms.js","names":["_clone","_interopRequireDefault","require","_utils","_punctuation","obj","__esModule","default","WORST_WORK","relatorTermValues","scoreRelatorTerm","term","normalizedTerm","normalizeValue","_default","description","validate","fix","record","res","message","valid","fields","forEach","field","sortAdjacentESubfields","clonedField","clone","clonedFieldAsString","fieldToString","fieldAsString","push","length","value","replace","swapESubfields","subfields","loopAgain","some","sf","index","code","currScore","prevSubfield","prevScore","tmp","fieldFixPunctuation"],"sources":["../src/sortRelatorTerms.js"],"sourcesContent":["// Validator/fixer for sorting $e relator term subfields\n//\n// Author(s): Nicholas Volk\n\nimport clone from 'clone';\n//import createDebugLogger from 'debug';\nimport {fieldToString} from './utils';\nimport {fieldFixPunctuation} from './punctuation2';\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortRelatorTerms');\n//const debugData = debug.extend('data');\n\nconst WORST_WORK = 98;\n\nconst relatorTermValues = { // The higher, the better\n // More abstract, the earlier it appears.\n // Note that terms with same abstraction level might also have order preferences\n // work/teos > expression/ekspressio > manifestation/manifestaatio\n 'säveltäjä': 100,\n 'kirjoittaja': 99, // Viola wants composer/säveltäjä on top (highly unlikely to ever appear together, but...)\n 'taiteilija': 98,\n 'sanoittaja': 90,\n // ekspressio\n 'sovittaja': 80,\n 'toimittaja': 80,\n 'kuvittaja': 75,\n 'editointi': 71,\n 'kääntäjä': 70,\n 'lukija': 61,\n // manifestaatio\n 'esittäjä': 60,\n 'johtaja': 50\n};\n\nfunction scoreRelatorTerm(term) {\n const normalizedTerm = normalizeValue(term);\n if (normalizedTerm in relatorTermValues) {\n return relatorTermValues[normalizedTerm];\n }\n return 0;\n}\n\nexport default function () {\n\n return {\n description: 'Sort adjacent $e subfields in field [1678][01]0',\n validate, fix\n };\n\n function fix(record) {\n const res = {message: [], fix: [], valid: true};\n\n record.fields.forEach(field => {\n sortAdjacentESubfields(field);\n });\n\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n\n record.fields.forEach(field => {\n const clonedField = clone(field);\n sortAdjacentESubfields(clonedField);\n const clonedFieldAsString = fieldToString(clonedField);\n const fieldAsString = fieldToString(field);\n if (fieldAsString !== clonedFieldAsString) { // eslint-disable-line functional/no-conditional-statements\n res.message.push(`${fieldAsString} => ${clonedFieldAsString}`); // eslint-disable-line functional/immutable-data\n }\n });\n\n res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n}\n\n\nfunction normalizeValue(value) {\n // Removing last punc char is good enough for our purposes.\n // We don't handle abbreviations here etc.\n // Brackets should not happen either, should they?\n return value.replace(/[.,]$/u, '');\n}\n\n\nfunction swapESubfields(field) {\n if (!field.subfields) {\n return;\n }\n\n const loopAgain = field.subfields.some((sf, index) => {\n if (index === 0 || sf.code !== 'e') {\n return false;\n }\n const currScore = scoreRelatorTerm(sf.value);\n\n const prevSubfield = field.subfields[index - 1];\n if (currScore === 0 || prevSubfield.code !== 'e') {\n return false;\n }\n const prevScore = scoreRelatorTerm(prevSubfield.value);\n\n\n // If this subfield maps to a Work, then subfields can be swapped, even if we don't have a score for the prev subfield!\n if (prevScore === 0 && currScore < WORST_WORK) {\n return false;\n }\n\n if (currScore > prevScore) {\n // Swap:\n const tmp = field.subfields[index - 1];\n field.subfields[index - 1] = sf; // eslint-disable-line functional/immutable-data\n field.subfields[index] = tmp; // eslint-disable-line functional/immutable-data\n fieldFixPunctuation(field);\n return true;\n }\n\n return false;\n\n });\n\n if (loopAgain) {\n swapESubfields(field); // uh, evil recursion...\n return;\n }\n\n return;\n\n}\n\nexport function sortAdjacentESubfields(field) {\n if (!field.subfields) {\n return field;\n }\n swapESubfields(field);\n\n return field;\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"sortRelatorTerms.js","names":["_clone","_interopRequireDefault","require","_utils","_punctuation","obj","__esModule","default","WORST_WORK","relatorTermValues","scoreRelatorTerm","term","normalizedTerm","normalizeValue","_default","description","validate","fix","record","res","message","valid","fields","forEach","field","sortAdjacentESubfields","clonedField","clone","clonedFieldAsString","fieldToString","fieldAsString","push","length","value","replace","swapESubfields","subfields","loopAgain","some","sf","index","code","currScore","prevSubfield","prevScore","tmp","fieldFixPunctuation"],"sources":["../src/sortRelatorTerms.js"],"sourcesContent":["// Validator/fixer for sorting $e relator term subfields\n//\n// Author(s): Nicholas Volk\n\nimport clone from 'clone';\n//import createDebugLogger from 'debug';\nimport {fieldToString} from './utils';\nimport {fieldFixPunctuation} from './punctuation2';\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortRelatorTerms');\n//const debugData = debug.extend('data');\n\nconst WORST_WORK = 98;\n\nconst relatorTermValues = { // The higher, the better\n // More abstract, the earlier it appears.\n // Note that terms with same abstraction level might also have order preferences\n // work/teos > expression/ekspressio > manifestation/manifestaatio\n 'säveltäjä': 100,\n 'kirjoittaja': 99, // Viola wants composer/säveltäjä on top (highly unlikely to ever appear together, but...)\n 'taiteilija': 98,\n 'sanoittaja': 90,\n // ekspressio\n 'sovittaja': 80,\n 'toimittaja': 80,\n 'kuvittaja': 75,\n 'editointi': 71,\n 'kääntäjä': 70,\n 'lukija': 61,\n // manifestaatio\n 'esittäjä': 60,\n 'johtaja': 50,\n 'kustantaja': 41,\n 'julkaisija': 40\n\n};\n\nfunction scoreRelatorTerm(term) {\n const normalizedTerm = normalizeValue(term);\n if (normalizedTerm in relatorTermValues) {\n return relatorTermValues[normalizedTerm];\n }\n return 0;\n}\n\nexport default function () {\n\n return {\n description: 'Sort adjacent $e subfields in field [1678][01]0',\n validate, fix\n };\n\n function fix(record) {\n const res = {message: [], fix: [], valid: true};\n\n record.fields.forEach(field => {\n sortAdjacentESubfields(field);\n });\n\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n\n record.fields.forEach(field => {\n const clonedField = clone(field);\n sortAdjacentESubfields(clonedField);\n const clonedFieldAsString = fieldToString(clonedField);\n const fieldAsString = fieldToString(field);\n if (fieldAsString !== clonedFieldAsString) { // eslint-disable-line functional/no-conditional-statements\n res.message.push(`${fieldAsString} => ${clonedFieldAsString}`); // eslint-disable-line functional/immutable-data\n }\n });\n\n res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n}\n\n\nfunction normalizeValue(value) {\n // Removing last punc char is good enough for our purposes.\n // We don't handle abbreviations here etc.\n // Brackets should not happen either, should they?\n return value.replace(/[.,]$/u, '');\n}\n\n\nfunction swapESubfields(field) {\n if (!field.subfields) {\n return;\n }\n\n const loopAgain = field.subfields.some((sf, index) => {\n if (index === 0 || sf.code !== 'e') {\n return false;\n }\n const currScore = scoreRelatorTerm(sf.value);\n\n const prevSubfield = field.subfields[index - 1];\n if (currScore === 0 || prevSubfield.code !== 'e') {\n return false;\n }\n const prevScore = scoreRelatorTerm(prevSubfield.value);\n\n\n // If this subfield maps to a Work, then subfields can be swapped, even if we don't have a score for the prev subfield!\n if (prevScore === 0 && currScore < WORST_WORK) {\n return false;\n }\n\n if (currScore > prevScore) {\n // Swap:\n const tmp = field.subfields[index - 1];\n field.subfields[index - 1] = sf; // eslint-disable-line functional/immutable-data\n field.subfields[index] = tmp; // eslint-disable-line functional/immutable-data\n fieldFixPunctuation(field);\n return true;\n }\n\n return false;\n\n });\n\n if (loopAgain) {\n swapESubfields(field); // uh, evil recursion...\n return;\n }\n\n return;\n\n}\n\nexport function sortAdjacentESubfields(field) {\n if (!field.subfields) {\n return field;\n }\n swapESubfields(field);\n\n return field;\n}\n\n"],"mappings":"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"}
@@ -54,8 +54,14 @@ const licences = [{
54
54
  }, {
55
55
  'license': 'CC BY-ND 4.0',
56
56
  'url': 'https://creativecommons.org/licenses/by-nd/4.0/deed.fi'
57
+ }, {
58
+ 'license': 'CC BY-SA 4.0',
59
+ 'url': 'https://creativecommons.org/licenses/by-sa/4.0/deed.fi'
60
+ }, {
61
+ 'license': 'CC0 1.0',
62
+ 'url': 'https://creativecommons.org/publicdomain/zero/1.0/deed.fi'
57
63
  },
58
- // {'license': 'CC0 1.0', 'url': ' https://creativecommons.org/publicdomain/zero/1.0/deed.fi' }, // not seen/unused
64
+ // not seen/unused
59
65
  {
60
66
  'license': 'Public domain',
61
67
  'url': 'https://creativecommons.org/publicdomain/mark/1.0/deed.fi'
@@ -1 +1 @@
1
- {"version":3,"file":"update-field-540.js","names":["_utils","require","_default","description","validate","fix","record","fixedFields","getFieldsThatUseOldFormat","fixedFieldsAsStrings","map","f","fieldToString","message","valid","yeOldeFields","length","messages","licences","findSubfieldIndex","field","subfield","nvtmp","index","subfields","findIndex","sf","validLicenseInSubfieldC","subfieldC","license","code","value","validUrlInSubfieldU","subfieldU","url","fixC","splice","fieldHasOldCcLicense","tag","validLicense","find","some","subfieldsC","filter","forEach","c","fields"],"sources":["../src/update-field-540.js"],"sourcesContent":["//import createDebugLogger from 'debug';\nimport {fieldToString} from './utils';\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': '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; // eslint-disable-line functional/immutable-data\n const index = field.subfields.findIndex(sf => sf.nvtmp === 1);\n delete subfield.nvtmp; // eslint-disable-line functional/immutable-data\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}`);\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}`);\n return license.url === subfieldU.value;\n}\n\n\nfunction fixC(field, subfieldC) {\n // MELINDA-2431_\n subfieldC.code = 'f'; // eslint-disable-line functional/immutable-data\n const index = findSubfieldIndex(field, subfieldC);\n field.subfields.splice(index + 1, 0, {'code': '2', 'value': 'cc'}); // eslint-disable-line functional/immutable-data\n}\n\nfunction fieldHasOldCcLicense(field, fix) {\n if (field.tag !== '540') {\n return false;\n }\n //nvdebug(`NORM 540: ${fieldToString(field)}`);\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`);\n if (fix) { // eslint-disable-line functional/no-conditional-statements\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"],"mappings":"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"}
1
+ {"version":3,"file":"update-field-540.js","names":["_utils","require","_default","description","validate","fix","record","fixedFields","getFieldsThatUseOldFormat","fixedFieldsAsStrings","map","f","fieldToString","message","valid","yeOldeFields","length","messages","licences","findSubfieldIndex","field","subfield","nvtmp","index","subfields","findIndex","sf","validLicenseInSubfieldC","subfieldC","license","code","value","validUrlInSubfieldU","subfieldU","url","fixC","splice","fieldHasOldCcLicense","tag","validLicense","find","some","subfieldsC","filter","forEach","c","fields"],"sources":["../src/update-field-540.js"],"sourcesContent":["//import createDebugLogger from 'debug';\nimport {fieldToString} from './utils';\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; // eslint-disable-line functional/immutable-data\n const index = field.subfields.findIndex(sf => sf.nvtmp === 1);\n delete subfield.nvtmp; // eslint-disable-line functional/immutable-data\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}`);\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}`);\n return license.url === subfieldU.value;\n}\n\n\nfunction fixC(field, subfieldC) {\n // MELINDA-2431_\n subfieldC.code = 'f'; // eslint-disable-line functional/immutable-data\n const index = findSubfieldIndex(field, subfieldC);\n field.subfields.splice(index + 1, 0, {'code': '2', 'value': 'cc'}); // eslint-disable-line functional/immutable-data\n}\n\nfunction fieldHasOldCcLicense(field, fix) {\n if (field.tag !== '540') {\n return false;\n }\n //nvdebug(`NORM 540: ${fieldToString(field)}`);\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`);\n if (fix) { // eslint-disable-line functional/no-conditional-statements\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"],"mappings":"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"}
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "git@github.com:natlibfi/marc-record-validators-melinda.git"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "10.7.0",
17
+ "version": "10.8.0-alpha.1",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -63,7 +63,7 @@
63
63
  "chai": "^4.3.7",
64
64
  "chai-as-promised": "^7.1.1",
65
65
  "cross-env": "^7.0.3",
66
- "eslint": "^8.39.0",
66
+ "eslint": "^8.41.0",
67
67
  "fetch-mock": "^9.11.0",
68
68
  "mocha": "^10.2.0",
69
69
  "nyc": "^15.1.0"
package/src/index.js CHANGED
@@ -22,6 +22,7 @@ import UpdateField540 from './update-field-540';
22
22
  import SortSubfields from './sortSubfields';
23
23
  import SortTags from './sort-tags';
24
24
  import SubfieldExclusion from './subfield-exclusion';
25
+ import TypeOfDateF008 from './typeOfDate-008';
25
26
  import UnicodeDecomposition from './unicode-decomposition';
26
27
  import Urn from './urn';
27
28
 
@@ -49,6 +50,7 @@ export {
49
50
  SortSubfields,
50
51
  SortTags,
51
52
  SubfieldExclusion,
53
+ TypeOfDateF008,
52
54
  UnicodeDecomposition,
53
55
  UpdateField540,
54
56
  Urn
@@ -0,0 +1,143 @@
1
+ // Merge author/agent fields
2
+ //
3
+ // Rationale: Same author can appear in one 1XX and multiple 7XX fields having only different $e subfields.
4
+ // These fields can be merged (and $e-subfields can then be sorted)...
5
+ //
6
+ // Author(s): Nicholas Volk
7
+
8
+
9
+ import clone from 'clone';
10
+ import {fieldFixPunctuation, fieldStripPunctuation} from './punctuation2';
11
+ import {fieldToString, nvdebug} from './utils';
12
+ import {sortAdjacentSubfields} from './sortSubfields';
13
+ import {sortAdjacentESubfields} from './sortRelatorTerms';
14
+ //import createDebugLogger from 'debug';
15
+ /*
16
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:mergeRelatorTermFields');
17
+ //const debugData = debug.extend('data');
18
+ */
19
+
20
+ export default function () {
21
+
22
+ return {
23
+ description: 'Merge author fields that only differ in $e relator terms',
24
+ validate, fix
25
+ };
26
+
27
+ function fix(record) {
28
+ const msg = mergeRelatorTermFields(record, true);
29
+ const res = {message: msg, fix: msg, valid: true};
30
+ return res;
31
+ }
32
+
33
+ function validate(record) {
34
+ const msg = mergeRelatorTermFields(record, false);
35
+ const res = {message: msg};
36
+
37
+ res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
38
+ return res;
39
+ }
40
+ }
41
+
42
+ function createNormalizedClone(field) {
43
+ const clonedField = clone(field);
44
+ // Normalize
45
+ fieldStripPunctuation(clonedField);
46
+ return clonedField;
47
+ }
48
+
49
+ function createNormalizedCloneWithoutRelatorTerms(field) {
50
+ const clonedField = createNormalizedClone(field);
51
+ // Remove relator terms $e subfi:
52
+ clonedField.subfields = clonedField.subfields.filter(sf => sf.code !== 'e'); // eslint-disable-line functional/immutable-data
53
+ return clonedField;
54
+ }
55
+
56
+ function fieldToRelatorTermSubfieldCode(field) {
57
+ if (['100', '110', '700', '710', '720', '751', '752'].includes(field.tag)) {
58
+ return 'e';
59
+ }
60
+ if (field.tag === '111' || field.tag === '711') {
61
+ return 'j';
62
+ }
63
+ return '?'; // No need to complain. Nothing is found.
64
+ }
65
+
66
+ function getRelatorTermStrings(relatorTermSubfieldCode, field) {
67
+ return field.subfields.filter(sf => sf.code === relatorTermSubfieldCode).map(sf => sf.value);
68
+
69
+ }
70
+
71
+ function extractAddableRelatorTerms(fromField, toField) {
72
+ const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);
73
+ const normalizedFromFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, fromField);
74
+ if (normalizedFromFieldRelatorTerms.length === 0) {
75
+ return [];
76
+ }
77
+ // Remove values that already exist:
78
+ const normalizedToFieldRelatorTerms = getRelatorTermStrings(relatorTermSubfieldCode, toField);
79
+ return normalizedFromFieldRelatorTerms.filter(str => !normalizedToFieldRelatorTerms.includes(str));
80
+ }
81
+
82
+
83
+ function copyRelatorSubfields(fromField, toField) {
84
+ const relatorTermSubfieldCode = fieldToRelatorTermSubfieldCode(fromField);
85
+ const newRelatorTerms = extractAddableRelatorTerms(fromField, toField);
86
+
87
+ newRelatorTerms.forEach(term => toField.subfields.push({code: relatorTermSubfieldCode, value: term})); // eslint-disable-line functional/immutable-data
88
+
89
+ }
90
+
91
+ function mergeRelatorTermFields(record, fix = false) {
92
+ /* eslint-disable */
93
+ // NV: 111/711, 751 and 752 where so rare that I did not add them here
94
+ let fields = record.get('(?:[17][01]0|720)');
95
+ let result = [];
96
+ const comparisonFieldsAsString = fields.map(f => fieldToString(createNormalizedCloneWithoutRelatorTerms(f)));
97
+
98
+ nvdebug(`mergeRelatorTermFields(): ${fields.length} cand field(s) found`);
99
+ for(let i=0; i < fields.length-1; i++) {
100
+ let currField = fields[i];
101
+ if (currField.deleted) {
102
+ continue;
103
+ }
104
+ nvdebug(`RT: Trying to pair ${comparisonFieldsAsString[i]}/${i}`);
105
+ for (let j=i+1; j < fields.length; j++) {
106
+ nvdebug(` Compare with ${comparisonFieldsAsString[j]}/${j}`);
107
+ let mergableField = fields[j];
108
+ // Skip 1/7 from 1XX/7XX for similarity check:
109
+ if ( comparisonFieldsAsString[i].substring(1) !== comparisonFieldsAsString[j].substring(1)) {
110
+ nvdebug(" NOT PAIR");
111
+ continue;
112
+ }
113
+ if (mergableField.deleted) {
114
+ nvdebug(" DELETED");
115
+ continue;
116
+ }
117
+ const str = `MERGE RELATOR TERM FIELD: ${fieldToString(mergableField)}`;
118
+ nvdebug(str);
119
+
120
+ if(!result.includes(str)) {
121
+ result.push(str)
122
+ }
123
+
124
+ if (fix) {
125
+ mergableField.deleted = 1;
126
+ copyRelatorSubfields(mergableField, currField);
127
+ fieldFixPunctuation(currField);
128
+ sortAdjacentSubfields(currField); // Put the added $e subfield to proper places.
129
+ sortAdjacentESubfields(currField); // Sort $e subfields with each other
130
+ fieldFixPunctuation(currField);
131
+
132
+ }
133
+ }
134
+ }
135
+
136
+ if(!fix) {
137
+ fields.forEach(f => delete f.deleted);
138
+ }
139
+
140
+ record.fields = record.fields.filter(f => !f.deleted);
141
+ /* eslint-enable */
142
+ return result;
143
+ }
@@ -0,0 +1,52 @@
1
+ import {expect} from 'chai';
2
+ import {MarcRecord} from '@natlibfi/marc-record';
3
+ import validatorFactory from './mergeRelatorTermFields';
4
+ import {READERS} from '@natlibfi/fixura';
5
+ import generateTests from '@natlibfi/fixugen';
6
+ import createDebugLogger from 'debug';
7
+
8
+ generateTests({
9
+ callback,
10
+ path: [__dirname, '..', 'test-fixtures', 'mergeRelatorTermFields'],
11
+ useMetadataFile: true,
12
+ recurse: true,
13
+ fixura: {
14
+ reader: READERS.JSON
15
+ },
16
+ mocha: {
17
+ before: () => testValidatorFactory()
18
+ }
19
+ });
20
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/mergeRelatorTermFields:test');
21
+
22
+ async function testValidatorFactory() {
23
+ const validator = await validatorFactory();
24
+
25
+ expect(validator)
26
+ .to.be.an('object')
27
+ .that.has.any.keys('description', 'validate');
28
+
29
+ expect(validator.description).to.be.a('string');
30
+ expect(validator.validate).to.be.a('function');
31
+ }
32
+
33
+ async function callback({getFixture, enabled = true, fix = false}) {
34
+ if (enabled === false) {
35
+ debug('TEST SKIPPED!');
36
+ return;
37
+ }
38
+
39
+ const validator = await validatorFactory();
40
+ const record = new MarcRecord(getFixture('record.json'));
41
+ const expectedResult = getFixture('expectedResult.json');
42
+ // console.log(expectedResult); // eslint-disable-line
43
+
44
+ if (!fix) {
45
+ const result = await validator.validate(record);
46
+ expect(result).to.eql(expectedResult);
47
+ return;
48
+ }
49
+
50
+ await validator.fix(record);
51
+ expect(record).to.eql(expectedResult);
52
+ }
@@ -28,7 +28,10 @@ const relatorTermValues = { // The higher, the better
28
28
  'lukija': 61,
29
29
  // manifestaatio
30
30
  'esittäjä': 60,
31
- 'johtaja': 50
31
+ 'johtaja': 50,
32
+ 'kustantaja': 41,
33
+ 'julkaisija': 40
34
+
32
35
  };
33
36
 
34
37
  function scoreRelatorTerm(term) {
@@ -38,7 +38,8 @@ const licences = [
38
38
  {'license': 'CC BY-NC-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fi'},
39
39
  {'license': 'CC BY-NC-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-nc-sa/4.0/deed.fi'},
40
40
  {'license': 'CC BY-ND 4.0', 'url': 'https://creativecommons.org/licenses/by-nd/4.0/deed.fi'},
41
- // {'license': 'CC0 1.0', 'url': ' https://creativecommons.org/publicdomain/zero/1.0/deed.fi' }, // not seen/unused
41
+ {'license': 'CC BY-SA 4.0', 'url': 'https://creativecommons.org/licenses/by-sa/4.0/deed.fi'},
42
+ {'license': 'CC0 1.0', 'url': 'https://creativecommons.org/publicdomain/zero/1.0/deed.fi'}, // not seen/unused
42
43
  {'license': 'Public domain', 'url': 'https://creativecommons.org/publicdomain/mark/1.0/deed.fi'}
43
44
  ];
44
45
 
@@ -0,0 +1,14 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "005", "value": "20220202020202.0" },
5
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "Sukunimi, Etunimi," },
7
+ { "code": "e", "value": "kirjoittaja," },
8
+ { "code": "e", "value": "kuvittaja," },
9
+ { "code": "e", "value": "valokuvaaja." }
10
+
11
+ ]}
12
+ ],
13
+ "leader": ""
14
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "merge relator terms fields 100 + 700",
3
+ "comment": "Note that relator term sorting is used from another validator",
4
+ "fix": true,
5
+ "only": false
6
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ { "tag": "005", "value": "20220202020202.0" },
4
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
5
+ { "code": "a", "value": "Sukunimi, Etunimi," },
6
+ { "code": "e", "value": "kuvittaja." }
7
+ ]},
8
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
9
+ { "code": "a", "value": "Sukunimi, Etunimi," },
10
+ { "code": "e", "value": "kirjoittaja," },
11
+ { "code": "e", "value": "valokuvaaja." }
12
+ ]}
13
+ ],
14
+
15
+ "leader": ""
16
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "005", "value": "20220202020202.0" },
5
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "Sukunimi, Etunimi," },
7
+ { "code": "e", "value": "kirjoittaja," },
8
+ { "code": "e", "value": "kuvittaja." }
9
+ ]},
10
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
11
+ { "code": "a", "value": "Sukunimi2, Etunimi," },
12
+ { "code": "e", "value": "kirjoittaja," },
13
+ { "code": "e", "value": "kuvittaja." }
14
+ ]}
15
+ ],
16
+ "leader": ""
17
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "merge relator terms 7XX: merge termless",
3
+ "only": false,
4
+ "fix": true
5
+
6
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "fields": [
3
+ { "tag": "005", "value": "20220202020202.0" },
4
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
5
+ { "code": "a", "value": "Sukunimi, Etunimi." }
6
+ ]},
7
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
8
+ { "code": "a", "value": "Sukunimi, Etunimi," },
9
+ { "code": "e", "value": "kuvittaja," },
10
+ { "code": "e", "value": "kirjoittaja." }
11
+ ]},
12
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
13
+ { "code": "a", "value": "Sukunimi2, Etunimi," },
14
+ { "code": "e", "value": "kuvittaja," },
15
+ { "code": "e", "value": "kirjoittaja." }
16
+ ]},
17
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
18
+ { "code": "a", "value": "Sukunimi2, Etunimi." }
19
+ ]}
20
+ ],
21
+
22
+ "leader": ""
23
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "message": [
3
+ "MERGE RELATOR TERM FIELD: 700 1 ‡a Sukunimi, Etunimi, ‡e kirjoittaja, ‡e valokuvaaja."
4
+ ],
5
+ "valid": false
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "01: validate 100/700 relator term merge",
3
+ "only": false,
4
+ "fix": false
5
+
6
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ { "tag": "005", "value": "20220202020202.0" },
4
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
5
+ { "code": "a", "value": "Sukunimi, Etunimi," },
6
+ { "code": "e", "value": "kuvittaja." }
7
+ ]},
8
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
9
+ { "code": "a", "value": "Sukunimi, Etunimi," },
10
+ { "code": "e", "value": "kirjoittaja," },
11
+ { "code": "e", "value": "valokuvaaja." }
12
+ ]}
13
+ ],
14
+
15
+ "leader": ""
16
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "message": [],
3
+ "valid": true
4
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "description": "v02: Relator field merge has nothing to do",
3
+ "only": false,
4
+ "fix": false
5
+
6
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "fields": [
3
+ { "tag": "005", "value": "20220202020202.0" },
4
+ { "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
5
+ { "code": "a", "value": "Sukunimi, Etunimi," },
6
+ { "code": "e", "value": "kuvittaja." }
7
+ ]},
8
+ { "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
9
+ { "code": "a", "value": "Eri-Sukunimi, Etunimi," },
10
+ { "code": "e", "value": "kirjoittaja," },
11
+ { "code": "e", "value": "valokuvaaja." }
12
+ ]}
13
+ ],
14
+
15
+ "leader": ""
16
+ }