@natlibfi/marc-record-validators-melinda 12.0.8 → 12.0.9

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.
@@ -166,52 +166,69 @@ function deriveIndividualDeletables(record) {
166
166
  return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);
167
167
  }
168
168
  }
169
- if (currString.match(/^500 ## ‡a Lisäpainokset: Lisäpainos /u)) {
170
- const tmp1 = currString.replace(" Lis\xE4painos ", " [Lis\xE4painos] ");
171
- const tmp2 = currString.replace(" Lis\xE4painos ", " ");
172
- if (tmp1 !== currString && tmp2 !== currString) {
173
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp1, tmp2]);
174
- }
175
- }
176
- if (currString.match(/^500 ## ‡a Lisäpainokset: \[Lisäpainos\] /u)) {
177
- const tmp = currString.replace(" [Lis\xE4painos] ", " ");
178
- if (tmp !== currString) {
179
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);
180
- }
181
- }
182
- if (currString.match(/^500 ## ‡a Ei vastaanotettu\.$/u)) {
183
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, "500 ## \u2021a EI VASTAANOTETTU."]);
184
- }
185
- if (currString.match(/^500 ## ‡a Ei ilmesty\.$/u)) {
186
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, "500 ## \u2021a EI ILMESTY."]);
187
- }
188
169
  if (currString.match(/^505 .0.*-- ‡t/u)) {
189
170
  const tmp = currString.replace(/ -- ‡t /gu, " -- ").replace(/ ‡[rg] /gu, " ").replace(/ ‡t /u, " \u2021a ").replace(/^505 (.)0/u, "505 $1#");
190
171
  if (tmp !== currString) {
191
172
  return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);
192
173
  }
193
174
  }
194
- if (currString.match(/^594 ## ‡a Ei vastaanotettu ‡5 FENNI$/u)) {
195
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, "594 ## \u2021a EI VASTAANOTETTU \u20215 FENNI"]);
175
+ const inferiorFunctions = [getPrepublicationTerms, getInferior341, getAiBased, getMelkehitys3147, getMet831, getMet569];
176
+ const inferiorTerms2 = getInferiorTerms2(inferiorFunctions);
177
+ const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms2];
178
+ return processTodoList([...stillToDo, ...moreToDo], newDeletables);
179
+ function getInferiorTerms2(functions, results = []) {
180
+ const [currFunction, ...remainingFunctions] = functions;
181
+ if (!currFunction) {
182
+ return results;
183
+ }
184
+ const newDeletables2 = currFunction(currString);
185
+ return getInferiorTerms2(remainingFunctions, [...results, ...newDeletables2]);
196
186
  }
