@natlibfi/marc-record-validators-melinda 11.3.8 → 11.4.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.
- package/dist/cyrillux.js +67 -34
- package/dist/cyrillux.js.map +1 -1
- package/dist/translate-terms.js +291 -0
- package/dist/translate-terms.js.map +1 -0
- package/dist/translate-terms.spec.js +51 -0
- package/dist/translate-terms.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/cyrillux.js +56 -32
- package/src/translate-terms.js +274 -0
- package/src/translate-terms.spec.js +52 -0
- package/test-fixtures/cyrillux/f01/metadata.json +1 -1
- package/test-fixtures/cyrillux/f03/metadata.json +4 -3
- package/test-fixtures/cyrillux/f03b/expectedResult.json +21 -0
- package/test-fixtures/cyrillux/f03b/metadata.json +11 -0
- package/test-fixtures/cyrillux/f03b/record.json +19 -0
- package/test-fixtures/cyrillux/f04/metadata.json +4 -3
- package/test-fixtures/cyrillux/f08/metadata.json +1 -1
- package/test-fixtures/cyrillux/f09/metadata.json +1 -1
- package/test-fixtures/cyrillux/f11/expectedResult.json +18 -0
- package/test-fixtures/cyrillux/f11/metadata.json +9 -0
- package/test-fixtures/cyrillux/f11/record.json +9 -0
- package/test-fixtures/cyrillux/f11b/expectedResult.json +18 -0
- package/test-fixtures/cyrillux/f11b/metadata.json +9 -0
- package/test-fixtures/cyrillux/f11b/record.json +16 -0
- package/test-fixtures/translate-terms/01/expectedResult.json +37 -0
- package/test-fixtures/translate-terms/01/metadata.json +6 -0
- package/test-fixtures/translate-terms/01/record.json +27 -0
- package/test-fixtures/translate-terms/02/expectedResult.json +37 -0
- package/test-fixtures/translate-terms/02/metadata.json +6 -0
- package/test-fixtures/translate-terms/02/record.json +27 -0
- package/test-fixtures/translate-terms/03/expectedResult.json +26 -0
- package/test-fixtures/translate-terms/03/metadata.json +5 -0
- package/test-fixtures/translate-terms/03/record.json +26 -0
- package/test-fixtures/translate-terms/04/expectedResult.json +16 -0
- package/test-fixtures/translate-terms/04/metadata.json +7 -0
- package/test-fixtures/translate-terms/04/record.json +17 -0
|
@@ -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":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,MAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AAAiE,SAAAD,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAGjE,MAAMG,KAAK,GAAG,IAAAC,cAAiB,EAAC,wDAAwD,CAAC;AACzF,MAAMC,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;AAEhD,MAAMC,gBAAgB,GAAG;EAAC,KAAK,EAAE,KAAK;EAAE,IAAI,EAAE,IAAI;EAAE,IAAI,EAAE,IAAI;EAAE,KAAK,EAAE;AAAK,CAAC;AAC7E,MAAMC,cAAc,GAAG;EAAC,IAAI,EAAE,KAAK;EAAE,KAAK,EAAE,IAAI;EAAE,IAAI,EAAE,KAAK;EAAE,KAAK,EAAE;AAAI,CAAC;;AAE3E;AACA,MAAMC,SAAS,GAAG,CAAC,CAAC;;AAEpB;AACe,SAAAC,SAAA,EAAY;EAGzB,OAAO;IACLC,WAAW,EAAE,iEAAiE;IAC9EC,QAAQ;IAAEC;EACZ,CAAC;EAED,eAAeA,GAAGA,CAACC,MAAM,EAAE;IACzB,MAAMC,SAAS,GAAG,MAAMC,SAAS,CAACF,MAAM,EAAER,WAAW,EAAE,EAAE,CAAC;IAE1DS,SAAS,CAACE,OAAO,CAACC,EAAE,IAAI,IAAAC,cAAO,EAAC,kBAAkB,IAAAC,oBAAa,EAACF,EAAE,CAAC,GAAG,EAAEd,KAAK,CAAC,CAAC;IAE/EW,SAAS,CAACE,OAAO,CAACC,EAAE,IAAIJ,MAAM,CAACO,WAAW,CAACH,EAAE,CAAC,CAAC;IAE/C,MAAMI,kBAAkB,GAAGP,SAAS,CAACQ,GAAG,CAACC,CAAC,IAAI,IAAAJ,oBAAa,EAACI,CAAC,CAAC,CAAC;IAG/D,OAAO;MAACC,OAAO,EAAE,EAAE;MAAEZ,GAAG,EAAES,kBAAkB;MAAEI,KAAK,EAAE;IAAI,CAAC;EAC5D;EAEA,eAAed,QAAQA,CAACE,MAAM,EAAE;IAC9B,MAAMC,SAAS,GAAG,MAAMC,SAAS,CAACF,MAAM,EAAER,WAAW,EAAE,EAAE,CAAC;IAC1D,IAAIS,SAAS,CAACY,MAAM,KAAK,CAAC,EAAE;MAC1B,OAAO;QAAC,SAAS,EAAE,EAAE;QAAE,OAAO,EAAE;MAAI,CAAC;IACvC;IACA,MAAMC,QAAQ,GAAGb,SAAS,CAACQ,GAAG,CAACC,CAAC,IAAI,IAAAJ,oBAAa,EAACI,CAAC,CAAC,CAAC;IAErD,OAAO;MAAC,SAAS,EAAEI,QAAQ;MAAE,OAAO,EAAE;IAAK,CAAC;EAC9C;EAEA,eAAeZ,SAASA,CAACF,MAAM,EAAEe,IAAI,EAAEC,WAAW,EAAE;IAClD,MAAM,CAACC,OAAO,EAAE,GAAGC,aAAa,CAAC,GAAGH,IAAI;IACxC,IAAI,CAACE,OAAO,EAAE;MACZ,OAAOD,WAAW;IACpB;IACA,MAAMG,aAAa,GAAG,MAAMC,mBAAmB,CAACpB,MAAM,EAAEiB,OAAO,CAAC;IAEhE,MAAMI,GAAG,GAAG,MAAMnB,SAAS,CAACF,MAAM,EAAEkB,aAAa,EAAE,CAAC,GAAGF,WAAW,EAAE,GAAGG,aAAa,CAAC,CAAC;IACtF,OAAOE,GAAG;EACZ;EAEA,SAASC,kCAAkCA,CAACtB,MAAM,EAAEuB,GAAG,EAAE;IACvD,MAAMC,WAAW,GAAGC,WAAW,CAACF,GAAG,CAAC;IACpC,IAAI,CAACC,WAAW,EAAE;MAChB,OAAO,EAAE;IACX;IACA,MAAME,MAAM,GAAG1B,MAAM,CAAC2B,GAAG,CAACJ,GAAG,CAAC;IAC9B,MAAMK,aAAa,GAAGF,MAAM,CAACG,MAAM,CAACnB,CAAC,IAAIoB,eAAe,CAACpB,CAAC,EAAE,KAAK,CAAC,CAAC;IACnE,MAAMqB,aAAa,GAAGL,MAAM,CAACG,MAAM,CAACnB,CAAC,IAAIoB,eAAe,CAACpB,CAAC,EAAE,KAAK,CAAC,CAAC;IACnE,MAAMsB,WAAW,GAAGC,SAAS,CAACL,aAAa,EAAEG,aAAa,CAAC;IAC3D,MAAMG,WAAW,GAAGD,SAAS,CAACF,aAAa,EAAEH,aAAa,CAAC;;IAE3D;IACA,OAAO,CAAC,GAAGI,WAAW,EAAE,GAAGE,WAAW,CAAC,CAACL,MAAM,CAACnB,CAAC,IAAIyB,gBAAgB,CAACzB,CAAC,CAAC,CAAC;IAExE,SAASyB,gBAAgBA,CAACC,KAAK,EAAE;MAC/B;MACA,MAAMC,OAAO,GAAGC,qBAAqB,CAACF,KAAK,CAAC,CAAC,CAAC;MAC9C,OAAOZ,WAAW,KAAKa,OAAO,CAACE,GAAG;IACpC;EACF;EAEA,eAAenB,mBAAmBA,CAACpB,MAAM,EAAEuB,GAAG,EAAE;IAC9C,MAAMiB,cAAc,GAAGlB,kCAAkC,CAACtB,MAAM,EAAEuB,GAAG,CAAC;;IAEtE;IACA;IACA,IAAIkB,UAAU,GAAG,EAAE;IACnB,KAAK,IAAIC,CAAC,GAAC,CAAC,EAAEA,CAAC,GAAGF,cAAc,CAAC3B,MAAM,EAAE6B,CAAC,IAAI,CAAC,EAAE;MAC/CD,UAAU,CAACC,CAAC,CAAC,GAAG,MAAMC,YAAY,CAACH,cAAc,CAACE,CAAC,CAAC,CAAC;IACvD;IACA;;IAEA,MAAMvB,aAAa,GAAGqB,cAAc,CAAC/B,GAAG,CAAC,CAACC,CAAC,EAAEgC,CAAC,KAAKE,SAAS,CAAClC,CAAC,EAAE+B,UAAU,CAACC,CAAC,CAAC,CAAC,CAAC;IAC/E,OAAOvB,aAAa,CAACU,MAAM,CAACnB,CAAC,IAAIA,CAAC,CAAC;EACrC;EAEA,SAASkC,SAASA,CAACR,KAAK,EAAEK,UAAU,EAAE;IACpC,IAAI,CAACA,UAAU,EAAE;MACf,OAAOI,SAAS;IAClB;IACA;IACA,MAAMC,UAAU,GAAGR,qBAAqB,CAACF,KAAK,CAAC;IAC/C;IACA,MAAMW,kBAAkB,GAAGC,gCAAgC,CAACC,UAAU,CAACH,UAAU,CAACI,IAAI,CAAC,CAAC;IACxF,MAAMC,SAAS,GAAGV,UAAU,CAACW,IAAI,CAACC,CAAC,IAAIA,CAAC,CAACH,IAAI,KAAKH,kBAAkB,CAAC;IACrE;IACA,MAAMO,GAAG,GAAG;MAAC,MAAM,EAAE,GAAG;MAAE,OAAO,EAAEH,SAAS,CAACI;IAAK,CAAC,CAAC,CAAC;IACrD,MAAMC,GAAG,GAAG,IAAAC,cAAK,EAACrB,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC,CAAC;IAC9D,MAAMC,GAAG,GAAG;MAAC,MAAM,EAAE,GAAG;MAAE,OAAO,EAAE,GAAGf,UAAU,CAACP,GAAG,IAAIO,UAAU,CAACI,IAAI,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK;IAAE,CAAC,CAAC,CAAC;IACtG,MAAMY,QAAQ,GAAG;MAACvC,GAAG,EAAEa,KAAK,CAACb,GAAG;MAAEwC,IAAI,EAAE3B,KAAK,CAAC2B,IAAI;MAAEC,IAAI,EAAE5B,KAAK,CAAC4B,IAAI;MAAEN,SAAS,EAAE,CAACJ,GAAG,EAAEO,GAAG,EAAEL,GAAG;IAAC,CAAC;IACjG,OAAOM,QAAQ;EACjB;EAEA,SAASxB,qBAAqBA,CAACF,KAAK,EAAE;IACpC,MAAM6B,SAAS,GAAG7B,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC;IAC7D,IAAIK,SAAS,CAACV,KAAK,KAAK,SAAS,EAAE;MACjC,OAAO;QAAC,KAAK,EAAE,KAAK;QAAE,MAAM,EAAE;MAAK,CAAC;IACtC;IACA,IAAIU,SAAS,CAACV,KAAK,KAAK,SAAS,EAAE;MACjC,OAAO;QAAC,KAAK,EAAE,KAAK;QAAE,MAAM,EAAE;MAAK,CAAC;IACtC;IACA,IAAIU,SAAS,CAACV,KAAK,KAAK,SAAS,EAAE;MACjC,OAAO;QAAC,KAAK,EAAE,KAAK;QAAE,MAAM,EAAE;MAAK,CAAC;IACtC;IACA,IAAIU,SAAS,CAACV,KAAK,KAAK,SAAS,EAAE;MACjC,OAAO;QAAC,KAAK,EAAE,KAAK;QAAE,MAAM,EAAE;MAAK,CAAC;IACtC;IACA,OAAO,CAAC,CAAC;EACX;EAEA,eAAeZ,YAAYA,CAACP,KAAK,EAAE;IACjC;IACA,MAAM8B,GAAG,GAAGC,UAAU,CAAC/B,KAAK,CAAC;IAC7B,IAAI,CAAC8B,GAAG,EAAE;MAAE;MACV,OAAOrB,SAAS;IAClB;IACA,MAAMJ,UAAU,GAAG,MAAM2B,WAAW,CAACF,GAAG,CAAC;IACzC,IAAI,CAACzB,UAAU,EAAE;MAAE;MACjB,IAAApC,cAAO,EAAC,uBAAuB6D,GAAG,EAAE,EAAE5E,KAAK,CAAC;MAC5C,OAAOuD,SAAS;IAClB;IACA,MAAMR,OAAO,GAAGC,qBAAqB,CAACF,KAAK,CAAC,CAAC,CAAC;IAC9C,MAAMc,IAAI,GAAGD,UAAU,CAACZ,OAAO,CAACa,IAAI,CAAC;IAGrC,MAAMmB,SAAS,GAAGjC,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC;IAE7D,MAAMT,SAAS,GAAGV,UAAU,CAACW,IAAI,CAACkB,EAAE,IAAIA,EAAE,CAACpB,IAAI,KAAKA,IAAI,CAAC;IACzD;IACA,IAAIC,SAAS,CAACI,KAAK,KAAKc,SAAS,CAACd,KAAK,EAAE;MACvC,IAAAlD,cAAO,EAAC,IAAI,IAAAC,oBAAa,EAAC8B,KAAK,CAAC,wBAAwB,EAAE9C,KAAK,CAAC;MAChE,OAAOmD,UAAU;IACnB;IACA,OAAOI,SAAS;EAClB;EAEA,SAASG,gCAAgCA,CAACY,IAAI,EAAE;IAC9C,IAAInE,gBAAgB,CAACmE,IAAI,CAAC,EAAE;MAC1B,OAAOnE,gBAAgB,CAACmE,IAAI,CAAC;IAC/B;IACA,OAAOA,IAAI;EACb;EAEA,SAASX,UAAUA,CAACsB,IAAI,EAAE;IACxB,IAAI7E,cAAc,CAAC6E,IAAI,CAAC,EAAE;MACxB,OAAO7E,cAAc,CAAC6E,IAAI,CAAC;IAC7B;IACA,OAAOA,IAAI;EACb;EAEA,SAASC,YAAYA,CAACN,GAAG,EAAE;IACzB;IACA,OAAO,yCAAyCA,GAAG,4BAA4B,CAAC,CAAC;EACnF;EAEA,eAAeE,WAAWA,CAACF,GAAG,EAAE;IAC9B;IACA,IAAIvE,SAAS,CAACuE,GAAG,CAAC,EAAE;MAAE;MACpB;MACA,OAAOvE,SAAS,CAACuE,GAAG,CAAC;IACvB;IACA,MAAM7C,GAAG,GAAG,MAAMoD,oBAAoB,CAACP,GAAG,CAAC;IAC3CvE,SAAS,CAACuE,GAAG,CAAC,GAAG7C,GAAG,CAAC,CAAC;IACtB,OAAOA,GAAG;EACZ;EAEA,eAAeoD,oBAAoBA,CAACP,GAAG,EAAE;IACvC,MAAMQ,OAAO,GAAG;MAAC,QAAQ,EAAE;IAAkB,CAAC;IAC9C,MAAMC,IAAI,GAAGH,YAAY,CAACN,GAAG,CAAC;IAE9B,MAAMU,QAAQ,GAAG,MAAMC,KAAK,CAACF,IAAI,EAAE;MAACG,MAAM,EAAE,KAAK;MAAEJ;IAAO,CAAC,CAAC;IAC5D,IAAI,CAACE,QAAQ,CAACG,EAAE,EAAE;MAChB,OAAOlC,SAAS;IAClB;IACA,MAAMmC,IAAI,GAAG,MAAMJ,QAAQ,CAACI,IAAI,CAAC,CAAC;IAElC,IAAI,CAACA,IAAI,CAACC,KAAK,EAAE;MACf,OAAOpC,SAAS;IAClB;IACA,MAAMqC,GAAG,GAAGF,IAAI,CAACC,KAAK;IACtB,MAAM,CAACE,GAAG,CAAC,GAAGD,GAAG,CAACrD,MAAM,CAACuD,GAAG,IAAIA,GAAG,CAAClB,GAAG,KAAKA,GAAG,CAAC;IAChD;IACA,OAAOiB,GAAG,CAAChC,SAAS;EACtB;EAGA,SAASgB,UAAUA,CAAC/B,KAAK,EAAE;IACzB,MAAMG,GAAG,GAAGd,WAAW,CAACW,KAAK,CAACb,GAAG,CAAC;IAElC,MAAM8D,SAAS,GAAGjD,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC;IAC7D,MAAM0B,EAAE,GAAGD,SAAS,CAAC9B,KAAK,CAACgC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;IACnD,IAAIhD,GAAG,KAAK,KAAK,EAAE;MACjB;MACA,OAAO,+BAA+B+C,EAAE,EAAE;IAC5C;IACA,IAAI/C,GAAG,KAAK,KAAK,EAAE;MACjB,OAAO,oCAAoC+C,EAAE,EAAE;IACjD;IACA,OAAOzC,SAAS;EAClB;EAEA,SAASf,eAAeA,CAACM,KAAK,EAAEc,IAAI,EAAE;IACpC,MAAMsC,aAAa,GAAG,IAAAlF,oBAAa,EAAC8B,KAAK,CAAC;;IAE1C;IACA,IAAI,CAACoD,aAAa,CAACC,KAAK,CAAC,oEAAoE,CAAC,EAAE;MAC9F,OAAO,KAAK;IACd;IACA,MAAMlD,GAAG,GAAGd,WAAW,CAACW,KAAK,CAACb,GAAG,CAAC;IAClC,MAAMmE,OAAO,GAAG,GAAGnD,GAAG,IAAIW,IAAI,EAAE;IAChC,IAAI,CAAC,IAAAyC,uBAAgB,EAACvD,KAAK,EAAE,GAAG,EAAEsD,OAAO,CAAC,EAAE;MAC1C,OAAO,KAAK;IACd;IACA,OAAOE,sBAAsB,CAACxD,KAAK,CAAC;EACtC;EAEA,SAASwD,sBAAsBA,CAACxD,KAAK,EAAE;IACrC,MAAMG,GAAG,GAAGd,WAAW,CAACW,KAAK,CAACb,GAAG,CAAC;IAClC,MAAM8D,SAAS,GAAGjD,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC;IAC7D,IAAIrB,GAAG,KAAK,KAAK,IAAI8C,SAAS,CAAC9B,KAAK,CAACkC,KAAK,CAAC,8CAA8C,CAAC,EAAE;MAC1F,OAAO,IAAI;IACb;IACA,IAAIlD,GAAG,KAAK,KAAK,IAAI8C,SAAS,CAAC9B,KAAK,CAACkC,KAAK,CAAC,gDAAgD,CAAC,EAAE;MAC5F,OAAO,IAAI;IACb;IACA,OAAO,KAAK;EACd;EAEA,SAASxD,SAASA,CAAC4D,UAAU,EAAEC,UAAU,EAAE;IACzC,OAAOD,UAAU,CAAChE,MAAM,CAACnB,CAAC,IAAI,CAACqF,iBAAiB,CAACrF,CAAC,EAAEoF,UAAU,CAAC,CAAC;EAClE;EAEA,SAASC,iBAAiBA,CAAC3D,KAAK,EAAE4D,UAAU,EAAE;IAC5C,MAAMX,SAAS,GAAGjD,KAAK,CAACsB,SAAS,CAACN,IAAI,CAACO,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,CAAC;IAC7D,OAAOoC,UAAU,CAACC,IAAI,CAACvF,CAAC,IAAIA,CAAC,CAACgD,SAAS,CAACuC,IAAI,CAACtC,EAAE,IAAIA,EAAE,CAACC,IAAI,KAAK,GAAG,IAAID,EAAE,CAACJ,KAAK,KAAK8B,SAAS,CAAC9B,KAAK,CAAC,CAAC;EACtG;EAGA,SAAS9B,WAAWA,CAACF,GAAG,EAAE;IACxB,IAAIA,GAAG,KAAK,KAAK,EAAE;MACjB,OAAO,KAAK;IACd;IACA,OAAO,KAAK;EACd;;EAGA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AAEA","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
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(
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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
|
|
227
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
326
|
-
const newSFS4900Field = needsSfs4900Transliteration(existingPairedFields) ?
|
|
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
|
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import clone from 'clone';
|
|
2
|
+
import createDebugLogger from 'debug';
|
|
3
|
+
import {fieldHasSubfield, fieldToString, nvdebug} from './utils';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortSubfields');
|
|
7
|
+
const defaultTags = ['648', '650', '651', '655'];
|
|
8
|
+
|
|
9
|
+
const swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};
|
|
10
|
+
const changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};
|
|
11
|
+
|
|
12
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-term');
|
|
13
|
+
const termCache = {};
|
|
14
|
+
|
|
15
|
+
// Author(s): Nicholas Volk
|
|
16
|
+
export default function () {
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',
|
|
21
|
+
validate, fix
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
async function fix(record) {
|
|
25
|
+
const newFields = await getFields(record, defaultTags, []);
|
|
26
|
+
|
|
27
|
+
newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debug));
|
|
28
|
+
|
|
29
|
+
newFields.forEach(nf => record.insertField(nf));
|
|
30
|
+
|
|
31
|
+
const newFieldsAsStrings = newFields.map(f => fieldToString(f));
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
return {message: [], fix: newFieldsAsStrings, valid: true};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function validate(record) {
|
|
38
|
+
const newFields = await getFields(record, defaultTags, []);
|
|
39
|
+
if (newFields.length === 0) {
|
|
40
|
+
return {'message': [], 'valid': true};
|
|
41
|
+
}
|
|
42
|
+
const messages = newFields.map(f => fieldToString(f));
|
|
43
|
+
|
|
44
|
+
return {'message': messages, 'valid': false};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function getFields(record, tags, fieldsToAdd) {
|
|
48
|
+
const [currTag, ...remainingTags] = tags;
|
|
49
|
+
if (!currTag) {
|
|
50
|
+
return fieldsToAdd;
|
|
51
|
+
}
|
|
52
|
+
const missingFields = await deriveMissingFields(record, currTag);
|
|
53
|
+
|
|
54
|
+
const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);
|
|
55
|
+
return tmp;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getPairlessFinnishAndSwedishFields(record, tag) {
|
|
59
|
+
const expectedLex = mapTagToLex(tag);
|
|
60
|
+
if (!expectedLex) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const fields = record.get(tag);
|
|
64
|
+
const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));
|
|
65
|
+
const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));
|
|
66
|
+
const finnishOnly = getMisses(finnishFields, swedishFields);
|
|
67
|
+
const swedishOnly = getMisses(swedishFields, finnishFields);
|
|
68
|
+
|
|
69
|
+
//console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console
|
|
70
|
+
return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));
|
|
71
|
+
|
|
72
|
+
function tagAndFieldAgree(field) {
|
|
73
|
+
// Check that tag and $2 value are pairable:
|
|
74
|
+
const lexData = getLexiconAndLanguage(field); // $2 data
|
|
75
|
+
return expectedLex === lexData.lex;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function deriveMissingFields(record, tag) {
|
|
80
|
+
const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);
|
|
81
|
+
|
|
82
|
+
/* eslint-disable */
|
|
83
|
+
// 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...)
|
|
84
|
+
let prefLabels = [];
|
|
85
|
+
for (let i=0; i < pairlessFields.length; i += 1) {
|
|
86
|
+
prefLabels[i] = await getPrefLabel(pairlessFields[i]);
|
|
87
|
+
}
|
|
88
|
+
/* eslint-enable */
|
|
89
|
+
|
|
90
|
+
const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));
|
|
91
|
+
return missingFields.filter(f => f);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function pairField(field, prefLabels) {
|
|
95
|
+
if (!prefLabels) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
//console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console
|
|
99
|
+
const lexAndLang = getLexiconAndLanguage(field);
|
|
100
|
+
//console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console
|
|
101
|
+
const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));
|
|
102
|
+
const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);
|
|
103
|
+
//console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console
|
|
104
|
+
const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');
|
|
105
|
+
const sf0 = clone(field.subfields.find(sf => sf.code === '0'));
|
|
106
|
+
const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe
|
|
107
|
+
const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};
|
|
108
|
+
return newField;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getLexiconAndLanguage(field) {
|
|
112
|
+
const subfield2 = field.subfields.find(sf => sf.code === '2');
|
|
113
|
+
if (subfield2.value === 'slm/fin') {
|
|
114
|
+
return {'lex': 'slm', 'lang': 'fin'};
|
|
115
|
+
}
|
|
116
|
+
if (subfield2.value === 'slm/swe') {
|
|
117
|
+
return {'lex': 'slm', 'lang': 'swe'};
|
|
118
|
+
}
|
|
119
|
+
if (subfield2.value === 'yso/fin') {
|
|
120
|
+
return {'lex': 'yso', 'lang': 'fin'};
|
|
121
|
+
}
|
|
122
|
+
if (subfield2.value === 'yso/swe') {
|
|
123
|
+
return {'lex': 'yso', 'lang': 'swe'};
|
|
124
|
+
}
|
|
125
|
+
return {};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function getPrefLabel(field) {
|
|
129
|
+
// Tag vs $2 correlation has already been checked!
|
|
130
|
+
const uri = fieldToUri(field);
|
|
131
|
+
if (!uri) { // $0 is invalid or sumthing
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
const prefLabels = await getTermData(uri);
|
|
135
|
+
if (!prefLabels) { // Sanity check. Miss caused by illegal id etc.
|
|
136
|
+
nvdebug(`No labels found for ${uri}`, debug);
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const lexData = getLexiconAndLanguage(field); // $2 data
|
|
140
|
+
const lang = changeAbbr(lexData.lang);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
const subfieldA = field.subfields.find(sf => sf.code === 'a');
|
|
144
|
+
|
|
145
|
+
const prefLabel = prefLabels.find(pl => pl.lang === lang);
|
|
146
|
+
//console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console
|
|
147
|
+
if (prefLabel.value === subfieldA.value) {
|
|
148
|
+
nvdebug(`'${fieldToString(field)}' requires translating`, debug);
|
|
149
|
+
return prefLabels;
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function swapLanguageCodeBetweenLanguages(code) {
|
|
155
|
+
if (swapLanguageCode[code]) {
|
|
156
|
+
return swapLanguageCode[code];
|
|
157
|
+
}
|
|
158
|
+
return code;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function changeAbbr(abbr) {
|
|
162
|
+
if (changeAbbrHash[abbr]) {
|
|
163
|
+
return changeAbbrHash[abbr];
|
|
164
|
+
}
|
|
165
|
+
return abbr;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function swaggerQuery(uri) {
|
|
169
|
+
// This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;
|
|
170
|
+
return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function getTermData(uri) {
|
|
174
|
+
//console.log(`getTermData(${uri})`); // eslint-disable-line no-console
|
|
175
|
+
if (termCache[uri]) { // Don't think current implementation uses the cache any more.
|
|
176
|
+
//console.log(`CACHED ${uri}`); // eslint-disable-line no-console
|
|
177
|
+
return termCache[uri];
|
|
178
|
+
}
|
|
179
|
+
const tmp = await getTermDataFromFinto(uri);
|
|
180
|
+
termCache[uri] = tmp; // eslint-disable-line functional/immutable-data, require-atomic-updates
|
|
181
|
+
return tmp;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function getTermDataFromFinto(uri) {
|
|
185
|
+
const headers = {'Accept': 'application/json'};
|
|
186
|
+
const uri2 = swaggerQuery(uri);
|
|
187
|
+
|
|
188
|
+
const response = await fetch(uri2, {method: 'GET', headers});
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const json = await response.json();
|
|
193
|
+
|
|
194
|
+
if (!json.graph) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
const arr = json.graph;
|
|
198
|
+
const [hit] = arr.filter(row => row.uri === uri);
|
|
199
|
+
//console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console
|
|
200
|
+
return hit.prefLabel;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
function fieldToUri(field) {
|
|
205
|
+
const lex = mapTagToLex(field.tag);
|
|
206
|
+
|
|
207
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
208
|
+
const id = subfield0.value.replace(/^[^0-9]+/u, '');
|
|
209
|
+
if (lex === 'yso') {
|
|
210
|
+
//return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;
|
|
211
|
+
return `http://www.yso.fi/onto/yso/p${id}`;
|
|
212
|
+
}
|
|
213
|
+
if (lex === 'slm') {
|
|
214
|
+
return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isRelevantField(field, lang) {
|
|
220
|
+
const fieldAsString = fieldToString(field);
|
|
221
|
+
|
|
222
|
+
// We should probably allow an optional $8 as the first subfield.
|
|
223
|
+
if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const lex = mapTagToLex(field.tag);
|
|
227
|
+
const lexLang = `${lex}/${lang}`;
|
|
228
|
+
if (!fieldHasSubfield(field, '2', lexLang)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
return fieldHasValidSubfield0(field);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function fieldHasValidSubfield0(field) {
|
|
235
|
+
const lex = mapTagToLex(field.tag);
|
|
236
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
237
|
+
if (lex === 'yso' && subfield0.value.match(/^http:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
if (lex === 'slm' && subfield0.value.match(/^http:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getMisses(fieldList1, fieldList2) {
|
|
247
|
+
return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function hasSubfield0Match(field, pairFields) {
|
|
251
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
252
|
+
return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
function mapTagToLex(tag) {
|
|
257
|
+
if (tag === '655') {
|
|
258
|
+
return 'slm';
|
|
259
|
+
}
|
|
260
|
+
return 'yso';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
/*
|
|
265
|
+
function getValidIdentifiers(record, tag, lang) {
|
|
266
|
+
const lex = mapTagToLex(tag);
|
|
267
|
+
const subfield2Value = `${lex}/${lang}`;
|
|
268
|
+
const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
|
+
import validatorFactory from './translate-terms';
|
|
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', 'translate-terms'],
|
|
11
|
+
useMetadataFile: true,
|
|
12
|
+
recurse: false,
|
|
13
|
+
fixura: {
|
|
14
|
+
reader: READERS.JSON
|
|
15
|
+
},
|
|
16
|
+
mocha: {
|
|
17
|
+
before: () => testValidatorFactory()
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-terms: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
|
+
}
|