@natlibfi/marc-record-validators-melinda 11.3.8 → 11.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/cyrillux.js +67 -34
  2. package/dist/cyrillux.js.map +1 -1
  3. package/dist/index.js +7 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/translate-terms.js +291 -0
  6. package/dist/translate-terms.js.map +1 -0
  7. package/dist/translate-terms.spec.js +51 -0
  8. package/dist/translate-terms.spec.js.map +1 -0
  9. package/package.json +1 -1
  10. package/src/cyrillux.js +56 -32
  11. package/src/index.js +3 -1
  12. package/src/translate-terms.js +274 -0
  13. package/src/translate-terms.spec.js +52 -0
  14. package/test-fixtures/cyrillux/f01/metadata.json +1 -1
  15. package/test-fixtures/cyrillux/f03/metadata.json +4 -3
  16. package/test-fixtures/cyrillux/f03b/expectedResult.json +21 -0
  17. package/test-fixtures/cyrillux/f03b/metadata.json +11 -0
  18. package/test-fixtures/cyrillux/f03b/record.json +19 -0
  19. package/test-fixtures/cyrillux/f04/metadata.json +4 -3
  20. package/test-fixtures/cyrillux/f08/metadata.json +1 -1
  21. package/test-fixtures/cyrillux/f09/metadata.json +1 -1
  22. package/test-fixtures/cyrillux/f11/expectedResult.json +18 -0
  23. package/test-fixtures/cyrillux/f11/metadata.json +9 -0
  24. package/test-fixtures/cyrillux/f11/record.json +9 -0
  25. package/test-fixtures/cyrillux/f11b/expectedResult.json +18 -0
  26. package/test-fixtures/cyrillux/f11b/metadata.json +9 -0
  27. package/test-fixtures/cyrillux/f11b/record.json +16 -0
  28. package/test-fixtures/translate-terms/01/expectedResult.json +37 -0
  29. package/test-fixtures/translate-terms/01/metadata.json +6 -0
  30. package/test-fixtures/translate-terms/01/record.json +27 -0
  31. package/test-fixtures/translate-terms/02/expectedResult.json +37 -0
  32. package/test-fixtures/translate-terms/02/metadata.json +6 -0
  33. package/test-fixtures/translate-terms/02/record.json +27 -0
  34. package/test-fixtures/translate-terms/03/expectedResult.json +26 -0
  35. package/test-fixtures/translate-terms/03/metadata.json +5 -0
  36. package/test-fixtures/translate-terms/03/record.json +26 -0
  37. package/test-fixtures/translate-terms/04/expectedResult.json +16 -0
  38. package/test-fixtures/translate-terms/04/metadata.json +7 -0
  39. package/test-fixtures/translate-terms/04/record.json +17 -0