197
- if (currString.match(/^594 ## ‡a Ei ilmesty ‡5 FENNI$/u)) {
198
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, "594 ## \u2021a EI ILMESTY \u20215 FENNI"]);
187
+ function getMet569(string) {
188
+ if (string.match(/^500 ## ‡a Lisäpainokset: Lisäpainos /u)) {
189
+ const tmp1 = string.replace(" Lis\xE4painos ", " [Lis\xE4painos] ");
190
+ const tmp2 = string.replace(" Lis\xE4painos ", " ");
191
+ if (tmp1 !== string && tmp2 !== string) {
192
+ return [tmp1, tmp2];
193
+ }
194
+ }
195
+ if (string.match(/^500 ## ‡a Lisäpainokset: \[Lisäpainos\] /u)) {
196
+ const tmp = string.replace(" [Lis\xE4painos] ", " ");
197
+ if (tmp !== string) {
198
+ return [tmp];
199
+ }
200
+ }
201
+ return [];
199
202
  }
200
- if (currString.match(/^880.* ‡6 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {
201
- const tmp = currString.replace(/( ‡6 [0-9][0-9][0-9])-[0-9]+/u, "$1-00");
202
- if (tmp.match(/ ‡6 [0-9][0-9][0-9]-00\/[^ ]+ /u)) {
203
- const tmp2 = tmp.replace(/( ‡6 [0-9][0-9][0-9]-00)[^ ]+/u, "$1");
204
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp, tmp2]);
203
+ function getMet831(string) {
204
+ if (string.match(/^880.* ‡6 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {
205
+ const tmp = string.replace(/( ‡6 [0-9][0-9][0-9])-[0-9]+/u, "$1-00");
206
+ if (tmp.match(/ ‡6 [0-9][0-9][0-9]-00\/[^ ]+ /u)) {
207
+ const tmp2 = tmp.replace(/( ‡6 [0-9][0-9][0-9]-00)[^ ]+/u, "$1");
208
+ return [tmp, tmp2];
209
+ }
210
+ return [tmp];
205
211
  }
206
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);
212
+ return [];
207
213
  }
208
- const inferiorTerms2 = getPrepublicationTerms(currString);
209
- const aiBased = `${currString} \u20217 (dpenmw)AI`;
210
- const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms2, aiBased];
211
- if (subsets.length) {
212
- return processTodoList([...stillToDo, ...moreToDo], newDeletables);
214
+ function getMelkehitys3147(string) {
215
+ if (string.match(/^500 ## ‡a Ei vastaanotettu\.$/u)) {
216
+ return ["500 ## \u2021a EI VASTAANOTETTU."];
217
+ }
218
+ if (string.match(/^500 ## ‡a Ei ilmesty\.$/u)) {
219
+ return ["500 ## \u2021a EI ILMESTY."];
220
+ }
221
+ if (string.match(/^594 ## ‡a Ei vastaanotettu ‡5 FENNI$/u)) {
222
+ return ["594 ## \u2021a EI VASTAANOTETTU \u20215 FENNI"];
223
+ }
224
+ if (string.match(/^594 ## ‡a Ei ilmesty ‡5 FENNI$/u)) {
225
+ return ["594 ## \u2021a EI ILMESTY \u20215 FENNI"];
226
+ }
227
+ return [];
213
228
  }
214
- return processTodoList([...stillToDo, ...moreToDo], newDeletables);
229
+ }
230
+ function getAiBased(string) {
231
+ return [`${string} \u20217 (dpenmw)AI`];
215
232
  }
216
233
  function getAccentlessVersion(string) {
217
234
  if (string !== precomposeFinnishLetters(string)) {
@@ -230,6 +247,15 @@ function deriveIndividualDeletables(record) {
230
247
  }
231
248
  return [subfield7Prepub];
232
249
  }
250
+ function getInferior341(fieldAsString) {
251
+ if (fieldAsString.match(/^341 .. ‡a textual ‡[bcdef].* ‡2 sapdv(?:$| ‡)/u)) {
252
+ return ["341 ## \u2021a textual \u20212 sapdv", "341 1# \u2021a textual \u20212 sapdv", "341 0# \u2021a textual \u20212 sapdv"];
253
+ }
254
+ if (fieldAsString.match(/^341 .. ‡a auditory ‡[bcdef].* ‡2 sapdv(?:$| ‡)/u)) {
255
+ return ["341 ## \u2021a auditory \u20212 sapdv", "341 1# \u2021a auditory \u20212 sapdv", "341 0# \u2021a auditory \u20212 sapdv"];
256
+ }
257
+ return [];
258
+ }
233
259
  }
234
260
  function fieldToNormalizedString(field) {
235
261
  const normalizedField = cloneAndNormalizeFieldForComparison(field);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/removeInferiorDataFields.js"],
4
- "sourcesContent": ["//import createDebugLogger from 'debug';\nimport {fieldToChain, sameField} from './removeDuplicateDataFields.js';\nimport {fieldGetOccurrenceNumberPairs, fieldHasValidSubfield6, fieldSevenToOneOccurrenceNumber, fieldsToNormalizedString} from './subfield6Utils.js';\nimport {fieldHasSubfield, fieldsToString, fieldToString, /*nvdebug,*/ uniqArray} from './utils.js';\nimport {fieldHasValidSubfield8} from './subfield8Utils.js';\nimport {encodingLevelIsBetterThanPrepublication, fieldRefersToKoneellisestiTuotettuTietue, getEncodingLevel} from './prepublicationUtils.js';\nimport {cloneAndNormalizeFieldForComparison} from './normalizeFieldForComparison.js';\nimport {fixComposition, precomposeFinnishLetters} from './normalize-utf8-diacritics.js';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\n// NB! This validator handles only full fields, and does not support subfield $8 removal.\n// Also, having multiple $8 subfields in same fields is not supported.\n// If this functionality is needed, see removeDuplicateDatafields.js for examples of subfield-only stuff.\n\n// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeInferiorDataFields');\n//const debugData = debug.extend('data');\n//const debugDev = debug.extend('dev');\n\nexport default function () {\n return {\n description: 'Remove subset data fields. Certain exceptions apply, mainly too complicated for chained fields',\n validate, fix\n };\n\n function fix(record) {\n //nvdebug('Fix record: remove inferior (eg. subset) data fields', debugDev);\n const res = {message: [], fix: [], valid: true};\n removeInferiorDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n //nvdebug('Validate record: remove inferior (eg. subset) data fields', debugDev);\n\n const duplicates = removeInferiorDatafields(record, false);\n\n const res = {message: duplicates};\n\n res.valid = res.message.length < 1;\n return res;\n }\n}\n\n\nfunction deriveInferiorChains(fields, record) {\n //nvdebug(`======= GOT ${fields.length} FIELDS TO CHAINIFY`, debugDev);\n const hash = {};\n\n fields.forEach(f => fieldToChainToDeletables(f));\n\n return hash;\n\n //nvdebug(`WP1: GOT ${todoList.length} CHAINS`, debugDev);\n\n\n // here we map deletableStringObject[str] => field. The idea is to help debugging. We don't actually need the field object...\n //return deriveChainDeletables(todoList);\n\n function fieldToChainToDeletables(field) {\n const chain = fieldToChain(field, record);\n if (chain.length < 2) {\n return;\n }\n const chainAsString = fieldsToNormalizedString(chain, 0, true, true);\n const arr = deriveChainDeletables([chainAsString]);\n //nvdebug(`GOT ${arr.length} DELETABLES FOR ${chainAsString}`, debugDev);\n arr.forEach(val => {\n if (!(val in hash)) {\n hash[val] = field;\n }\n });\n }\n\n function deriveChainDeletables(todoList, deletables = []) {\n const [chainAsString, ...stillToDo] = todoList;\n if (chainAsString === undefined) {\n return deletables;\n }\n\n // Fix MRA-476 (part 1): one $6 value can be worse than the other\n const withoutScriptIdentificationCode = chainAsString.replace(/( \u20216 [0-9X][0-9][0-9]-(?:XX|[0-9]+))\\/[^ ]+/u, '$1');\n\n // Remove keepless versions:\n const keepless = chainAsString.replace(/ \u20219 [A-Z]+<KEEP>/u, '');\n\n // MRA-433: 490 ind1=1 vs ind1=0: remove latter (luckily no 2nd indicator etc)\n const linked490Ind1 = chainAsString.replace(/^490 1/u, '490 0').replace(/\\t880 1/ug, '\\t880 0');\n const arr = [withoutScriptIdentificationCode, keepless, linked490Ind1].filter(val => val !== chainAsString);\n if (arr.length > 0) {\n return deriveChainDeletables([...stillToDo, ...arr], [...deletables, ...arr]);\n }\n\n return deriveChainDeletables(stillToDo, deletables);\n }\n\n}\n\nfunction isRelevantChain6(field, record) {\n //Can't be a chain:\n if (!fieldHasValidSubfield6(field) && !fieldHasValidSubfield8(field)) {\n return false;\n }\n // Too short to be a chain:\n const chain = fieldToChain(field, record);\n if (chain.length < 2) {\n return false;\n }\n // No field can contains no more than one subfield $6\n if (chain.some(f => f.subfields.filter(sf => sf.code === '6').length > 1)) {\n return false;\n }\n\n // Check whether our field is the head of a chain:\n return sameField(field, chain[0]);\n}\n\nexport function removeInferiorChains(record, fix = true) {\n const fields = record.fields.filter(f => isRelevantChain6(f, record));\n //nvdebug(`WP2.0: GOT ${fields.length} chain(s)`, debugDev);\n\n const deletableChainsAsKeys = deriveInferiorChains(fields, record);\n const nChains = Object.keys(deletableChainsAsKeys).length;\n //nvdebug(`WP2: GOT ${nChains} chain(s)`, debugDev);\n if (nChains === 0) {\n return [];\n }\n\n //nvdebug(`removeInferiorChains() has ${fields.length} fields-in-chain(s), and a list of ${nChains} deletable(s)`, debugDev);\n\n return innerRemoveInferiorChains(fields);\n\n function innerRemoveInferiorChains(fields, deletedStringsArray = []) {\n const [currField, ...remainingFields] = fields;\n\n if (currField === undefined) {\n return deletedStringsArray;\n }\n\n const chain = fieldToChain(currField, record);\n if (chain.length === 0 || !sameField(currField, chain[0])) {\n return innerRemoveInferiorChains(remainingFields, deletedStringsArray);\n }\n\n const chainAsString = fieldsToNormalizedString(chain, 0, true, true);\n if (!(chainAsString in deletableChainsAsKeys)) {\n return innerRemoveInferiorChains(remainingFields, deletedStringsArray);\n }\n\n const triggeringField = deletableChainsAsKeys[chainAsString];\n const triggeringChain = fieldToChain(triggeringField, record);\n\n // If the inferior (deletable) chain is 1XX-based, convert the triggering better chain from 7XX to 1XX:\n if (chainContains1XX(chain)) {\n triggeringChain.forEach(f => sevenToOne(f, triggeringChain));\n }\n //nvdebug(`iRIS6C: ${chainAsString}`, debugDev);\n const deletedString = fieldsToString(chain);\n const message = `DEL: '${deletedString}' REASON: '${fieldsToString(triggeringChain)}'`;\n if (fix) {\n //nvdebug(`INFERIOR $6 CHAIN REMOVAL: ${message}}`, debugDev);\n chain.forEach(field => record.removeField(field));\n }\n return innerRemoveInferiorChains(remainingFields, [...deletedStringsArray, message]);\n }\n\n function chainContains1XX(chain) {\n return chain.some(f => f.tag.substring(0, 1) === '1');\n }\n\n function sevenToOne(field, chain) { // Change 7XX field to 1XX field. Also handle the corresponding 880$6 7XX-NN subfields\n // NB! This function should be called only if the original 1XX gets deleted!\n if (!['700', '710', '711', '730'].includes(field.tag)) {\n return;\n }\n // Retag field 7XX as 1XX and fix corresponding occurrence numbers as well:\n const pairs = fieldGetOccurrenceNumberPairs(field, chain);\n field.tag = `1${field.tag.substring(1)}`;\n // There should always be one pair, but I'm not sanity-checking this\n pairs.forEach(pairedField => fieldSevenToOneOccurrenceNumber(pairedField));\n }\n\n}\n\n\nfunction getIdentifierlessAndKeeplessSubsets(fieldAsString) {\n // The rules below are not perfect (in complex cases they don't catch all permutations), but good enough:\n // Remove identifier(s) (MELKEHITYS-2383-ish):\n\n const identifierlessString = fieldAsString.replace(/ \u2021[01] [^\u2021]+($| \u2021)/u, '$1');\n const keeplessString = fieldAsString.replace(/ \u20219 [A-Z]+<KEEP>/u, '');\n\n return [identifierlessString, keeplessString].filter(val => val !== fieldAsString);\n}\n\nfunction deriveIndividualDeletables490(todoList, deletables = []) {\n const [fieldAsString, ...stillToDo] = todoList;\n if (fieldAsString === undefined) {\n return deletables;\n }\n //nvdebug(`PROCESS ${fieldAsString}`, debugDev);\n if (!fieldAsString.match(/^490/u)) {\n return deriveIndividualDeletables490(stillToDo, deletables);\n }\n\n // $6-less version (keep this first)\n const sixless = fieldAsString.replace(/ \u20216 [^\u2021]+ \u2021/u, ' \u2021');\n\n // Without final $v or $x:\n const withoutFinalVOrX = fieldAsString.replace(/ *[;,] \u2021[vx] [^\u2021]+$/u, '');\n // Add intermediate $x-less version\n const xless = fieldAsString.replace(/, \u2021x [^\u2021]+(, \u2021x| ; \u2021v)/u, '$1');\n\n // Add $xv-less version (handled by recursion?)\n const xvless = fieldAsString.replace(/, \u2021x [^\u2021]+ \u2021v [^\u2021]+$/u, '');\n\n // MRA-433-ish (non-chain): 490 ind1=1 vs ind1=0: remove latter\n const modifiedInd2 = fieldAsString.match(/^490 1/u) ? `490 0${fieldAsString.substring(5)}` : fieldAsString;\n\n const arr = [sixless, withoutFinalVOrX, xless, xvless, modifiedInd2].filter(val => val !== fieldAsString);\n\n /*\n if (arr.length) {\n nvdebug(`${arr.length} derivation(s) for ${fieldAsString}`, debugDev);\n nvdebug(arr.join('\\n'), debugDev);\n }\n */\n return arr;\n}\n\n// eslint-disable-next-line max-lines-per-function\nfunction deriveIndividualDeletables(record) {\n const todoList = record.fields.map(f => fieldToString(f));\n //const finishedRecord = encodingLevelIsBetterThanPrepublication(getEncodingLevel(record));\n\n const deletableStringsArray = processTodoList(todoList);\n\n const inferiorTerms = getInferiorTerms(record);\n\n return uniqArray([...deletableStringsArray, ...inferiorTerms]);\n\n function getInferiorTerms(record) {\n const inputFields = record.fields.filter(f => ['648', '650', '651'].includes(f.tag) && f.subfields);\n const result = inputFields.flatMap(f => fieldToInferiorFields(f));\n\n // console.log(result.join('\\n')); // eslint-disable-line no-console\n return result;\n }\n\n function fieldToInferiorFields(field) {\n const aArray = field.subfields.filter(sf => sf.code === 'a');\n if (field.tag === '650') {\n return aArray.flatMap(sf => [`653 ## \u2021a ${sf.value}`, `653 #0 \u2021a ${sf.value}`]);\n }\n return aArray.map(sf => `653 ## \u2021a ${sf.value}`);\n }\n\n function processTodoList(thingsToDo, deletables = []) {\n const [currString, ...stillToDo] = thingsToDo;\n\n if (currString === undefined) {\n return deletables;\n }\n\n const accentless = getAccentlessVersion(currString);\n const d490 = deriveIndividualDeletables490([currString]);\n const subsets = getIdentifierlessAndKeeplessSubsets(currString);\n const moreToDo = [...accentless, ...d490, ...subsets];\n\n\n if (currString.match(/^[1678]00/u)) {\n // Proof-of-concept rule. Should be improved eventually...\n if (currString.match(/, \u2021e [^\u2021]+\\.$/u)) {\n const tmp = currString.replace(/, \u2021e [^\u2021]+\\.$/u, '.');\n return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n }\n\n if (currString.match(/^500 ## \u2021a Lis\u00E4painokset: Lis\u00E4painos /u)) { // MET-569\n const tmp1 = currString.replace(' Lis\u00E4painos ', ' [Lis\u00E4painos] ');\n const tmp2 = currString.replace(' Lis\u00E4painos ', ' ');\n if (tmp1 !== currString && tmp2 !== currString) {\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp1, tmp2]);\n }\n }\n\n if (currString.match(/^500 ## \u2021a Lis\u00E4painokset: \\[Lis\u00E4painos\\] /u)) { // MET-569\n const tmp = currString.replace(' [Lis\u00E4painos] ', ' ');\n if (tmp !== currString) {\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n }\n\n if (currString.match(/^500 ## \u2021a Ei vastaanotettu\\.$/u)) { // MELKEHITYS-3147\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, '500 ## \u2021a EI VASTAANOTETTU.']);\n }\n if (currString.match(/^500 ## \u2021a Ei ilmesty\\.$/u)) { // MELKEHITYS-3147\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, '500 ## \u2021a EI ILMESTY.']);\n }\n\n if (currString.match(/^505 .0.*-- \u2021t/u)) { // MRA-413-ish\n const tmp = currString.replace(/ -- \u2021t /gu, ' -- '). // remove non-initial $t subfields\n replace(/ \u2021[rg] /gu, ' '). // remove $r and $g subfields\n replace(/ \u2021t /u, ' \u2021a '). // change first $t to $a\n // ind2: '1' => '#':\n replace(/^505 (.)0/u, '505 $1#');\n if (tmp !== currString) {\n return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n //nvdebug(`505 ORIGINAL: '${fieldAsString}'`, debugDev)\n //nvdebug(`505 DERIVATE: '${tmp}'`, debugDev)\n }\n\n if (currString.match(/^594 ## \u2021a Ei vastaanotettu \u20215 FENNI$/u)) { // MELKEHITYS-3147\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, '594 ## \u2021a EI VASTAANOTETTU \u20215 FENNI']);\n }\n if (currString.match(/^594 ## \u2021a Ei ilmesty \u20215 FENNI$/u)) { // MELKEHITYS-3147\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, '594 ## \u2021a EI ILMESTY \u20215 FENNI']);\n }\n\n // MET-381: remove occurence number TAG-00, if TAG-NN existists\n if (currString.match(/^880.* \u20216 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {\n const tmp = currString.replace(/( \u20216 [0-9][0-9][0-9])-[0-9]+/u, '$1-00');\n //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`, debugDev);\n //deletableStringsArray.push(tmp);\n if (tmp.match(/ \u20216 [0-9][0-9][0-9]-00\\/[^ ]+ /u)) {\n const tmp2 = tmp.replace(/( \u20216 [0-9][0-9][0-9]-00)[^ ]+/u, '$1');\n //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp2}'`, debugDev);\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp, tmp2]);\n }\n return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n\n // MET-575 (merge: applies in postprocessing)\n const inferiorTerms = getPrepublicationTerms(currString);\n\n // MELKEHITYS-3277-ish: non-AI is better than AI (a rare case where longer version is inferior):\n const aiBased = `${currString} \u20217 (dpenmw)AI`;\n\n const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms, aiBased];\n\n if (subsets.length) {\n return processTodoList([...stillToDo, ...moreToDo], newDeletables);\n }\n\n return processTodoList([...stillToDo, ...moreToDo], newDeletables);\n }\n\n function getAccentlessVersion(string) { // MET-527\n //nvdebug(`START: '${string}`, debugDev);\n // This is a sanity check: if precomposition does something, there's something wrong, and we don't want to proceed..\n if (string !== precomposeFinnishLetters(string)) {\n return [];\n }\n const accentless = String(fixComposition(string)).replace(/\\p{Diacritic}/gu, '');\n //nvdebug(`FROM '${string}'\\n TO '${accentless}'`, debugDev);\n if (accentless === string) { // Don't self-destruct\n return [];\n }\n return [accentless];\n }\n\n function getPrepublicationTerms(fieldAsString) {\n const subfield7Prepub = `${fieldAsString} \u20217 Ennakkotieto`\n if (fieldAsString.match(/^653./u)) {\n // MET-528 (extented by MET-575)\n return [subfield7Prepub, `${fieldAsString} \u2021g ENNAKKOTIETO`, `${fieldAsString} \u2021g Ennakkotieto`, `${fieldAsString} \u2021g ennakkotieto`, `${fieldAsString} \u2021g ENNAKKOTIETO.`, `${fieldAsString} \u2021g Ennakkotieto.`, `${fieldAsString} \u2021g ennakkotieto.`];\n }\n\n return [subfield7Prepub];\n }\n\n}\n\nfunction fieldToNormalizedString(field) {\n const normalizedField = cloneAndNormalizeFieldForComparison(field);\n return fieldToString(normalizedField);\n}\n\nfunction deriveIndividualNormalizedDeletables(record) { // MET-461:\n const encodingLevel = getEncodingLevel(record);\n const recordIsFinished = encodingLevelIsBetterThanPrepublication(encodingLevel);\n const met495 = encodingLevel === '2' && record.fields.some(f => f.tag === '500' && fieldRefersToKoneellisestiTuotettuTietue(f));\n if (!recordIsFinished || met495) {\n return [];\n }\n const relevantFields = record.fields.filter(f => ['245', '246'].includes(f.tag) && fieldHasSubfield(f, 'a'));\n\n return deriveDeletable946s(relevantFields);\n\n function deriveDeletable946s(fields, results = []) {\n const [currField, ...remainingFields] = fields;\n if (currField === undefined) {\n return results;\n }\n\n const fieldAsNormalizedString = fieldToNormalizedString(currField);\n const tmp = fieldAsNormalizedString.replace(/^(?:...) ../u, '946 ##'). // <= Change tag to 946 and indicators to '##'\n replace(' \u2021a ', ' \u2021i nimeke onixissa \u2021a '). // Add $i before $a. NB! This is added in the normalized lower-cased form!\n replace(/(?: \\/)? \u2021c[^\u2021]+$/u, ''); // Remove $c. (Can $c be non-last?)\n const candArray = [tmp, `${tmp} \u20215 MELINDA`].filter(val => val !== fieldAsNormalizedString);\n if (candArray.length) {\n return deriveDeletable946s(remainingFields, [...results, ...candArray]);\n }\n return deriveDeletable946s(remainingFields, results);\n }\n}\n\nexport function removeIndividualInferiorDatafields(record, fix = true) { // No $6 nor $8 in field\n const deletableFieldsAsStrings = deriveIndividualDeletables(record);\n const deletableFieldsAsNormalizedStrings = deriveIndividualNormalizedDeletables(record);\n\n // nvdebug(`Deletables:\\n ${deletableFieldsAsStrings.join('\\n ')}`, debugDev);\n // nvdebug(`Normalized deletables:\\n ${deletableFieldsAsNormalizedStrings.join('\\n ')}`, debugDev);\n\n const hits = record.fields.filter(field => isDeletableField(field));\n\n const deletedFieldsAsStrings = hits.map(f => fieldToString(f));\n\n if (fix) {\n hits.forEach(field => {\n //nvdebug(`Remove inferior field: ${fieldToString(field)}`, debugDev);\n record.removeField(field);\n });\n }\n\n return deletedFieldsAsStrings;\n\n function isDeletableField(field) {\n const fieldAsString = fieldToString(field);\n if (deletableFieldsAsStrings.includes(fieldAsString)) {\n return true;\n }\n const fieldAsNormalizedString = fieldToNormalizedString(field);\n if (deletableFieldsAsNormalizedStrings.includes(fieldAsNormalizedString)) {\n return true;\n }\n\n return false;\n }\n}\n\n\nexport function removeInferiorDatafields(record, fix = true) {\n const removables = removeIndividualInferiorDatafields(record, fix); // Lone fields\n //const removables8 = removeDuplicateSubfield8Chains(record, fix); // Lone subfield $8 chains\n const removables6 = removeInferiorChains(record, fix); // Lone subfield $6 chains\n // HOW TO HANDLE $6+$8 combos? Skipping is relatively OK.\n\n //nvdebug(`REMOVABLES:\\n ${removables.join('\\n ')}`, debugDev);\n //nvdebug(`REMOVABLES 6:\\n ${removables6.join('\\n ')}`, debugDev);\n\n const removablesAll = removables.concat(removables6); //.concat(removables8);\n\n return removablesAll;\n}\n"],
5
- "mappings": "AACA,SAAQ,cAAc,iBAAgB;AACtC,SAAQ,+BAA+B,wBAAwB,iCAAiC,gCAA+B;AAC/H,SAAQ,kBAAkB,gBAAgB,eAA4B,iBAAgB;AACtF,SAAQ,8BAA6B;AACrC,SAAQ,yCAAyC,0CAA0C,wBAAuB;AAClH,SAAQ,2CAA0C;AAClD,SAAQ,gBAAgB,gCAA+B;AAYvD,0BAA2B;AACzB,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IAAU;AAAA,EACZ;AAEA,WAAS,IAAI,QAAQ;AAEnB,UAAM,MAAM,EAAC,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO,KAAI;AAC9C,6BAAyB,QAAQ,IAAI;AAErC,WAAO;AAAA,EACT;AAEA,WAAS,SAAS,QAAQ;AAIxB,UAAM,aAAa,yBAAyB,QAAQ,KAAK;AAEzD,UAAM,MAAM,EAAC,SAAS,WAAU;AAEhC,QAAI,QAAQ,IAAI,QAAQ,SAAS;AACjC,WAAO;AAAA,EACT;AACF;AAGA,SAAS,qBAAqB,QAAQ,QAAQ;AAE5C,QAAM,OAAO,CAAC;AAEd,SAAO,QAAQ,OAAK,yBAAyB,CAAC,CAAC;AAE/C,SAAO;AAQP,WAAS,yBAAyB,OAAO;AACvC,UAAM,QAAQ,aAAa,OAAO,MAAM;AACxC,QAAI,MAAM,SAAS,GAAG;AACpB;AAAA,IACF;AACA,UAAM,gBAAgB,yBAAyB,OAAO,GAAG,MAAM,IAAI;AACnE,UAAM,MAAM,sBAAsB,CAAC,aAAa,CAAC;AAEjD,QAAI,QAAQ,SAAO;AACjB,UAAI,EAAE,OAAO,OAAO;AAClB,aAAK,GAAG,IAAI;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,sBAAsB,UAAU,aAAa,CAAC,GAAG;AACxD,UAAM,CAAC,eAAe,GAAG,SAAS,IAAI;AACtC,QAAI,kBAAkB,QAAW;AAC/B,aAAO;AAAA,IACT;AAGA,UAAM,kCAAkC,cAAc,QAAQ,gDAAgD,IAAI;AAGlH,UAAM,WAAW,cAAc,QAAQ,qBAAqB,EAAE;AAG9D,UAAM,gBAAgB,cAAc,QAAQ,WAAW,OAAO,EAAE,QAAQ,aAAa,QAAS;AAC9F,UAAM,MAAM,CAAC,iCAAiC,UAAU,aAAa,EAAE,OAAO,SAAO,QAAQ,aAAa;AAC1G,QAAI,IAAI,SAAS,GAAG;AAClB,aAAO,sBAAsB,CAAC,GAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GAAG,YAAY,GAAG,GAAG,CAAC;AAAA,IAC9E;AAEA,WAAO,sBAAsB,WAAW,UAAU;AAAA,EACpD;AAEF;AAEA,SAAS,iBAAiB,OAAO,QAAQ;AAEvC,MAAI,CAAC,uBAAuB,KAAK,KAAK,CAAC,uBAAuB,KAAK,GAAG;AACpE,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,aAAa,OAAO,MAAM;AACxC,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,KAAK,OAAK,EAAE,UAAU,OAAO,QAAM,GAAG,SAAS,GAAG,EAAE,SAAS,CAAC,GAAG;AACzE,WAAO;AAAA,EACT;AAGA,SAAO,UAAU,OAAO,MAAM,CAAC,CAAC;AAClC;AAEO,gBAAS,qBAAqB,QAAQ,MAAM,MAAM;AACvD,QAAM,SAAS,OAAO,OAAO,OAAO,OAAK,iBAAiB,GAAG,MAAM,CAAC;AAGpE,QAAM,wBAAwB,qBAAqB,QAAQ,MAAM;AACjE,QAAM,UAAU,OAAO,KAAK,qBAAqB,EAAE;AAEnD,MAAI,YAAY,GAAG;AACjB,WAAO,CAAC;AAAA,EACV;AAIA,SAAO,0BAA0B,MAAM;AAEvC,WAAS,0BAA0BA,SAAQ,sBAAsB,CAAC,GAAG;AACnE,UAAM,CAAC,WAAW,GAAG,eAAe,IAAIA;AAExC,QAAI,cAAc,QAAW;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,aAAa,WAAW,MAAM;AAC5C,QAAI,MAAM,WAAW,KAAK,CAAC,UAAU,WAAW,MAAM,CAAC,CAAC,GAAG;AACzD,aAAO,0BAA0B,iBAAiB,mBAAmB;AAAA,IACvE;AAEA,UAAM,gBAAgB,yBAAyB,OAAO,GAAG,MAAM,IAAI;AACnE,QAAI,EAAE,iBAAiB,wBAAwB;AAC7C,aAAO,0BAA0B,iBAAiB,mBAAmB;AAAA,IACvE;AAEA,UAAM,kBAAkB,sBAAsB,aAAa;AAC3D,UAAM,kBAAkB,aAAa,iBAAiB,MAAM;AAG5D,QAAI,iBAAiB,KAAK,GAAG;AAC3B,sBAAgB,QAAQ,OAAK,WAAW,GAAG,eAAe,CAAC;AAAA,IAC7D;AAEA,UAAM,gBAAgB,eAAe,KAAK;AAC1C,UAAM,UAAU,SAAS,aAAa,eAAe,eAAe,eAAe,CAAC;AACpF,QAAI,KAAK;AAEP,YAAM,QAAQ,WAAS,OAAO,YAAY,KAAK,CAAC;AAAA,IAClD;AACA,WAAO,0BAA0B,iBAAiB,CAAC,GAAG,qBAAqB,OAAO,CAAC;AAAA,EACrF;AAEA,WAAS,iBAAiB,OAAO;AAC/B,WAAO,MAAM,KAAK,OAAK,EAAE,IAAI,UAAU,GAAG,CAAC,MAAM,GAAG;AAAA,EACtD;AAEA,WAAS,WAAW,OAAO,OAAO;AAEhC,QAAI,CAAC,CAAC,OAAO,OAAO,OAAO,KAAK,EAAE,SAAS,MAAM,GAAG,GAAG;AACrD;AAAA,IACF;AAEA,UAAM,QAAQ,8BAA8B,OAAO,KAAK;AACxD,UAAM,MAAM,IAAI,MAAM,IAAI,UAAU,CAAC,CAAC;AAEtC,UAAM,QAAQ,iBAAe,gCAAgC,WAAW,CAAC;AAAA,EAC3E;AAEF;AAGA,SAAS,oCAAoC,eAAe;AAI1D,QAAM,uBAAuB,cAAc,QAAQ,uBAAuB,IAAI;AAC9E,QAAM,iBAAiB,cAAc,QAAQ,qBAAqB,EAAE;AAEpE,SAAO,CAAC,sBAAsB,cAAc,EAAE,OAAO,SAAO,QAAQ,aAAa;AACnF;AAEA,SAAS,8BAA8B,UAAU,aAAa,CAAC,GAAG;AAChE,QAAM,CAAC,eAAe,GAAG,SAAS,IAAI;AACtC,MAAI,kBAAkB,QAAW;AAC/B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,MAAM,OAAO,GAAG;AACjC,WAAO,8BAA8B,WAAW,UAAU;AAAA,EAC5D;AAGA,QAAM,UAAU,cAAc,QAAQ,gBAAgB,SAAI;AAG1D,QAAM,mBAAmB,cAAc,QAAQ,wBAAwB,EAAE;AAEzE,QAAM,QAAQ,cAAc,QAAQ,2BAA2B,IAAI;AAGnE,QAAM,SAAS,cAAc,QAAQ,yBAAyB,EAAE;AAGhE,QAAM,eAAe,cAAc,MAAM,SAAS,IAAI,QAAQ,cAAc,UAAU,CAAC,CAAC,KAAK;AAE7F,QAAM,MAAM,CAAC,SAAS,kBAAkB,OAAO,QAAQ,YAAY,EAAE,OAAO,SAAO,QAAQ,aAAa;AAQxG,SAAO;AACT;AAGA,SAAS,2BAA2B,QAAQ;AAC1C,QAAM,WAAW,OAAO,OAAO,IAAI,OAAK,cAAc,CAAC,CAAC;AAGxD,QAAM,wBAAwB,gBAAgB,QAAQ;AAEtD,QAAM,gBAAgB,iBAAiB,MAAM;AAE7C,SAAO,UAAU,CAAC,GAAG,uBAAuB,GAAG,aAAa,CAAC;AAE7D,WAAS,iBAAiBC,SAAQ;AAChC,UAAM,cAAcA,QAAO,OAAO,OAAO,OAAK,CAAC,OAAO,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,SAAS;AAClG,UAAM,SAAS,YAAY,QAAQ,OAAK,sBAAsB,CAAC,CAAC;AAGhE,WAAO;AAAA,EACT;AAEA,WAAS,sBAAsB,OAAO;AACpC,UAAM,SAAS,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,GAAG;AAC3D,QAAI,MAAM,QAAQ,OAAO;AACvB,aAAO,OAAO,QAAQ,QAAM,CAAC,kBAAa,GAAG,KAAK,IAAI,kBAAa,GAAG,KAAK,EAAE,CAAC;AAAA,IAChF;AACA,WAAO,OAAO,IAAI,QAAM,kBAAa,GAAG,KAAK,EAAE;AAAA,EACjD;AAEA,WAAS,gBAAgB,YAAY,aAAa,CAAC,GAAG;AACpD,UAAM,CAAC,YAAY,GAAG,SAAS,IAAI;AAEnC,QAAI,eAAe,QAAW;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,qBAAqB,UAAU;AAClD,UAAM,OAAO,8BAA8B,CAAC,UAAU,CAAC;AACvD,UAAM,UAAU,oCAAoC,UAAU;AAC9D,UAAM,WAAW,CAAC,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO;AAGpD,QAAI,WAAW,MAAM,YAAY,GAAG;AAElC,UAAI,WAAW,MAAM,gBAAgB,GAAG;AACtC,cAAM,MAAM,WAAW,QAAQ,kBAAkB,GAAG;AACpD,eAAO,gBAAgB,CAAC,KAAK,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC;AAAA,MAC/E;AAAA,IACF;AAEA,QAAI,WAAW,MAAM,wCAAwC,GAAG;AAC9D,YAAM,OAAO,WAAW,QAAQ,mBAAgB,mBAAgB;AAChE,YAAM,OAAO,WAAW,QAAQ,mBAAgB,GAAG;AACnD,UAAI,SAAS,cAAc,SAAS,YAAY;AAC9C,eAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,MAAM,IAAI,CAAC;AAAA,MACjF;AAAA,IACF;AAEA,QAAI,WAAW,MAAM,4CAA4C,GAAG;AAClE,YAAM,MAAM,WAAW,QAAQ,qBAAkB,GAAG;AACpD,UAAI,QAAQ,YAAY;AACtB,eAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC;AAAA,MAC1E;AAAA,IACF;AAEA,QAAI,WAAW,MAAM,iCAAiC,GAAG;AACvD,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,kCAA6B,CAAC;AAAA,IACpG;AACA,QAAI,WAAW,MAAM,2BAA2B,GAAG;AACjD,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,4BAAuB,CAAC;AAAA,IAC9F;AAEA,QAAI,WAAW,MAAM,iBAAiB,GAAG;AACvC,YAAM,MAAM,WAAW,QAAQ,aAAa,MAAM,EAChD,QAAQ,aAAa,GAAG,EACxB,QAAQ,SAAS,WAAM,EAEvB,QAAQ,cAAc,SAAS;AACjC,UAAI,QAAQ,YAAY;AACtB,eAAO,gBAAgB,CAAC,KAAK,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC;AAAA,MAC/E;AAAA,IAGF;AAEA,QAAI,WAAW,MAAM,wCAAwC,GAAG;AAC9D,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,+CAAqC,CAAC;AAAA,IAC5G;AACA,QAAI,WAAW,MAAM,kCAAkC,GAAG;AACxD,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,yCAA+B,CAAC;AAAA,IACtG;AAGA,QAAI,WAAW,MAAM,kDAAkD,GAAG;AACxE,YAAM,MAAM,WAAW,QAAQ,iCAAiC,OAAO;AAGvE,UAAI,IAAI,MAAM,iCAAiC,GAAG;AAChD,cAAM,OAAO,IAAI,QAAQ,kCAAkC,IAAI;AAE/D,eAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,KAAK,IAAI,CAAC;AAAA,MAChF;AACA,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC;AAAA,IAC1E;AAGA,UAAMC,iBAAgB,uBAAuB,UAAU;AAGvD,UAAM,UAAU,GAAG,UAAU;AAE7B,UAAM,gBAAgB,CAAC,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,GAAGA,gBAAe,OAAO;AAEnG,QAAI,QAAQ,QAAQ;AAClB,aAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa;AAAA,IACnE;AAEA,WAAO,gBAAgB,CAAC,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa;AAAA,EACnE;AAEA,WAAS,qBAAqB,QAAQ;AAGpC,QAAI,WAAW,yBAAyB,MAAM,GAAG;AAC/C,aAAO,CAAC;AAAA,IACV;AACA,UAAM,aAAa,OAAO,eAAe,MAAM,CAAC,EAAE,QAAQ,mBAAmB,EAAE;AAE/E,QAAI,eAAe,QAAQ;AACzB,aAAO,CAAC;AAAA,IACV;AACA,WAAO,CAAC,UAAU;AAAA,EACpB;AAEA,WAAS,uBAAuB,eAAe;AAC7C,UAAM,kBAAkB,GAAG,aAAa;AACxC,QAAI,cAAc,MAAM,QAAQ,GAAG;AAEjC,aAAO,CAAC,iBAAiB,GAAG,aAAa,yBAAoB,GAAG,aAAa,yBAAoB,GAAG,aAAa,yBAAoB,GAAG,aAAa,0BAAqB,GAAG,aAAa,0BAAqB,GAAG,aAAa,wBAAmB;AAAA,IACpP;AAEA,WAAO,CAAC,eAAe;AAAA,EACzB;AAEF;AAEA,SAAS,wBAAwB,OAAO;AACtC,QAAM,kBAAkB,oCAAoC,KAAK;AACjE,SAAO,cAAc,eAAe;AACtC;AAEA,SAAS,qCAAqC,QAAQ;AACpD,QAAM,gBAAgB,iBAAiB,MAAM;AAC7C,QAAM,mBAAmB,wCAAwC,aAAa;AAC9E,QAAM,SAAS,kBAAkB,OAAO,OAAO,OAAO,KAAK,OAAK,EAAE,QAAQ,SAAS,yCAAyC,CAAC,CAAC;AAC9H,MAAI,CAAC,oBAAoB,QAAQ;AAC/B,WAAO,CAAC;AAAA,EACV;AACA,QAAM,iBAAiB,OAAO,OAAO,OAAO,OAAK,CAAC,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,iBAAiB,GAAG,GAAG,CAAC;AAE3G,SAAO,oBAAoB,cAAc;AAEzC,WAAS,oBAAoB,QAAQ,UAAU,CAAC,GAAG;AACjD,UAAM,CAAC,WAAW,GAAG,eAAe,IAAI;AACxC,QAAI,cAAc,QAAW;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,0BAA0B,wBAAwB,SAAS;AACjE,UAAM,MAAM,wBAAwB,QAAQ,gBAAgB,QAAQ,EAClE,QAAQ,aAAQ,mCAAyB,EACzC,QAAQ,sBAAsB,EAAE;AAClC,UAAM,YAAY,CAAC,KAAK,GAAG,GAAG,kBAAa,EAAE,OAAO,SAAO,QAAQ,uBAAuB;AAC1F,QAAI,UAAU,QAAQ;AACpB,aAAO,oBAAoB,iBAAiB,CAAC,GAAG,SAAS,GAAG,SAAS,CAAC;AAAA,IACxE;AACA,WAAO,oBAAoB,iBAAiB,OAAO;AAAA,EACrD;AACF;AAEO,gBAAS,mCAAmC,QAAQ,MAAM,MAAM;AACrE,QAAM,2BAA2B,2BAA2B,MAAM;AAClE,QAAM,qCAAqC,qCAAqC,MAAM;AAKtF,QAAM,OAAO,OAAO,OAAO,OAAO,WAAS,iBAAiB,KAAK,CAAC;AAElE,QAAM,yBAAyB,KAAK,IAAI,OAAK,cAAc,CAAC,CAAC;AAE7D,MAAI,KAAK;AACP,SAAK,QAAQ,WAAS;AAEpB,aAAO,YAAY,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAEA,SAAO;AAEP,WAAS,iBAAiB,OAAO;AAC/B,UAAM,gBAAgB,cAAc,KAAK;AACzC,QAAI,yBAAyB,SAAS,aAAa,GAAG;AACpD,aAAO;AAAA,IACT;AACA,UAAM,0BAA0B,wBAAwB,KAAK;AAC7D,QAAI,mCAAmC,SAAS,uBAAuB,GAAG;AACxE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;AAGO,gBAAS,yBAAyB,QAAQ,MAAM,MAAM;AAC3D,QAAM,aAAa,mCAAmC,QAAQ,GAAG;AAEjE,QAAM,cAAc,qBAAqB,QAAQ,GAAG;AAMpD,QAAM,gBAAgB,WAAW,OAAO,WAAW;AAEnD,SAAO;AACT;",
6
- "names": ["fields", "record", "inferiorTerms"]
4
+ "sourcesContent": ["//import createDebugLogger from 'debug';\nimport {fieldToChain, sameField} from './removeDuplicateDataFields.js';\nimport {fieldGetOccurrenceNumberPairs, fieldHasValidSubfield6, fieldSevenToOneOccurrenceNumber, fieldsToNormalizedString} from './subfield6Utils.js';\nimport {fieldHasSubfield, fieldsToString, fieldToString, /*nvdebug,*/ uniqArray} from './utils.js';\nimport {fieldHasValidSubfield8} from './subfield8Utils.js';\nimport {encodingLevelIsBetterThanPrepublication, fieldRefersToKoneellisestiTuotettuTietue, getEncodingLevel} from './prepublicationUtils.js';\nimport {cloneAndNormalizeFieldForComparison} from './normalizeFieldForComparison.js';\nimport {fixComposition, precomposeFinnishLetters} from './normalize-utf8-diacritics.js';\n\n// Relocated from melinda-marc-record-merge-reducers (and renamed)\n\n// NB! This validator handles only full fields, and does not support subfield $8 removal.\n// Also, having multiple $8 subfields in same fields is not supported.\n// If this functionality is needed, see removeDuplicateDatafields.js for examples of subfield-only stuff.\n\n// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:removeInferiorDataFields');\n//const debugData = debug.extend('data');\n//const debugDev = debug.extend('dev');\n\nexport default function () {\n return {\n description: 'Remove subset data fields. Certain exceptions apply, mainly too complicated for chained fields',\n validate, fix\n };\n\n function fix(record) {\n //nvdebug('Fix record: remove inferior (eg. subset) data fields', debugDev);\n const res = {message: [], fix: [], valid: true};\n removeInferiorDatafields(record, true);\n // This can not really fail...\n return res;\n }\n\n function validate(record) {\n // Check max, and check number of different indexes\n //nvdebug('Validate record: remove inferior (eg. subset) data fields', debugDev);\n\n const duplicates = removeInferiorDatafields(record, false);\n\n const res = {message: duplicates};\n\n res.valid = res.message.length < 1;\n return res;\n }\n}\n\n\nfunction deriveInferiorChains(fields, record) {\n //nvdebug(`======= GOT ${fields.length} FIELDS TO CHAINIFY`, debugDev);\n const hash = {};\n\n fields.forEach(f => fieldToChainToDeletables(f));\n\n return hash;\n\n //nvdebug(`WP1: GOT ${todoList.length} CHAINS`, debugDev);\n\n\n // here we map deletableStringObject[str] => field. The idea is to help debugging. We don't actually need the field object...\n //return deriveChainDeletables(todoList);\n\n function fieldToChainToDeletables(field) {\n const chain = fieldToChain(field, record);\n if (chain.length < 2) {\n return;\n }\n const chainAsString = fieldsToNormalizedString(chain, 0, true, true);\n const arr = deriveChainDeletables([chainAsString]);\n //nvdebug(`GOT ${arr.length} DELETABLES FOR ${chainAsString}`, debugDev);\n arr.forEach(val => {\n if (!(val in hash)) {\n hash[val] = field;\n }\n });\n }\n\n function deriveChainDeletables(todoList, deletables = []) {\n const [chainAsString, ...stillToDo] = todoList;\n if (chainAsString === undefined) {\n return deletables;\n }\n\n // Fix MRA-476 (part 1): one $6 value can be worse than the other\n const withoutScriptIdentificationCode = chainAsString.replace(/( \u20216 [0-9X][0-9][0-9]-(?:XX|[0-9]+))\\/[^ ]+/u, '$1');\n\n // Remove keepless versions:\n const keepless = chainAsString.replace(/ \u20219 [A-Z]+<KEEP>/u, '');\n\n // MRA-433: 490 ind1=1 vs ind1=0: remove latter (luckily no 2nd indicator etc)\n const linked490Ind1 = chainAsString.replace(/^490 1/u, '490 0').replace(/\\t880 1/ug, '\\t880 0');\n const arr = [withoutScriptIdentificationCode, keepless, linked490Ind1].filter(val => val !== chainAsString);\n if (arr.length > 0) {\n return deriveChainDeletables([...stillToDo, ...arr], [...deletables, ...arr]);\n }\n\n return deriveChainDeletables(stillToDo, deletables);\n }\n\n}\n\nfunction isRelevantChain6(field, record) {\n //Can't be a chain:\n if (!fieldHasValidSubfield6(field) && !fieldHasValidSubfield8(field)) {\n return false;\n }\n // Too short to be a chain:\n const chain = fieldToChain(field, record);\n if (chain.length < 2) {\n return false;\n }\n // No field can contains no more than one subfield $6\n if (chain.some(f => f.subfields.filter(sf => sf.code === '6').length > 1)) {\n return false;\n }\n\n // Check whether our field is the head of a chain:\n return sameField(field, chain[0]);\n}\n\nexport function removeInferiorChains(record, fix = true) {\n const fields = record.fields.filter(f => isRelevantChain6(f, record));\n //nvdebug(`WP2.0: GOT ${fields.length} chain(s)`, debugDev);\n\n const deletableChainsAsKeys = deriveInferiorChains(fields, record);\n const nChains = Object.keys(deletableChainsAsKeys).length;\n //nvdebug(`WP2: GOT ${nChains} chain(s)`, debugDev);\n if (nChains === 0) {\n return [];\n }\n\n //nvdebug(`removeInferiorChains() has ${fields.length} fields-in-chain(s), and a list of ${nChains} deletable(s)`, debugDev);\n\n return innerRemoveInferiorChains(fields);\n\n function innerRemoveInferiorChains(fields, deletedStringsArray = []) {\n const [currField, ...remainingFields] = fields;\n\n if (currField === undefined) {\n return deletedStringsArray;\n }\n\n const chain = fieldToChain(currField, record);\n if (chain.length === 0 || !sameField(currField, chain[0])) {\n return innerRemoveInferiorChains(remainingFields, deletedStringsArray);\n }\n\n const chainAsString = fieldsToNormalizedString(chain, 0, true, true);\n if (!(chainAsString in deletableChainsAsKeys)) {\n return innerRemoveInferiorChains(remainingFields, deletedStringsArray);\n }\n\n const triggeringField = deletableChainsAsKeys[chainAsString];\n const triggeringChain = fieldToChain(triggeringField, record);\n\n // If the inferior (deletable) chain is 1XX-based, convert the triggering better chain from 7XX to 1XX:\n if (chainContains1XX(chain)) {\n triggeringChain.forEach(f => sevenToOne(f, triggeringChain));\n }\n //nvdebug(`iRIS6C: ${chainAsString}`, debugDev);\n const deletedString = fieldsToString(chain);\n const message = `DEL: '${deletedString}' REASON: '${fieldsToString(triggeringChain)}'`;\n if (fix) {\n //nvdebug(`INFERIOR $6 CHAIN REMOVAL: ${message}}`, debugDev);\n chain.forEach(field => record.removeField(field));\n }\n return innerRemoveInferiorChains(remainingFields, [...deletedStringsArray, message]);\n }\n\n function chainContains1XX(chain) {\n return chain.some(f => f.tag.substring(0, 1) === '1');\n }\n\n function sevenToOne(field, chain) { // Change 7XX field to 1XX field. Also handle the corresponding 880$6 7XX-NN subfields\n // NB! This function should be called only if the original 1XX gets deleted!\n if (!['700', '710', '711', '730'].includes(field.tag)) {\n return;\n }\n // Retag field 7XX as 1XX and fix corresponding occurrence numbers as well:\n const pairs = fieldGetOccurrenceNumberPairs(field, chain);\n field.tag = `1${field.tag.substring(1)}`;\n // There should always be one pair, but I'm not sanity-checking this\n pairs.forEach(pairedField => fieldSevenToOneOccurrenceNumber(pairedField));\n }\n\n}\n\n\nfunction getIdentifierlessAndKeeplessSubsets(fieldAsString) {\n // The rules below are not perfect (in complex cases they don't catch all permutations), but good enough:\n // Remove identifier(s) (MELKEHITYS-2383-ish):\n\n const identifierlessString = fieldAsString.replace(/ \u2021[01] [^\u2021]+($| \u2021)/u, '$1');\n const keeplessString = fieldAsString.replace(/ \u20219 [A-Z]+<KEEP>/u, '');\n\n return [identifierlessString, keeplessString].filter(val => val !== fieldAsString);\n}\n\nfunction deriveIndividualDeletables490(todoList, deletables = []) {\n const [fieldAsString, ...stillToDo] = todoList;\n if (fieldAsString === undefined) {\n return deletables;\n }\n //nvdebug(`PROCESS ${fieldAsString}`, debugDev);\n if (!fieldAsString.match(/^490/u)) {\n return deriveIndividualDeletables490(stillToDo, deletables);\n }\n\n // $6-less version (keep this first)\n const sixless = fieldAsString.replace(/ \u20216 [^\u2021]+ \u2021/u, ' \u2021');\n\n // Without final $v or $x:\n const withoutFinalVOrX = fieldAsString.replace(/ *[;,] \u2021[vx] [^\u2021]+$/u, '');\n // Add intermediate $x-less version\n const xless = fieldAsString.replace(/, \u2021x [^\u2021]+(, \u2021x| ; \u2021v)/u, '$1');\n\n // Add $xv-less version (handled by recursion?)\n const xvless = fieldAsString.replace(/, \u2021x [^\u2021]+ \u2021v [^\u2021]+$/u, '');\n\n // MRA-433-ish (non-chain): 490 ind1=1 vs ind1=0: remove latter\n const modifiedInd2 = fieldAsString.match(/^490 1/u) ? `490 0${fieldAsString.substring(5)}` : fieldAsString;\n\n const arr = [sixless, withoutFinalVOrX, xless, xvless, modifiedInd2].filter(val => val !== fieldAsString);\n\n /*\n if (arr.length) {\n nvdebug(`${arr.length} derivation(s) for ${fieldAsString}`, debugDev);\n nvdebug(arr.join('\\n'), debugDev);\n }\n */\n return arr;\n}\n\n// eslint-disable-next-line max-lines-per-function\nfunction deriveIndividualDeletables(record) {\n const todoList = record.fields.map(f => fieldToString(f));\n //const finishedRecord = encodingLevelIsBetterThanPrepublication(getEncodingLevel(record));\n\n const deletableStringsArray = processTodoList(todoList);\n\n const inferiorTerms = getInferiorTerms(record);\n\n return uniqArray([...deletableStringsArray, ...inferiorTerms]);\n\n function getInferiorTerms(record) {\n const inputFields = record.fields.filter(f => ['648', '650', '651'].includes(f.tag) && f.subfields);\n const result = inputFields.flatMap(f => fieldToInferiorFields(f));\n\n // console.log(result.join('\\n')); // eslint-disable-line no-console\n return result;\n }\n\n function fieldToInferiorFields(field) {\n const aArray = field.subfields.filter(sf => sf.code === 'a');\n if (field.tag === '650') {\n return aArray.flatMap(sf => [`653 ## \u2021a ${sf.value}`, `653 #0 \u2021a ${sf.value}`]);\n }\n return aArray.map(sf => `653 ## \u2021a ${sf.value}`);\n }\n\n function processTodoList(thingsToDo, deletables = []) {\n const [currString, ...stillToDo] = thingsToDo;\n\n if (currString === undefined) {\n return deletables;\n }\n\n const accentless = getAccentlessVersion(currString);\n const d490 = deriveIndividualDeletables490([currString]);\n const subsets = getIdentifierlessAndKeeplessSubsets(currString);\n const moreToDo = [...accentless, ...d490, ...subsets];\n\n\n if (currString.match(/^[1678]00/u)) {\n // Proof-of-concept rule. Should be improved eventually...\n if (currString.match(/, \u2021e [^\u2021]+\\.$/u)) {\n const tmp = currString.replace(/, \u2021e [^\u2021]+\\.$/u, '.');\n return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n }\n\n if (currString.match(/^505 .0.*-- \u2021t/u)) { // MRA-413-ish\n const tmp = currString.replace(/ -- \u2021t /gu, ' -- '). // remove non-initial $t subfields\n replace(/ \u2021[rg] /gu, ' '). // remove $r and $g subfields\n replace(/ \u2021t /u, ' \u2021a '). // change first $t to $a\n // ind2: '1' => '#':\n replace(/^505 (.)0/u, '505 $1#');\n if (tmp !== currString) {\n return processTodoList([tmp, ...stillToDo, ...moreToDo], [...deletables, tmp]);\n }\n //nvdebug(`505 ORIGINAL: '${fieldAsString}'`, debugDev)\n //nvdebug(`505 DERIVATE: '${tmp}'`, debugDev)\n }\n\n const inferiorFunctions = [ getPrepublicationTerms, getInferior341, getAiBased, getMelkehitys3147, getMet831, getMet569 ];\n\n const inferiorTerms = getInferiorTerms(inferiorFunctions); //getPrepublicationTerms(currString);\n\n const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms];\n\n return processTodoList([...stillToDo, ...moreToDo], newDeletables);\n\n function getInferiorTerms(functions, results = []) {\n const [currFunction, ...remainingFunctions] = functions;\n if (!currFunction) {\n return results\n }\n const newDeletables = currFunction(currString);\n return getInferiorTerms(remainingFunctions, [...results, ...newDeletables]);\n }\n\n function getMet569(string) {\n if (string.match(/^500 ## \u2021a Lis\u00E4painokset: Lis\u00E4painos /u)) { // MET-569\n const tmp1 = string.replace(' Lis\u00E4painos ', ' [Lis\u00E4painos] ');\n const tmp2 = string.replace(' Lis\u00E4painos ', ' ');\n if (tmp1 !== string && tmp2 !== string) { // Should not happen, just a sanity check\n return [tmp1, tmp2];\n }\n }\n\n if (string.match(/^500 ## \u2021a Lis\u00E4painokset: \\[Lis\u00E4painos\\] /u)) { // MET-569\n const tmp = string.replace(' [Lis\u00E4painos] ', ' ');\n if (tmp !== string) { // Should not happen, just a sanity check\n return [tmp];\n }\n }\n return [];\n }\n\n function getMet831(string) { // MET-381\n // MET-381: remove occurence number TAG-00, if TAG-NN existists\n if (string.match(/^880.* \u20216 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {\n const tmp = string.replace(/( \u20216 [0-9][0-9][0-9])-[0-9]+/u, '$1-00');\n //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`, debugDev);\n //deletableStringsArray.push(tmp);\n if (tmp.match(/ \u20216 [0-9][0-9][0-9]-00\\/[^ ]+ /u)) {\n const tmp2 = tmp.replace(/( \u20216 [0-9][0-9][0-9]-00)[^ ]+/u, '$1');\n //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp2}'`, debugDev);\n return [tmp, tmp2];\n }\n return [tmp];\n }\n return [];\n }\n\n function getMelkehitys3147(string) {\n if (string.match(/^500 ## \u2021a Ei vastaanotettu\\.$/u)) { // MELKEHITYS-3147\n return ['500 ## \u2021a EI VASTAANOTETTU.'];\n }\n if (string.match(/^500 ## \u2021a Ei ilmesty\\.$/u)) { // MELKEHITYS-3147\n return ['500 ## \u2021a EI ILMESTY.'];\n }\n\n if (string.match(/^594 ## \u2021a Ei vastaanotettu \u20215 FENNI$/u)) { // MELKEHITYS-3147\n return ['594 ## \u2021a EI VASTAANOTETTU \u20215 FENNI'];\n }\n if (string.match(/^594 ## \u2021a Ei ilmesty \u20215 FENNI$/u)) { // MELKEHITYS-3147\n return ['594 ## \u2021a EI ILMESTY \u20215 FENNI'];\n }\n return [];\n }\n\n }\n\n function getAiBased(string) { // MELKEHITYS-3277-ish: non-AI is better than AI (a rare case where longer version is inferior):\n return [`${string} \u20217 (dpenmw)AI`];\n }\n \n function getAccentlessVersion(string) { // MET-527\n //nvdebug(`START: '${string}`, debugDev);\n // This is a sanity check: if precomposition does something, there's something wrong, and we don't want to proceed..\n if (string !== precomposeFinnishLetters(string)) {\n return [];\n }\n const accentless = String(fixComposition(string)).replace(/\\p{Diacritic}/gu, '');\n //nvdebug(`FROM '${string}'\\n TO '${accentless}'`, debugDev);\n if (accentless === string) { // Don't self-destruct\n return [];\n }\n return [accentless];\n }\n\n function getPrepublicationTerms(fieldAsString) {\n const subfield7Prepub = `${fieldAsString} \u20217 Ennakkotieto`\n if (fieldAsString.match(/^653./u)) {\n // MET-528 (extented by MET-575)\n return [subfield7Prepub, `${fieldAsString} \u2021g ENNAKKOTIETO`, `${fieldAsString} \u2021g Ennakkotieto`, `${fieldAsString} \u2021g ennakkotieto`, `${fieldAsString} \u2021g ENNAKKOTIETO.`, `${fieldAsString} \u2021g Ennakkotieto.`, `${fieldAsString} \u2021g ennakkotieto.`];\n }\n\n return [subfield7Prepub];\n }\n\n function getInferior341(fieldAsString) { // MET-783\n if (fieldAsString.match(/^341 .. \u2021a textual \u2021[bcdef].* \u20212 sapdv(?:$| \u2021)/u)) {\n return ['341 ## \u2021a textual \u20212 sapdv', '341 1# \u2021a textual \u20212 sapdv', '341 0# \u2021a textual \u20212 sapdv'];\n }\n if (fieldAsString.match(/^341 .. \u2021a auditory \u2021[bcdef].* \u20212 sapdv(?:$| \u2021)/u)) {\n return ['341 ## \u2021a auditory \u20212 sapdv', '341 1# \u2021a auditory \u20212 sapdv', '341 0# \u2021a auditory \u20212 sapdv'];\n }\n return [];\n }\n\n}\n\nfunction fieldToNormalizedString(field) {\n const normalizedField = cloneAndNormalizeFieldForComparison(field);\n return fieldToString(normalizedField);\n}\n\nfunction deriveIndividualNormalizedDeletables(record) { // MET-461:\n const encodingLevel = getEncodingLevel(record);\n const recordIsFinished = encodingLevelIsBetterThanPrepublication(encodingLevel);\n const met495 = encodingLevel === '2' && record.fields.some(f => f.tag === '500' && fieldRefersToKoneellisestiTuotettuTietue(f));\n if (!recordIsFinished || met495) {\n return [];\n }\n const relevantFields = record.fields.filter(f => ['245', '246'].includes(f.tag) && fieldHasSubfield(f, 'a'));\n\n return deriveDeletable946s(relevantFields);\n\n function deriveDeletable946s(fields, results = []) {\n const [currField, ...remainingFields] = fields;\n if (currField === undefined) {\n return results;\n }\n\n const fieldAsNormalizedString = fieldToNormalizedString(currField);\n const tmp = fieldAsNormalizedString.replace(/^(?:...) ../u, '946 ##'). // <= Change tag to 946 and indicators to '##'\n replace(' \u2021a ', ' \u2021i nimeke onixissa \u2021a '). // Add $i before $a. NB! This is added in the normalized lower-cased form!\n replace(/(?: \\/)? \u2021c[^\u2021]+$/u, ''); // Remove $c. (Can $c be non-last?)\n const candArray = [tmp, `${tmp} \u20215 MELINDA`].filter(val => val !== fieldAsNormalizedString);\n if (candArray.length) {\n return deriveDeletable946s(remainingFields, [...results, ...candArray]);\n }\n return deriveDeletable946s(remainingFields, results);\n }\n}\n\nexport function removeIndividualInferiorDatafields(record, fix = true) { // No $6 nor $8 in field\n const deletableFieldsAsStrings = deriveIndividualDeletables(record);\n const deletableFieldsAsNormalizedStrings = deriveIndividualNormalizedDeletables(record);\n\n // nvdebug(`Deletables:\\n ${deletableFieldsAsStrings.join('\\n ')}`, debugDev);\n // nvdebug(`Normalized deletables:\\n ${deletableFieldsAsNormalizedStrings.join('\\n ')}`, debugDev);\n\n const hits = record.fields.filter(field => isDeletableField(field));\n\n const deletedFieldsAsStrings = hits.map(f => fieldToString(f));\n\n if (fix) {\n hits.forEach(field => {\n //nvdebug(`Remove inferior field: ${fieldToString(field)}`, debugDev);\n record.removeField(field);\n });\n }\n\n return deletedFieldsAsStrings;\n\n function isDeletableField(field) {\n const fieldAsString = fieldToString(field);\n if (deletableFieldsAsStrings.includes(fieldAsString)) {\n return true;\n }\n const fieldAsNormalizedString = fieldToNormalizedString(field);\n if (deletableFieldsAsNormalizedStrings.includes(fieldAsNormalizedString)) {\n return true;\n }\n\n return false;\n }\n}\n\n\nexport function removeInferiorDatafields(record, fix = true) {\n const removables = removeIndividualInferiorDatafields(record, fix); // Lone fields\n //const removables8 = removeDuplicateSubfield8Chains(record, fix); // Lone subfield $8 chains\n const removables6 = removeInferiorChains(record, fix); // Lone subfield $6 chains\n // HOW TO HANDLE $6+$8 combos? Skipping is relatively OK.\n\n //nvdebug(`REMOVABLES:\\n ${removables.join('\\n ')}`, debugDev);\n //nvdebug(`REMOVABLES 6:\\n ${removables6.join('\\n ')}`, debugDev);\n\n const removablesAll = removables.concat(removables6); //.concat(removables8);\n\n return removablesAll;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fields", "record", "inferiorTerms", "getInferiorTerms", "newDeletables"]
7
7
  }
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "https://github.com/NatLibFi/marc-record-validators-melinda"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "12.0.8",
17
+ "version": "12.0.9",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -278,28 +278,6 @@ function deriveIndividualDeletables(record) {
278
278
  }
279
279
  }
280
280
 
281
- if (currString.match(/^500 ## ‡a Lisäpainokset: Lisäpainos /u)) { // MET-569
282
- const tmp1 = currString.replace(' Lisäpainos ', ' [Lisäpainos] ');
283
- const tmp2 = currString.replace(' Lisäpainos ', ' ');
284
- if (tmp1 !== currString && tmp2 !== currString) {
285
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp1, tmp2]);
286
- }
287
- }
288
-
289
- if (currString.match(/^500 ## ‡a Lisäpainokset: \[Lisäpainos\] /u)) { // MET-569
290
- const tmp = currString.replace(' [Lisäpainos] ', ' ');
291
- if (tmp !== currString) {
292
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);
293
- }
294
- }
295
-
296
- if (currString.match(/^500 ## ‡a Ei vastaanotettu\.$/u)) { // MELKEHITYS-3147
297
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, '500 ## ‡a EI VASTAANOTETTU.']);
298
- }
299
- if (currString.match(/^500 ## ‡a Ei ilmesty\.$/u)) { // MELKEHITYS-3147
300
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, '500 ## ‡a EI ILMESTY.']);
301
- }
302
-
303
281
  if (currString.match(/^505 .0.*-- ‡t/u)) { // MRA-413-ish
304
282
  const tmp = currString.replace(/ -- ‡t /gu, ' -- '). // remove non-initial $t subfields
305
283
  replace(/ ‡[rg] /gu, ' '). // remove $r and $g subfields
@@ -313,41 +291,80 @@ function deriveIndividualDeletables(record) {
313
291
  //nvdebug(`505 DERIVATE: '${tmp}'`, debugDev)
314
292
  }
315
293
 
316
- if (currString.match(/^594 ## ‡a Ei vastaanotettu ‡5 FENNI$/u)) { // MELKEHITYS-3147
317
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, '594 ## ‡a EI VASTAANOTETTU ‡5 FENNI']);
318
- }
319
- if (currString.match(/^594 ## ‡a Ei ilmesty ‡5 FENNI$/u)) { // MELKEHITYS-3147
320
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, '594 ## ‡a EI ILMESTY ‡5 FENNI']);
321
- }
294
+ const inferiorFunctions = [ getPrepublicationTerms, getInferior341, getAiBased, getMelkehitys3147, getMet831, getMet569 ];
295
+
296
+ const inferiorTerms = getInferiorTerms(inferiorFunctions); //getPrepublicationTerms(currString);
297
+
298
+ const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms];
322
299
 
323
- // MET-381: remove occurence number TAG-00, if TAG-NN existists
324
- if (currString.match(/^880.* ‡6 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {
325
- const tmp = currString.replace(/( ‡6 [0-9][0-9][0-9])-[0-9]+/u, '$1-00');
326
- //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`, debugDev);
327
- //deletableStringsArray.push(tmp);
328
- if (tmp.match(/ ‡6 [0-9][0-9][0-9]-00\/[^ ]+ /u)) {
329
- const tmp2 = tmp.replace(/( ‡6 [0-9][0-9][0-9]-00)[^ ]+/u, '$1');
330
- //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp2}'`, debugDev);
331
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp, tmp2]);
300
+ return processTodoList([...stillToDo, ...moreToDo], newDeletables);
301
+
302
+ function getInferiorTerms(functions, results = []) {
303
+ const [currFunction, ...remainingFunctions] = functions;
304
+ if (!currFunction) {
305
+ return results
332
306
  }
333
- return processTodoList([...stillToDo, ...moreToDo], [...deletables, tmp]);
307
+ const newDeletables = currFunction(currString);
308
+ return getInferiorTerms(remainingFunctions, [...results, ...newDeletables]);
334
309
  }
335
310
 
336
- // MET-575 (merge: applies in postprocessing)
337
- const inferiorTerms = getPrepublicationTerms(currString);
311
+ function getMet569(string) {
312
+ if (string.match(/^500 ## ‡a Lisäpainokset: Lisäpainos /u)) { // MET-569
313
+ const tmp1 = string.replace(' Lisäpainos ', ' [Lisäpainos] ');
314
+ const tmp2 = string.replace(' Lisäpainos ', ' ');
315
+ if (tmp1 !== string && tmp2 !== string) { // Should not happen, just a sanity check
316
+ return [tmp1, tmp2];
317
+ }
318
+ }
319
+
320
+ if (string.match(/^500 ## ‡a Lisäpainokset: \[Lisäpainos\] /u)) { // MET-569
321
+ const tmp = string.replace(' [Lisäpainos] ', ' ');
322
+ if (tmp !== string) { // Should not happen, just a sanity check
323
+ return [tmp];
324
+ }
325
+ }
326
+ return [];
327
+ }
338
328
 
339
- // MELKEHITYS-3277-ish: non-AI is better than AI (a rare case where longer version is inferior):
340
- const aiBased = `${currString} ‡7 (dpenmw)AI`;
329
+ function getMet831(string) { // MET-381
330
+ // MET-381: remove occurence number TAG-00, if TAG-NN existists
331
+ if (string.match(/^880.* ‡6 [0-9][0-9][0-9]-(?:[1-9][0-9]|0[1-9])/u)) {
332
+ const tmp = string.replace(/( ‡6 [0-9][0-9][0-9])-[0-9]+/u, '$1-00');
333
+ //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp}'`, debugDev);
334
+ //deletableStringsArray.push(tmp);
335
+ if (tmp.match(/ ‡6 [0-9][0-9][0-9]-00\/[^ ]+ /u)) {
336
+ const tmp2 = tmp.replace(/( ‡6 [0-9][0-9][0-9]-00)[^ ]+/u, '$1');
337
+ //nvdebug(`MET-381: ADD TO DELETABLES: '${tmp2}'`, debugDev);
338
+ return [tmp, tmp2];
339
+ }
340
+ return [tmp];
341
+ }
342
+ return [];
343
+ }
341
344
 
342
- const newDeletables = [...deletables, ...subsets, ...accentless, ...d490, ...inferiorTerms, aiBased];
345
+ function getMelkehitys3147(string) {
346
+ if (string.match(/^500 ## ‡a Ei vastaanotettu\.$/u)) { // MELKEHITYS-3147
347
+ return ['500 ## ‡a EI VASTAANOTETTU.'];
348
+ }
349
+ if (string.match(/^500 ## ‡a Ei ilmesty\.$/u)) { // MELKEHITYS-3147
350
+ return ['500 ## ‡a EI ILMESTY.'];
351
+ }
343
352
 
344
- if (subsets.length) {
345
- return processTodoList([...stillToDo, ...moreToDo], newDeletables);
353
+ if (string.match(/^594 ## ‡a Ei vastaanotettu ‡5 FENNI$/u)) { // MELKEHITYS-3147
354
+ return ['594 ## ‡a EI VASTAANOTETTU ‡5 FENNI'];
355
+ }
356
+ if (string.match(/^594 ## ‡a Ei ilmesty ‡5 FENNI$/u)) { // MELKEHITYS-3147
357
+ return ['594 ## ‡a EI ILMESTY ‡5 FENNI'];
358
+ }
359
+ return [];
346
360
  }
347
361
 
348
- return processTodoList([...stillToDo, ...moreToDo], newDeletables);
349
362
  }
350
363
 
364
+ function getAiBased(string) { // MELKEHITYS-3277-ish: non-AI is better than AI (a rare case where longer version is inferior):
365
+ return [`${string} ‡7 (dpenmw)AI`];
366
+ }
367
+
351
368
  function getAccentlessVersion(string) { // MET-527
352
369
  //nvdebug(`START: '${string}`, debugDev);
353
370
  // This is a sanity check: if precomposition does something, there's something wrong, and we don't want to proceed..
@@ -372,6 +389,16 @@ function deriveIndividualDeletables(record) {
372
389
  return [subfield7Prepub];
373
390
  }
374
391
 
392
+ function getInferior341(fieldAsString) { // MET-783
393
+ if (fieldAsString.match(/^341 .. ‡a textual ‡[bcdef].* ‡2 sapdv(?:$| ‡)/u)) {
394
+ return ['341 ## ‡a textual ‡2 sapdv', '341 1# ‡a textual ‡2 sapdv', '341 0# ‡a textual ‡2 sapdv'];
395
+ }
396
+ if (fieldAsString.match(/^341 .. ‡a auditory ‡[bcdef].* ‡2 sapdv(?:$| ‡)/u)) {
397
+ return ['341 ## ‡a auditory ‡2 sapdv', '341 1# ‡a auditory ‡2 sapdv', '341 0# ‡a auditory ‡2 sapdv'];
398
+ }
399
+ return [];
400
+ }
401
+
375
402
  }
376
403
 
377
404
  function fieldToNormalizedString(field) {
@@ -0,0 +1,13 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "001", "value": "f18" },
5
+ { "tag": "341", "ind1": "0", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "textual"},
7
+ { "code": "b", "value": "structuralNavigation"},
8
+ { "code": "b", "value": "readingOrder"},
9
+ { "code": "2", "value": "sapdv"}
10
+ ]}
11
+ ],
12
+ "leader": "01331cam a22003498i 4500"
13
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "f18: MET-783 default example",
3
+ "fix": true,
4
+ "only": false
5
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "001", "value": "f18" },
5
+ { "tag": "341", "ind1": " ", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "textual"},
7
+ { "code": "2", "value": "sapdv"}
8
+ ]},
9
+ { "tag": "341", "ind1": "0", "ind2": " ", "subfields": [
10
+ { "code": "a", "value": "textual"},
11
+ { "code": "b", "value": "structuralNavigation"},
12
+ { "code": "b", "value": "readingOrder"},
13
+ { "code": "2", "value": "sapdv"}
14
+ ]}
15
+ ],
16
+ "leader": "01331cam a22003498i 4500"
17
+
18
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "001", "value": "f19" },
5
+ { "tag": "341", "ind1": " ", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "auditory"},
7
+ { "code": "2", "value": "sapdv"}
8
+ ]},
9
+ { "tag": "341", "ind1": "0", "ind2": " ", "subfields": [
10
+ { "code": "a", "value": "textual"},
11
+ { "code": "b", "value": "structuralNavigation"},
12
+ { "code": "b", "value": "readingOrder"},
13
+ { "code": "2", "value": "sapdv"}
14
+ ]}
15
+ ],
16
+ "leader": "01331cam a22003498i 4500"
17
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "f19: MET-783 don't delete non-matching $a",
3
+ "fix": true,
4
+ "only": false
5
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ { "tag": "001", "value": "f19" },
5
+ { "tag": "341", "ind1": " ", "ind2": " ", "subfields": [
6
+ { "code": "a", "value": "auditory"},
7
+ { "code": "2", "value": "sapdv"}
8
+ ]},
9
+ { "tag": "341", "ind1": "0", "ind2": " ", "subfields": [
10
+ { "code": "a", "value": "textual"},
11
+ { "code": "b", "value": "structuralNavigation"},
12
+ { "code": "b", "value": "readingOrder"},
13
+ { "code": "2", "value": "sapdv"}
14
+ ]}
15
+ ],
16
+ "leader": "01331cam a22003498i 4500"
17
+
18
+ }