@@ -0,0 +1,291 @@
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 _debug = _interopRequireDefault(require("debug"));
9
+ var _utils = require("./utils");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const debug = (0, _debug.default)('@natlibfi/marc-record-validators-melinda:sortSubfields');
12
+ const defaultTags = ['648', '650', '651', '655'];
13
+ const swapLanguageCode = {
14
+ 'fin': 'swe',
15
+ 'fi': 'sv',
16
+ 'sv': 'fi',
17
+ 'swe': 'fin'
18
+ };
19
+ const changeAbbrHash = {
20
+ 'fi': 'fin',
21
+ 'fin': 'fi',
22
+ 'sv': 'swe',
23
+ 'swe': 'sv'
24
+ };
25
+
26
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-term');
27
+ const termCache = {};
28
+
29
+ // Author(s): Nicholas Volk
30
+ function _default() {
31
+ return {
32
+ description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',
33
+ validate,
34
+ fix
35
+ };
36
+ async function fix(record) {
37
+ const newFields = await getFields(record, defaultTags, []);
38
+ newFields.forEach(nf => (0, _utils.nvdebug)(`Add new field '${(0, _utils.fieldToString)(nf)}'`, debug));
39
+ newFields.forEach(nf => record.insertField(nf));
40
+ const newFieldsAsStrings = newFields.map(f => (0, _utils.fieldToString)(f));
41
+ return {
42
+ message: [],
43
+ fix: newFieldsAsStrings,
44
+ valid: true
45
+ };
46
+ }
47
+ async function validate(record) {
48
+ const newFields = await getFields(record, defaultTags, []);
49
+ if (newFields.length === 0) {
50
+ return {
51
+ 'message': [],
52
+ 'valid': true
53
+ };
54
+ }
55
+ const messages = newFields.map(f => (0, _utils.fieldToString)(f));
56
+ return {
57
+ 'message': messages,
58
+ 'valid': false
59
+ };
60
+ }
61
+ async function getFields(record, tags, fieldsToAdd) {
62
+ const [currTag, ...remainingTags] = tags;
63
+ if (!currTag) {
64
+ return fieldsToAdd;
65
+ }
66
+ const missingFields = await deriveMissingFields(record, currTag);
67
+ const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);
68
+ return tmp;
69
+ }
70
+ function getPairlessFinnishAndSwedishFields(record, tag) {
71
+ const expectedLex = mapTagToLex(tag);
72
+ if (!expectedLex) {
73
+ return [];
74
+ }
75
+ const fields = record.get(tag);
76
+ const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));
77
+ const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));
78
+ const finnishOnly = getMisses(finnishFields, swedishFields);
79
+ const swedishOnly = getMisses(swedishFields, finnishFields);
80
+
81
+ //console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console
82
+ return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));
83
+ function tagAndFieldAgree(field) {
84
+ // Check that tag and $2 value are pairable:
85
+ const lexData = getLexiconAndLanguage(field); // $2 data
86
+ return expectedLex === lexData.lex;
87
+ }
88
+ }
89
+ async function deriveMissingFields(record, tag) {
90
+ const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);
91
+
92
+ /* eslint-disable */
93
+ // Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)
94
+ let prefLabels = [];
95
+ for (let i = 0; i < pairlessFields.length; i += 1) {
96
+ prefLabels[i] = await getPrefLabel(pairlessFields[i]);
97
+ }
98
+ /* eslint-enable */
99
+
100
+ const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));
101
+ return missingFields.filter(f => f);
102
+ }
103
+ function pairField(field, prefLabels) {
104
+ if (!prefLabels) {
105
+ return undefined;
106
+ }
107
+ //console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console
108
+ const lexAndLang = getLexiconAndLanguage(field);
109
+ //console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console
110
+ const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));
111
+ const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);
112
+ //console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console
113
+ const sfA = {
114
+ 'code': 'a',
115
+ 'value': prefLabel.value
116
+ }; // field.subfields.field(sf => sf.code === 'a');
117
+ const sf0 = (0, _clone.default)(field.subfields.find(sf => sf.code === '0'));
118
+ const sf2 = {
119
+ 'code': '2',
120
+ 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`
121
+ }; // swap fin <=> swe
122
+ const newField = {
123
+ tag: field.tag,
124
+ ind1: field.ind1,
125
+ ind2: field.ind2,
126
+ subfields: [sfA, sf2, sf0]
127
+ };
128
+ return newField;
129
+ }
130
+ function getLexiconAndLanguage(field) {
131
+ const subfield2 = field.subfields.find(sf => sf.code === '2');
132
+ if (subfield2.value === 'slm/fin') {
133
+ return {
134
+ 'lex': 'slm',
135
+ 'lang': 'fin'
136
+ };
137
+ }
138
+ if (subfield2.value === 'slm/swe') {
139
+ return {
140
+ 'lex': 'slm',
141
+ 'lang': 'swe'
142
+ };
143
+ }
144
+ if (subfield2.value === 'yso/fin') {
145
+ return {
146
+ 'lex': 'yso',
147
+ 'lang': 'fin'
148
+ };
149
+ }
150
+ if (subfield2.value === 'yso/swe') {
151
+ return {
152
+ 'lex': 'yso',
153
+ 'lang': 'swe'
154
+ };
155
+ }
156
+ return {};
157
+ }
158
+ async function getPrefLabel(field) {
159
+ // Tag vs $2 correlation has already been checked!
160
+ const uri = fieldToUri(field);
161
+ if (!uri) {
162
+ // $0 is invalid or sumthing
163
+ return undefined;
164
+ }
165
+ const prefLabels = await getTermData(uri);
166
+ if (!prefLabels) {
167
+ // Sanity check. Miss caused by illegal id etc.
168
+ (0, _utils.nvdebug)(`No labels found for ${uri}`, debug);
169
+ return undefined;
170
+ }
171
+ const lexData = getLexiconAndLanguage(field); // $2 data
172
+ const lang = changeAbbr(lexData.lang);
173
+ const subfieldA = field.subfields.find(sf => sf.code === 'a');
174
+ const prefLabel = prefLabels.find(pl => pl.lang === lang);
175
+ //console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console
176
+ if (prefLabel.value === subfieldA.value) {
177
+ (0, _utils.nvdebug)(`'${(0, _utils.fieldToString)(field)}' requires translating`, debug);
178
+ return prefLabels;
179
+ }
180
+ return undefined;
181
+ }
182
+ function swapLanguageCodeBetweenLanguages(code) {
183
+ if (swapLanguageCode[code]) {
184
+ return swapLanguageCode[code];
185
+ }
186
+ return code;
187
+ }
188
+ function changeAbbr(abbr) {
189
+ if (changeAbbrHash[abbr]) {
190
+ return changeAbbrHash[abbr];
191
+ }
192
+ return abbr;
193
+ }
194
+ function swaggerQuery(uri) {
195
+ // This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;
196
+ return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data
197
+ }
198
+ async function getTermData(uri) {
199
+ //console.log(`getTermData(${uri})`); // eslint-disable-line no-console
200
+ if (termCache[uri]) {
201
+ // Don't think current implementation uses the cache any more.
202
+ //console.log(`CACHED ${uri}`); // eslint-disable-line no-console
203
+ return termCache[uri];
204
+ }
205
+ const tmp = await getTermDataFromFinto(uri);
206
+ termCache[uri] = tmp; // eslint-disable-line functional/immutable-data, require-atomic-updates
207
+ return tmp;
208
+ }
209
+ async function getTermDataFromFinto(uri) {
210
+ const headers = {
211
+ 'Accept': 'application/json'
212
+ };
213
+ const uri2 = swaggerQuery(uri);
214
+ const response = await fetch(uri2, {
215
+ method: 'GET',
216
+ headers
217
+ });
218
+ if (!response.ok) {
219
+ return undefined;
220
+ }
221
+ const json = await response.json();
222
+ if (!json.graph) {
223
+ return undefined;
224
+ }
225
+ const arr = json.graph;
226
+ const [hit] = arr.filter(row => row.uri === uri);
227
+ //console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console
228
+ return hit.prefLabel;
229
+ }
230
+ function fieldToUri(field) {
231
+ const lex = mapTagToLex(field.tag);
232
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
233
+ const id = subfield0.value.replace(/^[^0-9]+/u, '');
234
+ if (lex === 'yso') {
235
+ //return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;
236
+ return `http://www.yso.fi/onto/yso/p${id}`;
237
+ }
238
+ if (lex === 'slm') {
239
+ return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
240
+ }
241
+ return undefined;
242
+ }
243
+ function isRelevantField(field, lang) {
244
+ const fieldAsString = (0, _utils.fieldToString)(field);
245
+
246
+ // We should probably allow an optional $8 as the first subfield.
247
+ if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
248
+ return false;
249
+ }
250
+ const lex = mapTagToLex(field.tag);
251
+ const lexLang = `${lex}/${lang}`;
252
+ if (!(0, _utils.fieldHasSubfield)(field, '2', lexLang)) {
253
+ return false;
254
+ }
255
+ return fieldHasValidSubfield0(field);
256
+ }
257
+ function fieldHasValidSubfield0(field) {
258
+ const lex = mapTagToLex(field.tag);
259
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
260
+ if (lex === 'yso' && subfield0.value.match(/^http:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
261
+ return true;
262
+ }
263
+ if (lex === 'slm' && subfield0.value.match(/^http:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
264
+ return true;
265
+ }
266
+ return false;
267
+ }
268
+ function getMisses(fieldList1, fieldList2) {
269
+ return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));
270
+ }
271
+ function hasSubfield0Match(field, pairFields) {
272
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
273
+ return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));
274
+ }
275
+ function mapTagToLex(tag) {
276
+ if (tag === '655') {
277
+ return 'slm';
278
+ }
279
+ return 'yso';
280
+ }
281
+
282
+ /*
283
+ function getValidIdentifiers(record, tag, lang) {
284
+ const lex = mapTagToLex(tag);
285
+ const subfield2Value = `${lex}/${lang}`;
286
+ const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter
287
+ return [];
288
+ }
289
+ */
290
+ }
291
+ //# sourceMappingURL=translate-terms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate-terms.js","names":["_clone","_interopRequireDefault","require","_debug","_utils","e","__esModule","default","debug","createDebugLogger","defaultTags","swapLanguageCode","changeAbbrHash","termCache","_default","description","validate","fix","record","newFields","getFields","forEach","nf","nvdebug","fieldToString","insertField","newFieldsAsStrings","map","f","message","valid","length","messages","tags","fieldsToAdd","currTag","remainingTags","missingFields","deriveMissingFields","tmp","getPairlessFinnishAndSwedishFields","tag","expectedLex","mapTagToLex","fields","get","finnishFields","filter","isRelevantField","swedishFields","finnishOnly","getMisses","swedishOnly","tagAndFieldAgree","field","lexData","getLexiconAndLanguage","lex","pairlessFields","prefLabels","i","getPrefLabel","pairField","undefined","lexAndLang","twoLetterOtherLang","swapLanguageCodeBetweenLanguages","changeAbbr","lang","prefLabel","find","l","sfA","value","sf0","clone","subfields","sf","code","sf2","newField","ind1","ind2","subfield2","uri","fieldToUri","getTermData","subfieldA","pl","abbr","swaggerQuery","getTermDataFromFinto","headers","uri2","response","fetch","method","ok","json","graph","arr","hit","row","subfield0","id","replace","fieldAsString","match","lexLang","fieldHasSubfield","fieldHasValidSubfield0","fieldList1","fieldList2","hasSubfield0Match","pairFields","some"],"sources":["../src/translate-terms.js"],"sourcesContent":["import clone from 'clone';\nimport createDebugLogger from 'debug';\nimport {fieldHasSubfield, fieldToString, nvdebug} from './utils';\n\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortSubfields');\nconst defaultTags = ['648', '650', '651', '655'];\n\nconst swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};\nconst changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-term');\nconst termCache = {};\n\n// Author(s): Nicholas Volk\nexport default function () {\n\n\n return {\n description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',\n validate, fix\n };\n\n async function fix(record) {\n const newFields = await getFields(record, defaultTags, []);\n\n newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debug));\n\n newFields.forEach(nf => record.insertField(nf));\n\n const newFieldsAsStrings = newFields.map(f => fieldToString(f));\n\n\n return {message: [], fix: newFieldsAsStrings, valid: true};\n }\n\n async function validate(record) {\n const newFields = await getFields(record, defaultTags, []);\n if (newFields.length === 0) {\n return {'message': [], 'valid': true};\n }\n const messages = newFields.map(f => fieldToString(f));\n\n return {'message': messages, 'valid': false};\n }\n\n async function getFields(record, tags, fieldsToAdd) {\n const [currTag, ...remainingTags] = tags;\n if (!currTag) {\n return fieldsToAdd;\n }\n const missingFields = await deriveMissingFields(record, currTag);\n\n const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);\n return tmp;\n }\n\n function getPairlessFinnishAndSwedishFields(record, tag) {\n const expectedLex = mapTagToLex(tag);\n if (!expectedLex) {\n return [];\n }\n const fields = record.get(tag);\n const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));\n const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));\n const finnishOnly = getMisses(finnishFields, swedishFields);\n const swedishOnly = getMisses(swedishFields, finnishFields);\n\n //console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console\n return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));\n\n function tagAndFieldAgree(field) {\n // Check that tag and $2 value are pairable:\n const lexData = getLexiconAndLanguage(field); // $2 data\n return expectedLex === lexData.lex;\n }\n }\n\n async function deriveMissingFields(record, tag) {\n const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);\n\n /* eslint-disable */\n // Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)\n let prefLabels = [];\n for (let i=0; i < pairlessFields.length; i += 1) {\n prefLabels[i] = await getPrefLabel(pairlessFields[i]);\n }\n /* eslint-enable */\n\n const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));\n return missingFields.filter(f => f);\n }\n\n function pairField(field, prefLabels) {\n if (!prefLabels) {\n return undefined;\n }\n //console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console\n const lexAndLang = getLexiconAndLanguage(field);\n //console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console\n const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));\n const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);\n //console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console\n const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');\n const sf0 = clone(field.subfields.find(sf => sf.code === '0'));\n const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe\n const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};\n return newField;\n }\n\n function getLexiconAndLanguage(field) {\n const subfield2 = field.subfields.find(sf => sf.code === '2');\n if (subfield2.value === 'slm/fin') {\n return {'lex': 'slm', 'lang': 'fin'};\n }\n if (subfield2.value === 'slm/swe') {\n return {'lex': 'slm', 'lang': 'swe'};\n }\n if (subfield2.value === 'yso/fin') {\n return {'lex': 'yso', 'lang': 'fin'};\n }\n if (subfield2.value === 'yso/swe') {\n return {'lex': 'yso', 'lang': 'swe'};\n }\n return {};\n }\n\n async function getPrefLabel(field) {\n // Tag vs $2 correlation has already been checked!\n const uri = fieldToUri(field);\n if (!uri) { // $0 is invalid or sumthing\n return undefined;\n }\n const prefLabels = await getTermData(uri);\n if (!prefLabels) { // Sanity check. Miss caused by illegal id etc.\n nvdebug(`No labels found for ${uri}`, debug);\n return undefined;\n }\n const lexData = getLexiconAndLanguage(field); // $2 data\n const lang = changeAbbr(lexData.lang);\n\n\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n\n const prefLabel = prefLabels.find(pl => pl.lang === lang);\n //console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console\n if (prefLabel.value === subfieldA.value) {\n nvdebug(`'${fieldToString(field)}' requires translating`, debug);\n return prefLabels;\n }\n return undefined;\n }\n\n function swapLanguageCodeBetweenLanguages(code) {\n if (swapLanguageCode[code]) {\n return swapLanguageCode[code];\n }\n return code;\n }\n\n function changeAbbr(abbr) {\n if (changeAbbrHash[abbr]) {\n return changeAbbrHash[abbr];\n }\n return abbr;\n }\n\n function swaggerQuery(uri) {\n // This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;\n return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data\n }\n\n async function getTermData(uri) {\n //console.log(`getTermData(${uri})`); // eslint-disable-line no-console\n if (termCache[uri]) { // Don't think current implementation uses the cache any more.\n //console.log(`CACHED ${uri}`); // eslint-disable-line no-console\n return termCache[uri];\n }\n const tmp = await getTermDataFromFinto(uri);\n termCache[uri] = tmp; // eslint-disable-line functional/immutable-data, require-atomic-updates\n return tmp;\n }\n\n async function getTermDataFromFinto(uri) {\n const headers = {'Accept': 'application/json'};\n const uri2 = swaggerQuery(uri);\n\n const response = await fetch(uri2, {method: 'GET', headers});\n if (!response.ok) {\n return undefined;\n }\n const json = await response.json();\n\n if (!json.graph) {\n return undefined;\n }\n const arr = json.graph;\n const [hit] = arr.filter(row => row.uri === uri);\n //console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console\n return hit.prefLabel;\n }\n\n\n function fieldToUri(field) {\n const lex = mapTagToLex(field.tag);\n\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n const id = subfield0.value.replace(/^[^0-9]+/u, '');\n if (lex === 'yso') {\n //return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;\n return `http://www.yso.fi/onto/yso/p${id}`;\n }\n if (lex === 'slm') {\n return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;\n }\n return undefined;\n }\n\n function isRelevantField(field, lang) {\n const fieldAsString = fieldToString(field);\n\n // We should probably allow an optional $8 as the first subfield.\n if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {\n return false;\n }\n const lex = mapTagToLex(field.tag);\n const lexLang = `${lex}/${lang}`;\n if (!fieldHasSubfield(field, '2', lexLang)) {\n return false;\n }\n return fieldHasValidSubfield0(field);\n }\n\n function fieldHasValidSubfield0(field) {\n const lex = mapTagToLex(field.tag);\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n if (lex === 'yso' && subfield0.value.match(/^http:\\/\\/www\\.yso\\.fi\\/onto\\/yso\\/p[0-9]+$/u)) {\n return true;\n }\n if (lex === 'slm' && subfield0.value.match(/^http:\\/\\/urn\\.fi\\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {\n return true;\n }\n return false;\n }\n\n function getMisses(fieldList1, fieldList2) {\n return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));\n }\n\n function hasSubfield0Match(field, pairFields) {\n const subfield0 = field.subfields.find(sf => sf.code === '0');\n return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));\n }\n\n\n function mapTagToLex(tag) {\n if (tag === '655') {\n return 'slm';\n }\n return 'yso';\n }\n\n\n /*\n function getValidIdentifiers(record, tag, lang) {\n const lex = mapTagToLex(tag);\n const subfield2Value = `${lex}/${lang}`;\n const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter\n return [];\n }\n */\n\n}\n\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var _chai = require("chai");
4
+ var _marcRecord = require("@natlibfi/marc-record");
5
+ var _translateTerms = _interopRequireDefault(require("./translate-terms"));
6
+ var _fixura = require("@natlibfi/fixura");
7
+ var _fixugen = _interopRequireDefault(require("@natlibfi/fixugen"));
8
+ var _debug = _interopRequireDefault(require("debug"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ (0, _fixugen.default)({
11
+ callback,
12
+ path: [__dirname, '..', 'test-fixtures', 'translate-terms'],
13
+ useMetadataFile: true,
14
+ recurse: false,
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/translate-terms:test');
23
+ async function testValidatorFactory() {
24
+ const validator = await (0, _translateTerms.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, _translateTerms.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=translate-terms.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate-terms.spec.js","names":["_chai","require","_marcRecord","_translateTerms","_interopRequireDefault","_fixura","_fixugen","_debug","e","__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/translate-terms.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './translate-terms';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [__dirname, '..', 'test-fixtures', 'translate-terms'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n mocha: {\n before: () => testValidatorFactory()\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-terms: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,eAAA,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,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAEtC,IAAAG,gBAAa,EAAC;EACZC,QAAQ;EACRC,IAAI,EAAE,CAACC,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,iBAAiB,CAAC;EAC3DC,eAAe,EAAE,IAAI;EACrBC,OAAO,EAAE,KAAK;EACdC,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,+DAA+D,CAAC;AAEhG,eAAeF,oBAAoBA,CAAA,EAAG;EACpC,MAAMG,SAAS,GAAG,MAAM,IAAAC,uBAAgB,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,uBAAgB,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","ignoreList":[]}
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": "11.3.8",
17
+ "version": "11.4.0",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
package/src/cyrillux.js CHANGED
@@ -16,6 +16,7 @@ const cyrillicTrans = 'CYRILLIC <TRANS>';
16
16
  const sfs4900Trans = 'SFS4900 <TRANS>';
17
17
 
18
18
  export default function (config = {}) {
19
+ // console.log(`CONFIG=${JSON.stringify(config)}`); // eslint-disable-line no-console
19
20
 
20
21
  return {
21
22
  description: 'Cyrillux functionality: convert original field to latinitsa (ISO-9) and add 880s for original cyrillic and latinitsa (SFS-4900)',
@@ -23,15 +24,17 @@ export default function (config = {}) {
23
24
  };
24
25
 
25
26
  function preprocessConfig() {
27
+ config.retainCyrillic = typeof config.retainCyrillic === 'undefined' ? true : config.retainCyrillic; // eslint-disable-line functional/immutable-data
26
28
  config.doISO9Transliteration = typeof config.doISO9Transliteration === 'undefined' ? true : config.doISO9Transliteration; // eslint-disable-line functional/immutable-data
27
29
  config.doSFS4900Transliteration = typeof config.doSFS4900Transliteration === 'undefined' ? true : config.doSFS4900Transliteration; // eslint-disable-line functional/immutable-data
28
30
  }
29
31
 
30
32
  function fix(record) {
33
+ // console.log(`FIX has CONFIG=${JSON.stringify(config)}`); // eslint-disable-line no-console
31
34
  // Fix always succeeds
32
35
  const res = {message: [], fix: [], valid: true};
33
36
 
34
- preprocessConfig(config);
37
+ preprocessConfig();
35
38
 
36
39
  const nBefore = record.fields.length;
37
40
 
@@ -61,7 +64,7 @@ export default function (config = {}) {
61
64
  function validate(record) {
62
65
  const res = {message: [], valid: true};
63
66
 
64
- preprocessConfig(config);
67
+ preprocessConfig();
65
68
 
66
69
  record.fields?.forEach(field => {
67
70
  validateField(field, res, record);
@@ -150,22 +153,47 @@ export default function (config = {}) {
150
153
 
151
154
 
152
155
  function mapFieldToIso9(field, occurrenceNumber) {
153
- // This is the original non-880 field, that will be converted from Cyrillic to ISO
154
-
156
+ if (!config.doISO9Transliteration) {
157
+ return undefined;
158
+ }
155
159
  // Just converts the field to ISO-9 latinitsa, does not create any field-880s, so don't bother with $6 or $9 either
156
- if (!config.doISO9Transliteration && !config.doSFS4900Transliteration) {
160
+ if (!config.retainCyrillic && !config.doSFS4900Transliteration) {
157
161
  const subfields = field.subfields.map(sf => mapSubfieldToIso9(sf));
158
162
  return {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields};
159
163
  }
160
164
 
161
165
  const subfield6 = deriveSubfield6('880', field.subfields, occurrenceNumber);
162
- const subfield9 = fieldHasSubfield(field, '9', iso9Trans) ? [] : [{code: '9', value: iso9Trans}];
166
+ const subfield9 = fieldHasSubfield(field, '9', iso9Trans) ? [] : [{code: '9', value: iso9Trans}]; // Add only if needed
163
167
 
164
168
  const subfields = field.subfields.filter(sf => sf.code !== '6').map(sf => mapSubfieldToIso9(sf));
165
169
 
166
170
  return {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [subfield6, ...subfields, ...subfield9]};
167
171
  }
168
172
 
173
+ function mapFieldToSfs4900(field, occurrenceNumber, lang = 'rus') {
174
+ // Just converts the field to ISO-9 latinitsa, does not create any field-880s, so don't bother with $6 or $9 either
175
+ if (!config.retainCyrillic && !config.doISO9Transliteration) {
176
+ const subfields = field.subfields.map(sf => mapSubfieldToIso9(sf));
177
+ return {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields};
178
+ }
179
+
180
+ const subfield6 = deriveSubfield6(field.tag, field.subfields, occurrenceNumber);
181
+ const subfield9 = fieldHasSubfield(field, '9', sfs4900Trans) ? [] : [{code: '9', value: sfs4900Trans}]; // Add only if needed
182
+
183
+ const subfields = field.subfields.filter(sf => sf.code !== '6').map(sf => mapSubfieldToSfs4900(sf, lang));
184
+
185
+ const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [subfield6, ...subfields, ...subfield9]};
186
+
187
+ if (!config.doISO9Transliteration) {
188
+ return newField;
189
+ }
190
+
191
+ //const subfield6 = newField.subfields.find(sf => sf.code === '6');
192
+ newField.tag = '880'; // eslint-disable-line functional/immutable-data
193
+ resetSubfield6Tag(subfield6, field.tag);
194
+ return newField;
195
+ }
196
+
169
197
  function deriveSubfield6(tag, subfields, occurrenceNumber) {
170
198
  const initialSubfield = {code: '6', value: `${tag}-${occurrenceNumber}`};
171
199
  if (tag === '880') { // If *tag in subfield $6* is 880, field is not 880 :D
@@ -182,6 +210,9 @@ export default function (config = {}) {
182
210
  }
183
211
 
184
212
  function mapFieldToCyrillicField880(field, occurrenceNumber) {
213
+ if (!config.retainCyrillic) {
214
+ return undefined;
215
+ }
185
216
  nvdebug(`Derive CYR 880 from ${fieldToString(field)}`);
186
217
  const newSubfield6 = deriveSubfield6(field.tag, field.subfields, occurrenceNumber);
187
218
  const newSubfield9 = fieldHasSubfield(field, '9', cyrillicTrans) ? [] : [{code: '9', value: cyrillicTrans}];
@@ -196,21 +227,6 @@ export default function (config = {}) {
196
227
  return newField;
197
228
  }
198
229
 
199
- function mapFieldToSfs4900Field880(field, occurrenceNumber, lang = 'rus') {
200
- nvdebug(`Derive SFS 880 from ${fieldToString(field)}`);
201
- const newSubfield6 = deriveSubfield6(field.tag, field.subfields, occurrenceNumber);
202
- const newSubfield9 = fieldHasSubfield(field, '9', sfs4900Trans) ? [] : [{code: '9', value: sfs4900Trans}];
203
- const subfields = [
204
- newSubfield6,
205
- ...field.subfields.filter(sf => sf.code !== '6').map(sf => mapSubfieldToSfs4900(sf, lang)),
206
- ...newSubfield9
207
- ];
208
-
209
- const newField = {tag: '880', ind1: field.ind1, ind2: field.ind2, subfields};
210
- nvdebug(` SFS 880 ${fieldToString(newField)}`);
211
- return newField;
212
- }
213
-
214
230
  function getNewOccurrenceNumber(originalField, record, maxCreatedOccurrenceNumber = 0) {
215
231
  const occurrenceNumber = fieldGetMaxSubfield6OccurrenceNumberAsInteger(originalField);
216
232
  // Return existing occurrence number:
@@ -223,12 +239,12 @@ export default function (config = {}) {
223
239
  return recordGetMaxSubfield6OccurrenceNumberAsInteger(record) + 1;
224
240
  }
225
241
 
226
- function needsIso9Transliteration(existingPairedFields) {
227
- if (!config.doISO9Transliteration) {
242
+ function retainCyrillic(existingPairedFields) {
243
+ // Should we move cyrillic content from a normali field to a 880?
244
+ if (!config.retainCyrillic) {
228
245
  return false;
229
246
  }
230
- // Actually normal field is always converted to ISO-9, and this function checks where we move original cyrillic field to 880.
231
- // Thus we look for field 880$9 "CYRILLIC <TRANS>" here, and not "ISO9 <TRANS>"!
247
+ // Fail if we already have a paired 880 $9 <CYRILLIC> TRANS
232
248
  return !existingPairedFields.some(f => fieldHasSubfield(f, '9', cyrillicTrans));
233
249
  }
234
250
 
@@ -257,7 +273,12 @@ export default function (config = {}) {
257
273
 
258
274
  // Paired field: $9 CYRILLIC <TRANS> is the only legal <TRANS>
259
275
  const [pairedField] = existingPairedFields;
260
- if (!fieldContainsCyrillicCharacters(pairedField) || pairedField.subfields.some(sf => sf.code === '9' && sf.value.includes('<TRANS>') && sf.value !== cyrillicTrans)) {
276
+ nvdebug(`LOOKING FOR SFS4900 PAIR: ${fieldToString(field)}`);
277
+ nvdebug(` HAVING PAIRED FIELD: ${fieldToString(pairedField)}`);
278
+ if (!fieldContainsCyrillicCharacters(pairedField)) {
279
+ return false;
280
+ }
281
+ if (pairedField.subfields.some(sf => sf.code === '9' && sf.value.includes('<TRANS>') && sf.value !== cyrillicTrans)) {
261
282
  return false;
262
283
  }
263
284
 
@@ -265,7 +286,7 @@ export default function (config = {}) {
265
286
  // and thus it's a real case of MELINDA-10330 ISO9 adding:
266
287
  const occurrenceNumberAsString = fieldGetUnambiguousOccurrenceNumber(field);
267
288
  const languageCode = getLanguageCode(record);
268
- const field2 = fieldToString(createFieldForSfs4900Comparison(mapFieldToSfs4900Field880(pairedField, occurrenceNumberAsString, languageCode), field.tag));
289
+ const field2 = fieldToString(createFieldForSfs4900Comparison(mapFieldToSfs4900(pairedField, occurrenceNumberAsString, languageCode), field.tag));
269
290
  const field1 = fieldToString(createFieldForSfs4900Comparison(field, field.tag));
270
291
  nvdebug(`COMPARE CONTENTS:\n '${field1}' vs\n '${field2}': ${field1 === field2 ? 'OK' : 'FAIL'}`);
271
292
  return field1 === field2;
@@ -280,6 +301,9 @@ export default function (config = {}) {
280
301
 
281
302
  function transliterateSfs4900Pair(field, record) {
282
303
  // Handle MELINDA-10330: Field is already in SFS-4900 and the only paired field is in Cyrillic!
304
+ if (!config.doISO9Transliteration) {
305
+ return [];
306
+ }
283
307
  const [pairedField] = fieldGetOccurrenceNumberPairs(field, record.get('880'));
284
308
 
285
309
  const occurrenceNumberAsString = fieldGetUnambiguousOccurrenceNumber(field);
@@ -287,9 +311,9 @@ export default function (config = {}) {
287
311
 
288
312
  const tmpField = {'tag': field.tag, 'ind1': field.ind1, 'ind2': field.ind2, 'subfields': pairedField.subfields};
289
313
 
290
- const newMainField = mapFieldToIso9(tmpField, occurrenceNumberAsString); // Cyrillic => ISO-9
291
- const newCyrillicField = mapFieldToCyrillicField880(tmpField, occurrenceNumberAsString); // CYRILLIC
292
- const newSFS4900Field = mapFieldToSfs4900Field880(field, occurrenceNumberAsString, languageCode); // SFS-4900
314
+ const newMainField = config.doISO9Transliteration ? mapFieldToIso9(tmpField, occurrenceNumberAsString) : undefined; // Cyrillic => ISO-9
315
+ const newCyrillicField = config.retainCyrillic ? mapFieldToCyrillicField880(tmpField, occurrenceNumberAsString) : undefined; // CYRILLIC
316
+ const newSFS4900Field = config.doSFS4900Transliteration ? mapFieldToSfs4900(field, occurrenceNumberAsString, languageCode) : undefined; // SFS-4900
293
317
 
294
318
  // Trigger the drop of original counterpart $6 :
295
319
  pairedField.cyrilluxSkip = 1; // eslint-disable-line functional/immutable-data
@@ -322,8 +346,8 @@ export default function (config = {}) {
322
346
  // nvdebug(`NUMBER OF PAIRED 880 FIELDS: ${existingPairedFields.length}`);
323
347
 
324
348
  const newMainField = mapFieldToIso9(originalField, newOccurrenceNumberAsString); // ISO-9
325
- const newCyrillicField = needsIso9Transliteration(existingPairedFields) ? mapFieldToCyrillicField880(originalField, newOccurrenceNumberAsString) : undefined; // CYRILLIC
326
- const newSFS4900Field = needsSfs4900Transliteration(existingPairedFields) ? mapFieldToSfs4900Field880(originalField, newOccurrenceNumberAsString, languageCode) : undefined; /// SFS-4900
349
+ const newCyrillicField = retainCyrillic(existingPairedFields) ? mapFieldToCyrillicField880(originalField, newOccurrenceNumberAsString) : undefined; // CYRILLIC
350
+ const newSFS4900Field = needsSfs4900Transliteration(existingPairedFields) ? mapFieldToSfs4900(originalField, newOccurrenceNumberAsString, languageCode) : undefined; /// SFS-4900
327
351
 
328
352
  return [newMainField, newCyrillicField, newSFS4900Field].filter(f => f);
329
353
  }
package/src/index.js CHANGED
@@ -50,6 +50,7 @@ import SortTags from './sort-tags';
50
50
  import SubfieldValueNormalizations from './subfieldValueNormalizations';
51
51
  import SubfieldExclusion from './subfield-exclusion';
52
52
  import Sync007And300 from './sync-007-and-300';
53
+ import TranslateTerms from './translate-terms';
53
54
  import TypeOfDateF008 from './typeOfDate-008';
54
55
  import UnicodeDecomposition from './unicode-decomposition';
55
56
  import UpdateField540 from './update-field-540';
@@ -106,9 +107,10 @@ export {
106
107
  SubfieldValueNormalizations,
107
108
  Sync007And300,
108
109
  TypeOfDateF008,
110
+ TranslateTerms,
109
111
  UnicodeDecomposition,
110
112
  UpdateField540,
111
113
  Urn,
112
- SortFields, // Keep this penultimateas last
114
+ SortFields, // Keep this penultimate
113
115
  MergeFields // Run this last *iff* you want to use this at all
114
116
  };