@natlibfi/marc-record-validators-melinda 12.0.0-alpha.1 → 12.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.github/workflows/{melinda-node-tests.yml → melinda-node-tests-and-publish.yml} +36 -11
  2. package/dist/access-rights.test.js +1 -1
  3. package/dist/access-rights.test.js.map +1 -1
  4. package/dist/addMissingField337.test.js +1 -1
  5. package/dist/addMissingField337.test.js.map +1 -1
  6. package/dist/addMissingField338.test.js +1 -1
  7. package/dist/addMissingField338.test.js.map +1 -1
  8. package/dist/cyrillux-usemarcon-replacement.test.js +4 -7
  9. package/dist/cyrillux-usemarcon-replacement.test.js.map +2 -2
  10. package/dist/cyrillux.test.js +1 -1
  11. package/dist/cyrillux.test.js.map +1 -1
  12. package/dist/double-commas.test.js +1 -1
  13. package/dist/double-commas.test.js.map +1 -1
  14. package/dist/empty-fields.test.js +1 -1
  15. package/dist/empty-fields.test.js.map +1 -1
  16. package/dist/ending-punctuation-conf.js +6 -4
  17. package/dist/ending-punctuation-conf.js.map +2 -2
  18. package/dist/ending-punctuation.js +88 -18
  19. package/dist/ending-punctuation.js.map +3 -3
  20. package/dist/ending-punctuation.test.js +198 -103
  21. package/dist/ending-punctuation.test.js.map +2 -2
  22. package/dist/field-008-18-34-character-groups.test.js +1 -1
  23. package/dist/field-008-18-34-character-groups.test.js.map +1 -1
  24. package/dist/field-structure.test.js +1 -1
  25. package/dist/field-structure.test.js.map +1 -1
  26. package/dist/index.js +122 -59
  27. package/dist/index.js.map +2 -2
  28. package/dist/indicator-fixes.js +11 -1
  29. package/dist/indicator-fixes.js.map +2 -2
  30. package/dist/isbn-issn.js +8 -5
  31. package/dist/isbn-issn.js.map +2 -2
  32. package/dist/melindaCustomMergeFields.js +1 -1
  33. package/dist/melindaCustomMergeFields.js.map +2 -2
  34. package/dist/merge-fields/counterpartField.js +5 -0
  35. package/dist/merge-fields/counterpartField.js.map +2 -2
  36. package/dist/merge-fields/dataProvenance.js +29 -0
  37. package/dist/merge-fields/dataProvenance.js.map +7 -0
  38. package/dist/merge-fields/index.js +11 -2
  39. package/dist/merge-fields/index.js.map +2 -2
  40. package/dist/merge-fields/mergeField.js +1 -1
  41. package/dist/merge-fields/mergeField.js.map +2 -2
  42. package/dist/merge-fields.test.js +4 -2
  43. package/dist/merge-fields.test.js.map +2 -2
  44. package/dist/mergeField500Lisapainokset.js +1 -1
  45. package/dist/mergeField500Lisapainokset.js.map +2 -2
  46. package/dist/normalizeFieldForComparison.js +24 -0
  47. package/dist/normalizeFieldForComparison.js.map +2 -2
  48. package/dist/punctuation2.js +11 -5
  49. package/dist/punctuation2.js.map +2 -2
  50. package/dist/removeInferiorDataFields.js +2 -1
  51. package/dist/removeInferiorDataFields.js.map +2 -2
  52. package/dist/resolveOrphanedSubfield6s.js +1 -1
  53. package/dist/resolveOrphanedSubfield6s.js.map +2 -2
  54. package/dist/sortSubfields.js +5 -5
  55. package/dist/sortSubfields.js.map +2 -2
  56. package/dist/translate-terms.test.js +12 -2
  57. package/dist/translate-terms.test.js.map +2 -2
  58. package/dist/utils.js +9 -3
  59. package/dist/utils.js.map +2 -2
  60. package/package.json +22 -23
  61. package/src/access-rights.test.js +1 -1
  62. package/src/addMissingField337.test.js +1 -1
  63. package/src/addMissingField338.test.js +1 -1
  64. package/src/cyrillux-usemarcon-replacement.test.js +4 -9
  65. package/src/cyrillux.test.js +1 -1
  66. package/src/double-commas.test.js +1 -1
  67. package/src/empty-fields.test.js +1 -1
  68. package/src/ending-punctuation-conf.js +6 -5
  69. package/src/ending-punctuation.js +115 -24
  70. package/src/ending-punctuation.test.js +187 -104
  71. package/src/field-008-18-34-character-groups.test.js +1 -1
  72. package/src/field-structure.test.js +1 -1
  73. package/src/index.js +132 -59
  74. package/src/indicator-fixes.js +14 -1
  75. package/src/isbn-issn.js +11 -6
  76. package/src/melindaCustomMergeFields.js +1 -1
  77. package/src/merge-fields/counterpartField.js +6 -0
  78. package/src/merge-fields/dataProvenance.js +41 -0
  79. package/src/merge-fields/index.js +11 -2
  80. package/src/merge-fields/mergeField.js +2 -2
  81. package/src/merge-fields.test.js +6 -2
  82. package/src/mergeField500Lisapainokset.js +1 -1
  83. package/src/normalizeFieldForComparison.js +26 -0
  84. package/src/punctuation2.js +14 -5
  85. package/src/removeInferiorDataFields.js +4 -1
  86. package/src/resolveOrphanedSubfield6s.js +1 -1
  87. package/src/sortSubfields.js +7 -5
  88. package/src/translate-terms.test.js +25 -2
  89. package/src/utils.js +19 -3
  90. package/test-fixtures/indicator-fixes/10/expectedResult.json +11 -0
  91. package/test-fixtures/indicator-fixes/10/metadata.json +4 -0
  92. package/test-fixtures/indicator-fixes/10/record.json +11 -0
  93. package/test-fixtures/merge-fields/f05/expectedResult.json +24 -0
  94. package/test-fixtures/merge-fields/f05/metadata.json +6 -0
  95. package/test-fixtures/merge-fields/f05/record.json +30 -0
  96. package/test-fixtures/remove-inferior-datafields/f16/expectedResult.json +12 -0
  97. package/test-fixtures/remove-inferior-datafields/f16/metadata.json +5 -0
  98. package/test-fixtures/remove-inferior-datafields/f16/record.json +14 -0
  99. package/test-fixtures/translate-terms-data.js +42 -0
  100. package/src/melindaCustomMergeFields.json +0 -5120
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert";
2
2
  import { MarcRecord } from "@natlibfi/marc-record";
3
- import validatorFactory from "../src/field-008-18-34-character-groups.js";
3
+ import validatorFactory from "./field-008-18-34-character-groups.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
6
  import createDebugLogger from "debug";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/field-008-18-34-character-groups.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from '../src/field-008-18-34-character-groups.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'field-008-18-34-character-groups'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-008-18-34-character-groups:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.fix, 'function');\n assert.equal(typeof validator.validate, '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 assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './field-008-18-34-character-groups.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'field-008-18-34-character-groups'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-008-18-34-character-groups:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.fix, 'function');\n assert.equal(typeof validator.validate, '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 assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
5
  "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAE9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,kCAAkC;AAAA,EACrF,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,gFAAgF;AAEhH,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,KAAK,UAAU;AAC7C,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAK,GAAG;AACjE,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert";
2
2
  import { describe, it } from "node:test";
3
3
  import { MarcRecord } from "@natlibfi/marc-record";
4
- import validatorFactory from "../src/field-structure.js";
4
+ import validatorFactory from "./field-structure.js";
5
5
  describe("field-structure", () => {
6
6
  it("Creates a validator", async () => {
7
7
  const config = [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/field-structure.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {describe, it} from 'node:test';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from '../src/field-structure.js';\n\n\n// Factory validation\ndescribe('field-structure', () => {\n it('Creates a validator', async () => {\n const config = [\n {\n tag: /^035$/u,\n ind1: /^0$/u,\n ind2: /^1$/u\n }, {\n tag: /^100$/u,\n subfields: {\n a: {maxOccurrence: 1}\n }\n }\n ];\n\n const validator = await validatorFactory(config);\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n describe('#configuration', () => {\n it('Throws an error when config array not provided', () => {\n try {\n validatorFactory();\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration array not provided');\n }\n });\n\n it('Throws an error when config array has unidentified field', () => {\n const config = [\n {\n leader: /^035$/u,\n tags: /^035$/u\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - unidentified value: tags');\n }\n });\n\n it('Throws an error when config array has field with incorrect data type', () => {\n const config = [\n {\n leader: /^035$/u,\n tag: 35\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - invalid data type for: tag');\n }\n });\n\n it('Throws an error when config array has excluded element', () => {\n const config = [\n {\n leader: /^035$/u,\n tag: /^035$/u\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - excluded element');\n }\n });\n\n it('Throws an error when config subfields not object', () => {\n const config = [\n {\n tag: /^001$/u,\n valuePattern: /\\d+/u\n }, {\n tag: /^245$/u,\n strict: true,\n subfields: 'This should be Object'\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - subfields not object');\n }\n });\n });\n\n it('Should find the record valid because no fields match the config', async () => {\n const config = [\n {\n tag: /^FOO$/u,\n valuePattern: /bar/u\n }\n ];\n\n const record = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }\n ]\n });\n\n const validator = await validatorFactory(config);\n const result = await validator.validate(record);\n\n assert.deepEqual(result, {valid: true});\n });\n\n // Indicators and subfields validation\n describe('#validate: Indicators and subfields', () => {\n const config = [\n {\n tag: /^035$/u,\n ind1: /^0$/u,\n ind2: /^1$/u\n }, {\n tag: /^100$/u,\n subfields: {\n a: {maxOccurrence: 1}\n }\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '035',\n ind1: '0',\n ind2: '1',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }, {\n code: 'b',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMany = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '035',\n ind1: '1',\n ind2: '1',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }, {\n code: 'b',\n value: 'fubar'\n }, {\n code: 'a',\n value: 'barfoo'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid: Too many subfields', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMany);\n\n assert.deepEqual(result, {valid: false});\n });\n });\n\n // Patterns and mandatory & strict subfields\n describe('#validate: Patterns and mandatory & strict subfields', () => {\n const config = [\n {\n tag: /^001$/u,\n valuePattern: /\\d+/u\n }, {\n tag: /^245$/u,\n strict: true,\n subfields: {\n a: {required: true, maxOccurrence: 1, pattern: /\\w+/u},\n b: {maxOccurrence: 1, pattern: /\\w+/u}\n }\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidExtra = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }, {\n code: 'c',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidTooMany = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }, {\n code: 'a',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidRegExp = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: '\u00E4\u00E4'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMissing = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: '\u00E4\u00E4'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMissingSubfield = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid: Extra field in strict', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidExtra);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Too many occurances', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidTooMany);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Invalid RegExp', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidRegExp);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Missing field', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMissing);\n\n assert.deepEqual(result, {valid: false});\n });\n it('Finds the record invalid: Missing subfield', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMissingSubfield);\n\n assert.deepEqual(result, {valid: false});\n });\n });\n\n // Dependencies\n describe('#validate: Dependencies', () => {\n const config = [\n {\n leader: /^.{6}s/u,\n dependencies: [\n {\n tag: /^773$/u,\n subfields: {7: /^nnas$/u}\n }\n ]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '63ab75sfoo122myhgh',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '773',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: '7',\n value: 'nnas'\n }, {\n code: 'w',\n value: '789101112'\n }\n ]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: '63ab75afoo122myhgh',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '773',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: '7',\n value: 'nnas'\n }, {\n code: 'w',\n value: '789101112'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Find the record valid (Dependency on leader)', async () => {\n const validator = await validatorFactory([{tag: /^007$/u, dependencies: [{leader: /^.{6}[at]/u}]}]);\n const result = await validator.validate(new MarcRecord({\n leader: '00000ccm^a22003372i^4500',\n fields: [\n {tag: '001', value: '123456'},\n {tag: '245', value: 'foobar'}\n ]\n }));\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Find the record invalid (Dependency on leader)', async () => {\n const validator = await validatorFactory([{tag: /^007$/u, dependencies: [{leader: /^.{6}[at]/u}]}]);\n const result = await validator.validate(new MarcRecord({\n leader: '00000cam^a22003372i^4500',\n fields: [\n {tag: '001', value: '123456'},\n {tag: '245', value: 'foobar'}\n ]\n }));\n\n assert.deepEqual(result, {valid: false});\n });\n });\n});\n"],
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {describe, it} from 'node:test';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './field-structure.js';\n\n\n// Factory validation\ndescribe('field-structure', () => {\n it('Creates a validator', async () => {\n const config = [\n {\n tag: /^035$/u,\n ind1: /^0$/u,\n ind2: /^1$/u\n }, {\n tag: /^100$/u,\n subfields: {\n a: {maxOccurrence: 1}\n }\n }\n ];\n\n const validator = await validatorFactory(config);\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n describe('#configuration', () => {\n it('Throws an error when config array not provided', () => {\n try {\n validatorFactory();\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration array not provided');\n }\n });\n\n it('Throws an error when config array has unidentified field', () => {\n const config = [\n {\n leader: /^035$/u,\n tags: /^035$/u\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - unidentified value: tags');\n }\n });\n\n it('Throws an error when config array has field with incorrect data type', () => {\n const config = [\n {\n leader: /^035$/u,\n tag: 35\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - invalid data type for: tag');\n }\n });\n\n it('Throws an error when config array has excluded element', () => {\n const config = [\n {\n leader: /^035$/u,\n tag: /^035$/u\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - excluded element');\n }\n });\n\n it('Throws an error when config subfields not object', () => {\n const config = [\n {\n tag: /^001$/u,\n valuePattern: /\\d+/u\n }, {\n tag: /^245$/u,\n strict: true,\n subfields: 'This should be Object'\n }\n ];\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration not valid - subfields not object');\n }\n });\n });\n\n it('Should find the record valid because no fields match the config', async () => {\n const config = [\n {\n tag: /^FOO$/u,\n valuePattern: /bar/u\n }\n ];\n\n const record = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }\n ]\n });\n\n const validator = await validatorFactory(config);\n const result = await validator.validate(record);\n\n assert.deepEqual(result, {valid: true});\n });\n\n // Indicators and subfields validation\n describe('#validate: Indicators and subfields', () => {\n const config = [\n {\n tag: /^035$/u,\n ind1: /^0$/u,\n ind2: /^1$/u\n }, {\n tag: /^100$/u,\n subfields: {\n a: {maxOccurrence: 1}\n }\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '035',\n ind1: '0',\n ind2: '1',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }, {\n code: 'b',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMany = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '035',\n ind1: '1',\n ind2: '1',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }, {\n code: 'b',\n value: 'fubar'\n }, {\n code: 'a',\n value: 'barfoo'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid: Too many subfields', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMany);\n\n assert.deepEqual(result, {valid: false});\n });\n });\n\n // Patterns and mandatory & strict subfields\n describe('#validate: Patterns and mandatory & strict subfields', () => {\n const config = [\n {\n tag: /^001$/u,\n valuePattern: /\\d+/u\n }, {\n tag: /^245$/u,\n strict: true,\n subfields: {\n a: {required: true, maxOccurrence: 1, pattern: /\\w+/u},\n b: {maxOccurrence: 1, pattern: /\\w+/u}\n }\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidExtra = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }, {\n code: 'c',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidTooMany = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }, {\n code: 'b',\n value: 'bar'\n }, {\n code: 'a',\n value: 'fubar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidRegExp = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456a'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: '\u00E4\u00E4'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMissing = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: '\u00E4\u00E4'\n }, {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n const recordInvalidMissingSubfield = new MarcRecord({\n leader: '',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'bar'\n }\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'b',\n value: 'bar'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid: Extra field in strict', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidExtra);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Too many occurances', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidTooMany);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Invalid RegExp', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidRegExp);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Finds the record invalid: Missing field', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMissing);\n\n assert.deepEqual(result, {valid: false});\n });\n it('Finds the record invalid: Missing subfield', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalidMissingSubfield);\n\n assert.deepEqual(result, {valid: false});\n });\n });\n\n // Dependencies\n describe('#validate: Dependencies', () => {\n const config = [\n {\n leader: /^.{6}s/u,\n dependencies: [\n {\n tag: /^773$/u,\n subfields: {7: /^nnas$/u}\n }\n ]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: '63ab75sfoo122myhgh',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '773',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: '7',\n value: 'nnas'\n }, {\n code: 'w',\n value: '789101112'\n }\n ]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: '63ab75afoo122myhgh',\n fields: [\n {\n tag: '001',\n value: '123456'\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: 'a',\n value: 'foo'\n }\n ]\n }, {\n tag: '773',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {\n code: '7',\n value: 'nnas'\n }, {\n code: 'w',\n value: '789101112'\n }\n ]\n }\n ]\n });\n\n it('Finds the record valid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Finds the record invalid', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n\n assert.deepEqual(result, {valid: false});\n });\n\n it('Find the record valid (Dependency on leader)', async () => {\n const validator = await validatorFactory([{tag: /^007$/u, dependencies: [{leader: /^.{6}[at]/u}]}]);\n const result = await validator.validate(new MarcRecord({\n leader: '00000ccm^a22003372i^4500',\n fields: [\n {tag: '001', value: '123456'},\n {tag: '245', value: 'foobar'}\n ]\n }));\n\n assert.deepEqual(result, {valid: true});\n });\n\n it('Find the record invalid (Dependency on leader)', async () => {\n const validator = await validatorFactory([{tag: /^007$/u, dependencies: [{leader: /^.{6}[at]/u}]}]);\n const result = await validator.validate(new MarcRecord({\n leader: '00000cam^a22003372i^4500',\n fields: [\n {tag: '001', value: '123456'},\n {tag: '245', value: 'foobar'}\n ]\n }));\n\n assert.deepEqual(result, {valid: false});\n });\n });\n});\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.js CHANGED
@@ -1,61 +1,89 @@
1
- import AccessRights from "./access-rights";
2
- import AddMissingField041 from "./addMissingField041";
3
- import AddMissingField336 from "./addMissingField336";
4
- import AddMissingField337 from "./addMissingField337";
5
- import AddMissingField338 from "./addMissingField338";
6
- import Cyrillux from "./cyrillux";
7
- import CyrilluxUsemarconReplacement from "./cyrillux-usemarcon-replacement";
8
- import DisambiguateSeriesStatements from "./disambiguateSeriesStatements";
9
- import DoubleCommas from "./double-commas";
10
- import DuplicatesInd1 from "./duplicates-ind1";
11
- import EmptyFields from "./empty-fields";
12
- import EndingPunctuation from "./ending-punctuation";
13
- import EndingWhitespace from "./ending-whitespace";
14
- import Field008CharacterGroups from "./field-008-18-34-character-groups";
15
- import Field505Separators from "./field-505-separators";
16
- import Field521Fix from "./field-521-fix";
17
- import FieldExclusion from "./field-exclusion";
18
- import FieldStructure from "./field-structure";
19
- import FieldsPresent from "./fields-present";
20
- import Fix33X from "./fix-33X";
21
- import FixCountryCodes from "./fix-country-codes";
22
- import FixLanguageCodes from "./fix-language-codes";
23
- import FixRelatorTerms from "./fixRelatorTerms";
24
- import FixedFields from "./fixed-fields";
25
- import IdenticalFields from "./identical-fields";
26
- import IndicatorFixes from "./indicator-fixes";
27
- import IsbnIssn from "./isbn-issn";
28
- import ItemLanguage from "./item-language";
29
- import MergeField500Lisapainokset from "./mergeField500Lisapainokset";
30
- import MergeFields from "./merge-fields/";
31
- import MergeRelatorTermFields from "./mergeRelatorTermFields";
32
- import Modernize502 from "./modernize-502";
33
- import MultipleSubfield0s from "./multiple-subfield-0";
34
- import NonBreakingSpace from "./non-breaking-space";
35
- import NormalizeDashes from "./normalize-dashes";
36
- import NormalizeIdentifiers from "./normalize-identifiers";
37
- import NormalizeQualifyingInformation from "./normalize-qualifying-information";
38
- import NormalizeUTF8Diacritics from "./normalize-utf8-diacritics";
39
- import Punctuation from "./punctuation/";
40
- import Punctuation2 from "./punctuation2";
41
- import ReindexSubfield6OccurenceNumbers from "./reindexSubfield6OccurenceNumbers";
42
- import RemoveDuplicateDataFields from "./removeDuplicateDataFields";
43
- import RemoveInferiorDataFields from "./removeInferiorDataFields";
44
- import ResolvableExtReferences from "./resolvable-ext-references-melinda";
45
- import ResolveOrphanedSubfield6s from "./resolveOrphanedSubfield6s";
46
- import SanitizeVocabularySourceCodes from "./sanitize-vocabulary-source-codes";
47
- import SortFields from "./sortFields";
48
- import SortRelatorTerms from "./sortRelatorTerms";
49
- import SortSubfields from "./sortSubfields";
50
- import SortTags from "./sort-tags";
51
- import SubfieldValueNormalizations from "./subfieldValueNormalizations";
52
- import SubfieldExclusion from "./subfield-exclusion";
53
- import Sync007And300 from "./sync-007-and-300";
54
- import TranslateTerms from "./translate-terms";
55
- import TypeOfDateF008 from "./typeOfDate-008";
56
- import UnicodeDecomposition from "./unicode-decomposition";
57
- import UpdateField540 from "./update-field-540";
58
- import Urn from "./urn";
1
+ import AccessRights from "./access-rights.js";
2
+ import AddMissingField041 from "./addMissingField041.js";
3
+ import AddMissingField336 from "./addMissingField336.js";
4
+ import AddMissingField337 from "./addMissingField337.js";
5
+ import AddMissingField338 from "./addMissingField338.js";
6
+ import Cyrillux from "./cyrillux.js";
7
+ import CyrilluxUsemarconReplacement from "./cyrillux-usemarcon-replacement.js";
8
+ import DisambiguateSeriesStatements from "./disambiguateSeriesStatements.js";
9
+ import DoubleCommas from "./double-commas.js";
10
+ import DuplicatesInd1 from "./duplicates-ind1.js";
11
+ import EmptyFields from "./empty-fields.js";
12
+ import EndingPunctuation from "./ending-punctuation.js";
13
+ import EndingWhitespace from "./ending-whitespace.js";
14
+ import Field008CharacterGroups from "./field-008-18-34-character-groups.js";
15
+ import Field505Separators from "./field-505-separators.js";
16
+ import Field521Fix from "./field-521-fix.js";
17
+ import FieldExclusion from "./field-exclusion.js";
18
+ import FieldStructure from "./field-structure.js";
19
+ import FieldsPresent from "./fields-present.js";
20
+ import Fix33X from "./fix-33X.js";
21
+ import FixCountryCodes from "./fix-country-codes.js";
22
+ import FixLanguageCodes from "./fix-language-codes.js";
23
+ import FixRelatorTerms from "./fixRelatorTerms.js";
24
+ import FixedFields from "./fixed-fields.js";
25
+ import IdenticalFields from "./identical-fields.js";
26
+ import IndicatorFixes from "./indicator-fixes.js";
27
+ import IsbnIssn from "./isbn-issn.js";
28
+ import ItemLanguage from "./item-language.js";
29
+ import MergeField500Lisapainokset from "./mergeField500Lisapainokset.js";
30
+ import MergeFields from "./merge-fields/index.js";
31
+ import MergeRelatorTermFields from "./mergeRelatorTermFields.js";
32
+ import Modernize502 from "./modernize-502.js";
33
+ import MultipleSubfield0s from "./multiple-subfield-0.js";
34
+ import NonBreakingSpace from "./non-breaking-space.js";
35
+ import NormalizeDashes from "./normalize-dashes.js";
36
+ import NormalizeIdentifiers from "./normalize-identifiers.js";
37
+ import NormalizeQualifyingInformation from "./normalize-qualifying-information.js";
38
+ import NormalizeUTF8Diacritics from "./normalize-utf8-diacritics.js";
39
+ import Punctuation from "./punctuation/index.js";
40
+ import Punctuation2 from "./punctuation2.js";
41
+ import ReindexSubfield6OccurenceNumbers from "./reindexSubfield6OccurenceNumbers.js";
42
+ import RemoveDuplicateDataFields from "./removeDuplicateDataFields.js";
43
+ import RemoveInferiorDataFields from "./removeInferiorDataFields.js";
44
+ import ResolvableExtReferences from "./resolvable-ext-references-melinda.js";
45
+ import ResolveOrphanedSubfield6s from "./resolveOrphanedSubfield6s.js";
46
+ import SanitizeVocabularySourceCodes from "./sanitize-vocabulary-source-codes.js";
47
+ import SortFields from "./sortFields.js";
48
+ import SortRelatorTerms from "./sortRelatorTerms.js";
49
+ import SortSubfields from "./sortSubfields.js";
50
+ import SortTags from "./sort-tags.js";
51
+ import SubfieldValueNormalizations from "./subfieldValueNormalizations.js";
52
+ import SubfieldExclusion from "./subfield-exclusion.js";
53
+ import Sync007And300 from "./sync-007-and-300.js";
54
+ import TranslateTerms from "./translate-terms.js";
55
+ import TypeOfDateF008 from "./typeOfDate-008.js";
56
+ import UnicodeDecomposition from "./unicode-decomposition.js";
57
+ import UpdateField540 from "./update-field-540.js";
58
+ import Urn from "./urn.js";
59
+ import { getCounterpart } from "./merge-fields/counterpartField.js";
60
+ import { postprocessRecords } from "./merge-fields/mergeOrAddPostprocess.js";
61
+ import { mergeField } from "./merge-fields/mergeField.js";
62
+ import {
63
+ fieldGetOccurrenceNumberPairs,
64
+ fieldGetUnambiguousOccurrenceNumber,
65
+ fieldToNormalizedString,
66
+ fieldsToNormalizedString,
67
+ get6s,
68
+ isValidSubfield6,
69
+ recordGetMaxSubfield6OccurrenceNumberAsInteger,
70
+ intToOccurrenceNumberString,
71
+ resetSubfield6Tag,
72
+ subfield6ResetOccurrenceNumber,
73
+ subfield6GetOccurrenceNumber,
74
+ subfield6GetOccurrenceNumberAsInteger
75
+ } from "./subfield6Utils.js";
76
+ import { getSubfield8LinkingNumber, isValidSubfield8, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber } from "./subfield8Utils.js";
77
+ import { recordFixRelatorTerms } from "./fixRelatorTerms.js";
78
+ import { fieldTrimSubfieldValues } from "./normalizeFieldForComparison.js";
79
+ import { baseHasEqualOrHigherEncodingLevel, deleteAllPrepublicationNotesFromField500InNonPubRecord, encodingLevelIsBetterThanPrepublication, getEncodingLevel, isEnnakkotietoField, isEnnakkotietoSubfield } from "./prepublicationUtils.js";
80
+ import { melindaFieldSpecs } from "@natlibfi/marc-record-validators-melinda/dist/melindaCustomMergeFields.js";
81
+ import { cloneAndRemovePunctuation } from "./normalizeFieldForComparison.js";
82
+ import { removeWorsePrepubField500s, removeWorsePrepubField594s } from "./prepublicationUtils.js";
83
+ import { fieldFixPunctuation } from "./punctuation2.js";
84
+ import { recordResetSubfield6OccurrenceNumbers } from "./reindexSubfield6OccurenceNumbers.js";
85
+ import { sortAdjacentSubfields } from "./sortSubfields.js";
86
+ import { fieldsToString } from "./utils.js";
59
87
  export {
60
88
  AccessRights,
61
89
  AddMissingField041,
@@ -114,6 +142,41 @@ export {
114
142
  UpdateField540,
115
143
  Urn,
116
144
  SortFields,
117
- MergeFields
145
+ MergeFields,
146
+ getEncodingLevel,
147
+ cloneAndRemovePunctuation,
148
+ fieldFixPunctuation,
149
+ fieldToNormalizedString,
150
+ fieldTrimSubfieldValues,
151
+ fieldsToNormalizedString,
152
+ fieldsToString,
153
+ recordFixRelatorTerms,
154
+ sortAdjacentSubfields,
155
+ baseHasEqualOrHigherEncodingLevel,
156
+ deleteAllPrepublicationNotesFromField500InNonPubRecord,
157
+ encodingLevelIsBetterThanPrepublication,
158
+ isEnnakkotietoField,
159
+ isEnnakkotietoSubfield,
160
+ removeWorsePrepubField500s,
161
+ removeWorsePrepubField594s,
162
+ fieldGetOccurrenceNumberPairs,
163
+ get6s,
164
+ fieldGetUnambiguousOccurrenceNumber,
165
+ intToOccurrenceNumberString,
166
+ isValidSubfield6,
167
+ recordGetMaxSubfield6OccurrenceNumberAsInteger,
168
+ recordResetSubfield6OccurrenceNumbers,
169
+ resetSubfield6Tag,
170
+ subfield6ResetOccurrenceNumber,
171
+ subfield6GetOccurrenceNumber,
172
+ subfield6GetOccurrenceNumberAsInteger,
173
+ getSubfield8LinkingNumber,
174
+ isValidSubfield8,
175
+ recordGetAllSubfield8LinkingNumbers,
176
+ recordGetFieldsWithSubfield8LinkingNumber,
177
+ getCounterpart,
178
+ melindaFieldSpecs,
179
+ mergeField,
180
+ postprocessRecords
118
181
  };
119
182
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["import AccessRights from './access-rights';\nimport AddMissingField041 from './addMissingField041';\nimport AddMissingField336 from './addMissingField336';\nimport AddMissingField337 from './addMissingField337';\nimport AddMissingField338 from './addMissingField338';\nimport Cyrillux from './cyrillux';\nimport CyrilluxUsemarconReplacement from './cyrillux-usemarcon-replacement';\nimport DisambiguateSeriesStatements from './disambiguateSeriesStatements';\nimport DoubleCommas from './double-commas';\nimport DuplicatesInd1 from './duplicates-ind1';\nimport EmptyFields from './empty-fields';\nimport EndingPunctuation from './ending-punctuation';\nimport EndingWhitespace from './ending-whitespace';\nimport Field008CharacterGroups from './field-008-18-34-character-groups';\nimport Field505Separators from './field-505-separators';\nimport Field521Fix from './field-521-fix';\nimport FieldExclusion from './field-exclusion';\nimport FieldStructure from './field-structure';\nimport FieldsPresent from './fields-present';\nimport Fix33X from './fix-33X';\nimport FixCountryCodes from './fix-country-codes';\nimport FixLanguageCodes from './fix-language-codes';\nimport FixRelatorTerms from './fixRelatorTerms';\nimport FixedFields from './fixed-fields';\nimport IdenticalFields from './identical-fields';\nimport IndicatorFixes from './indicator-fixes';\nimport IsbnIssn from './isbn-issn';\nimport ItemLanguage from './item-language';\nimport MergeField500Lisapainokset from './mergeField500Lisapainokset';\nimport MergeFields from './merge-fields/';\nimport MergeRelatorTermFields from './mergeRelatorTermFields';\nimport Modernize502 from './modernize-502';\nimport MultipleSubfield0s from './multiple-subfield-0';\nimport NonBreakingSpace from './non-breaking-space';\nimport NormalizeDashes from './normalize-dashes';\nimport NormalizeIdentifiers from './normalize-identifiers';\nimport NormalizeQualifyingInformation from './normalize-qualifying-information';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics';\nimport Punctuation from './punctuation/';\nimport Punctuation2 from './punctuation2';\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers';\nimport RemoveDuplicateDataFields from './removeDuplicateDataFields';\nimport RemoveInferiorDataFields from './removeInferiorDataFields';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes';\nimport SortFields from './sortFields';\nimport SortRelatorTerms from './sortRelatorTerms';\nimport SortSubfields from './sortSubfields';\nimport SortTags from './sort-tags';\n// import StripPunctuation from './stripPunctuation'; // Can we add this here? Should be used very cautiosly!\nimport SubfieldValueNormalizations from './subfieldValueNormalizations';\nimport SubfieldExclusion from './subfield-exclusion';\nimport Sync007And300 from './sync-007-and-300';\nimport TranslateTerms from './translate-terms';\nimport TypeOfDateF008 from './typeOfDate-008';\nimport UnicodeDecomposition from './unicode-decomposition';\nimport UpdateField540 from './update-field-540';\nimport Urn from './urn';\n\nexport {\n AccessRights,\n AddMissingField041,\n AddMissingField336,\n AddMissingField337,\n AddMissingField338,\n Cyrillux,\n CyrilluxUsemarconReplacement,\n DisambiguateSeriesStatements,\n DoubleCommas,\n DuplicatesInd1,\n EmptyFields,\n EndingPunctuation,\n EndingWhitespace,\n Field008CharacterGroups,\n Field505Separators,\n Field521Fix,\n FieldExclusion,\n FieldsPresent,\n FieldStructure,\n Fix33X,\n FixCountryCodes,\n FixLanguageCodes,\n FixRelatorTerms,\n FixedFields,\n IdenticalFields,\n IndicatorFixes,\n IsbnIssn,\n ItemLanguage,\n MergeField500Lisapainokset,\n MergeRelatorTermFields,\n Modernize502, //\n MultipleSubfield0s,\n NonBreakingSpace,\n NormalizeDashes,\n NormalizeIdentifiers,\n NormalizeQualifyingInformation,\n NormalizeUTF8Diacritics,\n Punctuation,\n Punctuation2,\n ResolveOrphanedSubfield6s, // Do this before reindexing! (thus I'm not sticking with alphabetical order here)\n ReindexSubfield6OccurenceNumbers,\n RemoveDuplicateDataFields,\n RemoveInferiorDataFields,\n ResolvableExtReferences,\n SanitizeVocabularySourceCodes,\n SortRelatorTerms,\n SortSubfields,\n SortTags,\n SubfieldExclusion,\n SubfieldValueNormalizations,\n Sync007And300,\n TypeOfDateF008,\n TranslateTerms,\n UnicodeDecomposition,\n UpdateField540,\n Urn,\n SortFields, // Keep this penultimate\n MergeFields // Run this last *iff* you want to use this at all\n};\n"],
5
- "mappings": "AAAA,OAAO,kBAAkB;AACzB,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,wBAAwB;AAC/B,OAAO,cAAc;AACrB,OAAO,kCAAkC;AACzC,OAAO,kCAAkC;AACzC,OAAO,kBAAkB;AACzB,OAAO,oBAAoB;AAC3B,OAAO,iBAAiB;AACxB,OAAO,uBAAuB;AAC9B,OAAO,sBAAsB;AAC7B,OAAO,6BAA6B;AACpC,OAAO,wBAAwB;AAC/B,OAAO,iBAAiB;AACxB,OAAO,oBAAoB;AAC3B,OAAO,oBAAoB;AAC3B,OAAO,mBAAmB;AAC1B,OAAO,YAAY;AACnB,OAAO,qBAAqB;AAC5B,OAAO,sBAAsB;AAC7B,OAAO,qBAAqB;AAC5B,OAAO,iBAAiB;AACxB,OAAO,qBAAqB;AAC5B,OAAO,oBAAoB;AAC3B,OAAO,cAAc;AACrB,OAAO,kBAAkB;AACzB,OAAO,gCAAgC;AACvC,OAAO,iBAAiB;AACxB,OAAO,4BAA4B;AACnC,OAAO,kBAAkB;AACzB,OAAO,wBAAwB;AAC/B,OAAO,sBAAsB;AAC7B,OAAO,qBAAqB;AAC5B,OAAO,0BAA0B;AACjC,OAAO,oCAAoC;AAC3C,OAAO,6BAA6B;AACpC,OAAO,iBAAiB;AACxB,OAAO,kBAAkB;AACzB,OAAO,sCAAsC;AAC7C,OAAO,+BAA+B;AACtC,OAAO,8BAA8B;AACrC,OAAO,6BAA6B;AACpC,OAAO,+BAA+B;AACtC,OAAO,mCAAmC;AAC1C,OAAO,gBAAgB;AACvB,OAAO,sBAAsB;AAC7B,OAAO,mBAAmB;AAC1B,OAAO,cAAc;AAErB,OAAO,iCAAiC;AACxC,OAAO,uBAAuB;AAC9B,OAAO,mBAAmB;AAC1B,OAAO,oBAAoB;AAC3B,OAAO,oBAAoB;AAC3B,OAAO,0BAA0B;AACjC,OAAO,oBAAoB;AAC3B,OAAO,SAAS;AAEhB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;",
4
+ "sourcesContent": ["import AccessRights from './access-rights.js';\nimport AddMissingField041 from './addMissingField041.js';\nimport AddMissingField336 from './addMissingField336.js';\nimport AddMissingField337 from './addMissingField337.js';\nimport AddMissingField338 from './addMissingField338.js';\nimport Cyrillux from './cyrillux.js';\nimport CyrilluxUsemarconReplacement from './cyrillux-usemarcon-replacement.js';\nimport DisambiguateSeriesStatements from './disambiguateSeriesStatements.js';\nimport DoubleCommas from './double-commas.js';\nimport DuplicatesInd1 from './duplicates-ind1.js';\nimport EmptyFields from './empty-fields.js';\nimport EndingPunctuation from './ending-punctuation.js';\nimport EndingWhitespace from './ending-whitespace.js';\nimport Field008CharacterGroups from './field-008-18-34-character-groups.js';\nimport Field505Separators from './field-505-separators.js';\nimport Field521Fix from './field-521-fix.js';\nimport FieldExclusion from './field-exclusion.js';\nimport FieldStructure from './field-structure.js';\nimport FieldsPresent from './fields-present.js';\nimport Fix33X from './fix-33X.js';\nimport FixCountryCodes from './fix-country-codes.js';\nimport FixLanguageCodes from './fix-language-codes.js';\nimport FixRelatorTerms from './fixRelatorTerms.js';\nimport FixedFields from './fixed-fields.js';\nimport IdenticalFields from './identical-fields.js';\nimport IndicatorFixes from './indicator-fixes.js';\nimport IsbnIssn from './isbn-issn.js';\nimport ItemLanguage from './item-language.js';\nimport MergeField500Lisapainokset from './mergeField500Lisapainokset.js';\nimport MergeFields from './merge-fields/index.js';\nimport MergeRelatorTermFields from './mergeRelatorTermFields.js';\nimport Modernize502 from './modernize-502.js';\nimport MultipleSubfield0s from './multiple-subfield-0.js';\nimport NonBreakingSpace from './non-breaking-space.js';\nimport NormalizeDashes from './normalize-dashes.js';\nimport NormalizeIdentifiers from './normalize-identifiers.js';\nimport NormalizeQualifyingInformation from './normalize-qualifying-information.js';\nimport NormalizeUTF8Diacritics from './normalize-utf8-diacritics.js';\nimport Punctuation from './punctuation/index.js';\nimport Punctuation2 from './punctuation2.js';\nimport ReindexSubfield6OccurenceNumbers from './reindexSubfield6OccurenceNumbers.js';\nimport RemoveDuplicateDataFields from './removeDuplicateDataFields.js';\nimport RemoveInferiorDataFields from './removeInferiorDataFields.js';\nimport ResolvableExtReferences from './resolvable-ext-references-melinda.js';\nimport ResolveOrphanedSubfield6s from './resolveOrphanedSubfield6s.js';\nimport SanitizeVocabularySourceCodes from './sanitize-vocabulary-source-codes.js';\nimport SortFields from './sortFields.js';\nimport SortRelatorTerms from './sortRelatorTerms.js';\nimport SortSubfields from './sortSubfields.js';\nimport SortTags from './sort-tags.js';\n// import StripPunctuation from './stripPunctuation'; // Can we add this here? Should be used very cautiosly!\nimport SubfieldValueNormalizations from './subfieldValueNormalizations.js';\nimport SubfieldExclusion from './subfield-exclusion.js';\nimport Sync007And300 from './sync-007-and-300.js';\nimport TranslateTerms from './translate-terms.js';\nimport TypeOfDateF008 from './typeOfDate-008.js';\nimport UnicodeDecomposition from './unicode-decomposition.js';\nimport UpdateField540 from './update-field-540.js';\nimport Urn from './urn.js';\n\nimport {getCounterpart} from './merge-fields/counterpartField.js';\n\nimport {postprocessRecords} from './merge-fields/mergeOrAddPostprocess.js';\nimport {mergeField} from './merge-fields/mergeField.js';\nimport {fieldGetOccurrenceNumberPairs, fieldGetUnambiguousOccurrenceNumber, fieldToNormalizedString, fieldsToNormalizedString, get6s,\n isValidSubfield6, recordGetMaxSubfield6OccurrenceNumberAsInteger,\n intToOccurrenceNumberString, resetSubfield6Tag, subfield6ResetOccurrenceNumber, subfield6GetOccurrenceNumber,\n subfield6GetOccurrenceNumberAsInteger} from './subfield6Utils.js';\n\nimport {getSubfield8LinkingNumber, isValidSubfield8, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils.js';\n\nimport {recordFixRelatorTerms} from './fixRelatorTerms.js';\nimport {fieldTrimSubfieldValues} from './normalizeFieldForComparison.js';\nimport {baseHasEqualOrHigherEncodingLevel, deleteAllPrepublicationNotesFromField500InNonPubRecord, encodingLevelIsBetterThanPrepublication, getEncodingLevel, isEnnakkotietoField, isEnnakkotietoSubfield} from './prepublicationUtils.js';\nimport {melindaFieldSpecs} from '@natlibfi/marc-record-validators-melinda/dist/melindaCustomMergeFields.js';\n\nimport {cloneAndRemovePunctuation} from './normalizeFieldForComparison.js';\nimport {removeWorsePrepubField500s, removeWorsePrepubField594s} from './prepublicationUtils.js';\nimport {fieldFixPunctuation} from './punctuation2.js';\nimport {recordResetSubfield6OccurrenceNumbers} from './reindexSubfield6OccurenceNumbers.js';\nimport {sortAdjacentSubfields} from './sortSubfields.js';\nimport {fieldsToString} from './utils.js';\n\nexport {\n AccessRights,\n AddMissingField041,\n AddMissingField336,\n AddMissingField337,\n AddMissingField338,\n Cyrillux,\n CyrilluxUsemarconReplacement,\n DisambiguateSeriesStatements,\n DoubleCommas,\n DuplicatesInd1,\n EmptyFields,\n EndingPunctuation,\n EndingWhitespace,\n Field008CharacterGroups,\n Field505Separators,\n Field521Fix,\n FieldExclusion,\n FieldsPresent,\n FieldStructure,\n Fix33X,\n FixCountryCodes,\n FixLanguageCodes,\n FixRelatorTerms,\n FixedFields,\n IdenticalFields,\n IndicatorFixes,\n IsbnIssn,\n ItemLanguage,\n MergeField500Lisapainokset,\n MergeRelatorTermFields,\n Modernize502, //\n MultipleSubfield0s,\n NonBreakingSpace,\n NormalizeDashes,\n NormalizeIdentifiers,\n NormalizeQualifyingInformation,\n NormalizeUTF8Diacritics,\n Punctuation,\n Punctuation2,\n ResolveOrphanedSubfield6s, // Do this before reindexing! (thus I'm not sticking with alphabetical order here)\n ReindexSubfield6OccurenceNumbers,\n RemoveDuplicateDataFields,\n RemoveInferiorDataFields,\n ResolvableExtReferences,\n SanitizeVocabularySourceCodes,\n SortRelatorTerms,\n SortSubfields,\n SortTags,\n SubfieldExclusion,\n SubfieldValueNormalizations,\n Sync007And300,\n TypeOfDateF008,\n TranslateTerms,\n UnicodeDecomposition,\n UpdateField540,\n Urn,\n SortFields, // Keep this penultimate\n MergeFields, // Run this last *iff* you want to use this at all\n\n // Functions for processing record... These should probably go to some other project.\n // Too specific for marc-record-js though...\n // 1. generic low level stuff\n getEncodingLevel,\n\n // 2. text normalizations (eg. for similarity comparisons, field merge)\n cloneAndRemovePunctuation,\n fieldFixPunctuation,\n fieldToNormalizedString,\n fieldTrimSubfieldValues,\n fieldsToNormalizedString,\n fieldsToString,\n recordFixRelatorTerms,\n sortAdjacentSubfields,\n\n // 3. prepublication stuff\n baseHasEqualOrHigherEncodingLevel,\n deleteAllPrepublicationNotesFromField500InNonPubRecord,\n encodingLevelIsBetterThanPrepublication,\n isEnnakkotietoField,\n isEnnakkotietoSubfield,\n removeWorsePrepubField500s,\n removeWorsePrepubField594s,\n\n // 4. subfield $6 related functions\n fieldGetOccurrenceNumberPairs,\n get6s,\n fieldGetUnambiguousOccurrenceNumber,\n intToOccurrenceNumberString,\n isValidSubfield6,\n recordGetMaxSubfield6OccurrenceNumberAsInteger,\n recordResetSubfield6OccurrenceNumbers,\n resetSubfield6Tag,\n subfield6ResetOccurrenceNumber,\n subfield6GetOccurrenceNumber,\n subfield6GetOccurrenceNumberAsInteger,\n\n // 5. subfield $8 related functions\n getSubfield8LinkingNumber,\n isValidSubfield8,\n recordGetAllSubfield8LinkingNumbers,\n recordGetFieldsWithSubfield8LinkingNumber,\n\n // 6. merge, other\n getCounterpart, // field merge: finds a similar field with which a field can merge\n melindaFieldSpecs, // contains information about the legal fields and subfields, and their repeatability\n mergeField,\n postprocessRecords // clean-up function that cleans up both base and source record (which may be the same)\n\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -121,6 +121,15 @@ function normalize245Indicator1(field, record) {
121
121
  const field1XX = record.get("^1..$");
122
122
  field.ind1 = field1XX.length === 0 ? "0" : "1";
123
123
  }
124
+ function noDisplayConstantGenerated520Indicator1(field) {
125
+ if (field.tag !== "520") {
126
+ return;
127
+ }
128
+ const as = field.subfields.filter((sf) => sf.code === "a");
129
+ if (as.length === 1 && ["Abstract.", "Abstrakt.", "Abstrakti.", "Abstract.", "English Summary.", "Sammandrag.", "Tiivistelm\xE4."].includes(field.subfields[0].value)) {
130
+ field.ind1 = "8";
131
+ }
132
+ }
124
133
  function normalize776Indicator2(field) {
125
134
  if (field.tag !== "776") {
126
135
  return;
@@ -165,7 +174,7 @@ function getLanguages(record) {
165
174
  return true;
166
175
  }
167
176
  }
168
- export function recordNormalizeIndicators(record) {
177
+ function recordNormalizeIndicators(record) {
169
178
  recordNormalize490(record);
170
179
  const languages = getLanguages(record);
171
180
  record.fields.forEach((field) => fieldNormalizeIndicators(field, record, languages));
@@ -173,6 +182,7 @@ export function recordNormalizeIndicators(record) {
173
182
  function fieldNormalizeIndicators(field, record, languages) {
174
183
  normalize084Indicator1(field);
175
184
  normalize245Indicator1(field, record);
185
+ noDisplayConstantGenerated520Indicator1(field);
176
186
  normalizeNonFilingIndicator1(field, languages);
177
187
  normalizeNonFilingIndicator2(field, languages);
178
188
  normalize776Indicator2(field);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/indicator-fixes.js"],
4
- "sourcesContent": ["// Relocated from melinda-marc-record-merge-reducers (and renamed)\n//import createDebugLogger from 'debug';\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:normalizeIdentifiers');\n\nimport {fieldToString} from './utils.js';\n\n\nexport default function () {\n\n return {\n description: 'Normalizes indicator values',\n validate, fix\n };\n\n function fix(record) {\n const res = {message: [], fix: [], valid: true};\n\n recordNormalizeIndicators(record);\n\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n\n validateRecord(record, res);\n\n res.valid = res.message.length < 1;\n return res;\n }\n\n\n function validateRecord(record, res) {\n //nvdebug(record);\n const clonedFields = JSON.parse(JSON.stringify(record.fields));\n recordNormalizeIndicators(record);\n\n record.fields.forEach((field, index) => compareFields(field, index));\n\n function compareFields(field, index) {\n const origFieldAsString = fieldToString(clonedFields[index]);\n //const clonedFieldAsString = fieldToString(field);\n if (clonedFields[index].ind1 !== field.ind1) {\n //nvdebug(`FIX IND1: '${clonedFields[index].ind1}' => '${field.ind1}': ${clonedFieldAsString}`);\n res.message.push(`Expected IND1 for '${origFieldAsString}' is '${field.ind1}'`);\n }\n if (clonedFields[index].ind2 !== field.ind2) {\n //nvdebug(`FIX IND2: '${clonedFields[index].ind2}' => '${field.ind2}': ${clonedFieldAsString}`);\n res.message.push(`Expected IND2 for '${origFieldAsString}' is '${field.ind2}'`);\n }\n }\n // Validator should not change the original record:\n record.fields = clonedFields;\n return;\n }\n}\n\n\nconst ind1NonFilingChars = ['130', '630', '730', '740'];\nconst ind2NonFilingChars = ['222', '240', '242', '243', '245', '830'];\n\nfunction hasNonFilingIndicator1(field) {\n return ind1NonFilingChars.includes(field.tag);\n}\n\nfunction modifiableIndicatorValue(value) {\n // If field contains a legit-looking value, don't try to modify it here...\n return !['9', '8', '7', '6', '5', '4', '3', '2', '1'].includes(value);\n}\n\nfunction hasNonFilingIndicator2(field) {\n return ind2NonFilingChars.includes(field.tag);\n}\n\nfunction valueBeginsWithDeterminer(value, cands) {\n return cands.find(cand => value.substring(0, cand.length) === cand);\n}\n\nfunction determineNonFilingIndicatorValue(field, languages = undefined) {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (!subfieldA) {\n // nvdebug(' Subfield $a miss!');\n return;\n }\n\n const name = subfieldA.value.toLowerCase();\n\n if (languages.includes('eng')) {\n const match = valueBeginsWithDeterminer(name, ['a ', 'an ', 'the ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('fre')) {\n const match = valueBeginsWithDeterminer(name, ['l\\'', 'le ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('ger')) {\n const match = valueBeginsWithDeterminer(name, ['das ', 'der ', 'die ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('swe')) {\n const match = valueBeginsWithDeterminer(name, ['en ', 'ett ']);\n if (match) {\n return `${match.length}`;\n }\n if (name.match(/^de[nt] /u) && !name.match(/^de[nt] som /u)) {\n return '4';\n }\n }\n\n // Fallback-ish: try to guess even without languages:\n const match = valueBeginsWithDeterminer(name, ['the ']);\n if (match) {\n return `${match.length}`;\n }\n if (name.match(/^a /u) && !languages.includes('hun') && !name.match(/^a (?:b |la )/u)) { // Skip \"a b c\", \"a la carte\"...\n return '2';\n }\n\n return '0';\n}\n\nfunction normalizeNonFilingIndicator1(field, languages = []) {\n if (!hasNonFilingIndicator1(field) || !modifiableIndicatorValue(field.ind1)) {\n return;\n }\n\n field.ind1 = determineNonFilingIndicatorValue(field, languages);\n}\n\nfunction normalizeNonFilingIndicator2(field, languages = []) {\n if (!hasNonFilingIndicator2(field) || !modifiableIndicatorValue(field.ind2)) {\n return;\n }\n\n field.ind2 = determineNonFilingIndicatorValue(field, languages);\n}\n\nconst fiktiivisenAineistonLisaluokatFI = ['El\u00E4imet', 'Erotiikka', 'Er\u00E4', 'Fantasia', 'Historia', 'Huumori', 'J\u00E4nnitys', 'Kauhu', 'Novellit', 'Romantiikka', 'Scifi', 'Sota', 'Urheilu', 'Uskonto'];\n\nfunction containsFiktiivisenAineistonLisaluokka(field) {\n // Should we check Swedish versions as well?\n return field.subfields.some(sf => sf.code === 'a' && fiktiivisenAineistonLisaluokatFI.includes(sf.value));\n}\n\nfunction normalize084Indicator1(field) {\n if (field.tag !== '084') {\n return;\n }\n\n // https://marc21.kansalliskirjasto.fi/bib/05X-08X.htm#084 and https://finto.fi/ykl/fi/page/fiktioluokka\n if (field.ind1 !== '9' && containsFiktiivisenAineistonLisaluokka(field) && field.subfields.some(sf => sf.code === '2' && sf.value === 'ykl')) {\n field.ind1 = '9';\n return;\n }\n}\n\nfunction normalize245Indicator1(field, record) {\n if (field.tag !== '245') {\n return;\n }\n const field1XX = record.get('^1..$');\n field.ind1 = field1XX.length === 0 ? '0' : '1';\n}\n\nfunction normalize776Indicator2(field) {\n if (field.tag !== '776') {\n return;\n }\n // If subfield $i exists, ind2 must me '8'\n if (field.subfields.some(sf => sf.code === 'i')) {\n field.ind2 = '8';\n return;\n }\n}\n\n\nfunction recordNormalize490(record) {\n const fields490 = record.get('^490$');\n const fields8XX = record.get('^(?:800|810|811|830)$');\n\n if (fields490.length === 0) {\n return;\n }\n if (fields490.length <= fields8XX.length) {\n // Trace found for each field 490:\n fields490.forEach(f => {\n f.ind1 = '1';\n });\n return;\n }\n if (fields8XX.length === 0) { // Fields 490 are always untraced (no traces found)\n fields490.forEach(f => {\n f.ind1 = '0';\n });\n return;\n }\n // For other combinations we just can't be sure, so leave them as they are.\n}\n\n\nfunction getLanguages(record) {\n const langFields = record.get('^041$');\n\n if (langFields.length === 0) {\n return [];\n }\n\n return langFields[0].subfields.filter(sf => isRelevantSubfield(sf)).map(subfield => subfield.value);\n\n function isRelevantSubfield(subfield) {\n if (!['a', 'd', 'h'].includes(subfield.code)) {\n return false;\n }\n if (subfield.value.length !== 3) {\n return false;\n }\n // We could require /^[a-z][a-z][a-z]$/ etc as well, but it's not really that relevant.\n return true;\n }\n\n}\n\nexport function recordNormalizeIndicators(record) {\n recordNormalize490(record);\n\n // Language is used to handle non-filing indicators\n const languages = getLanguages(record);\n\n record.fields.forEach(field => fieldNormalizeIndicators(field, record, languages));\n\n}\n\nfunction fieldNormalizeIndicators(field, record, languages) {\n normalize084Indicator1(field);\n normalize245Indicator1(field, record);\n normalizeNonFilingIndicator1(field, languages);\n normalizeNonFilingIndicator2(field, languages);\n normalize776Indicator2(field);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Relocated from melinda-marc-record-merge-reducers (and renamed)\n//import createDebugLogger from 'debug';\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:normalizeIdentifiers');\n\nimport {fieldToString} from './utils.js';\n\n\nexport default function () {\n\n return {\n description: 'Normalizes indicator values',\n validate, fix\n };\n\n function fix(record) {\n const res = {message: [], fix: [], valid: true};\n\n recordNormalizeIndicators(record);\n\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n\n validateRecord(record, res);\n\n res.valid = res.message.length < 1;\n return res;\n }\n\n\n function validateRecord(record, res) {\n //nvdebug(record);\n const clonedFields = JSON.parse(JSON.stringify(record.fields));\n recordNormalizeIndicators(record);\n\n record.fields.forEach((field, index) => compareFields(field, index));\n\n function compareFields(field, index) {\n const origFieldAsString = fieldToString(clonedFields[index]);\n //const clonedFieldAsString = fieldToString(field);\n if (clonedFields[index].ind1 !== field.ind1) {\n //nvdebug(`FIX IND1: '${clonedFields[index].ind1}' => '${field.ind1}': ${clonedFieldAsString}`);\n res.message.push(`Expected IND1 for '${origFieldAsString}' is '${field.ind1}'`);\n }\n if (clonedFields[index].ind2 !== field.ind2) {\n //nvdebug(`FIX IND2: '${clonedFields[index].ind2}' => '${field.ind2}': ${clonedFieldAsString}`);\n res.message.push(`Expected IND2 for '${origFieldAsString}' is '${field.ind2}'`);\n }\n }\n // Validator should not change the original record:\n record.fields = clonedFields;\n return;\n }\n}\n\n\nconst ind1NonFilingChars = ['130', '630', '730', '740'];\nconst ind2NonFilingChars = ['222', '240', '242', '243', '245', '830'];\n\nfunction hasNonFilingIndicator1(field) {\n return ind1NonFilingChars.includes(field.tag);\n}\n\nfunction modifiableIndicatorValue(value) {\n // If field contains a legit-looking value, don't try to modify it here...\n return !['9', '8', '7', '6', '5', '4', '3', '2', '1'].includes(value);\n}\n\nfunction hasNonFilingIndicator2(field) {\n return ind2NonFilingChars.includes(field.tag);\n}\n\nfunction valueBeginsWithDeterminer(value, cands) {\n return cands.find(cand => value.substring(0, cand.length) === cand);\n}\n\nfunction determineNonFilingIndicatorValue(field, languages = undefined) {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (!subfieldA) {\n // nvdebug(' Subfield $a miss!');\n return;\n }\n\n const name = subfieldA.value.toLowerCase();\n\n if (languages.includes('eng')) {\n const match = valueBeginsWithDeterminer(name, ['a ', 'an ', 'the ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('fre')) {\n const match = valueBeginsWithDeterminer(name, ['l\\'', 'le ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('ger')) {\n const match = valueBeginsWithDeterminer(name, ['das ', 'der ', 'die ']);\n if (match) {\n return `${match.length}`;\n }\n }\n\n if (languages.includes('swe')) {\n const match = valueBeginsWithDeterminer(name, ['en ', 'ett ']);\n if (match) {\n return `${match.length}`;\n }\n if (name.match(/^de[nt] /u) && !name.match(/^de[nt] som /u)) {\n return '4';\n }\n }\n\n // Fallback-ish: try to guess even without languages:\n const match = valueBeginsWithDeterminer(name, ['the ']);\n if (match) {\n return `${match.length}`;\n }\n if (name.match(/^a /u) && !languages.includes('hun') && !name.match(/^a (?:b |la )/u)) { // Skip \"a b c\", \"a la carte\"...\n return '2';\n }\n\n return '0';\n}\n\nfunction normalizeNonFilingIndicator1(field, languages = []) {\n if (!hasNonFilingIndicator1(field) || !modifiableIndicatorValue(field.ind1)) {\n return;\n }\n\n field.ind1 = determineNonFilingIndicatorValue(field, languages);\n}\n\nfunction normalizeNonFilingIndicator2(field, languages = []) {\n if (!hasNonFilingIndicator2(field) || !modifiableIndicatorValue(field.ind2)) {\n return;\n }\n\n field.ind2 = determineNonFilingIndicatorValue(field, languages);\n}\n\nconst fiktiivisenAineistonLisaluokatFI = ['El\u00E4imet', 'Erotiikka', 'Er\u00E4', 'Fantasia', 'Historia', 'Huumori', 'J\u00E4nnitys', 'Kauhu', 'Novellit', 'Romantiikka', 'Scifi', 'Sota', 'Urheilu', 'Uskonto'];\n\nfunction containsFiktiivisenAineistonLisaluokka(field) {\n // Should we check Swedish versions as well?\n return field.subfields.some(sf => sf.code === 'a' && fiktiivisenAineistonLisaluokatFI.includes(sf.value));\n}\n\nfunction normalize084Indicator1(field) {\n if (field.tag !== '084') {\n return;\n }\n\n // https://marc21.kansalliskirjasto.fi/bib/05X-08X.htm#084 and https://finto.fi/ykl/fi/page/fiktioluokka\n if (field.ind1 !== '9' && containsFiktiivisenAineistonLisaluokka(field) && field.subfields.some(sf => sf.code === '2' && sf.value === 'ykl')) {\n field.ind1 = '9';\n return;\n }\n}\n\nfunction normalize245Indicator1(field, record) {\n if (field.tag !== '245') {\n return;\n }\n const field1XX = record.get('^1..$');\n field.ind1 = field1XX.length === 0 ? '0' : '1';\n}\n\nfunction noDisplayConstantGenerated520Indicator1(field) {\n if (field.tag !== '520') {\n return;\n }\n const as = field.subfields.filter(sf => sf.code === 'a');\n // Set ind1=8 \"no display constant generated\" fro certain values (part of MELKEHITYS-2579):\n if (as.length === 1 && ['Abstract.', 'Abstrakt.', 'Abstrakti.', 'Abstract.', 'English Summary.', 'Sammandrag.', 'Tiivistelm\u00E4.'].includes(field.subfields[0].value)) {\n field.ind1 = '8';\n }\n\n}\n\nfunction normalize776Indicator2(field) {\n if (field.tag !== '776') {\n return;\n }\n // If subfield $i exists, ind2 must me '8'\n if (field.subfields.some(sf => sf.code === 'i')) {\n field.ind2 = '8';\n return;\n }\n}\n\n\nfunction recordNormalize490(record) {\n const fields490 = record.get('^490$');\n const fields8XX = record.get('^(?:800|810|811|830)$');\n\n if (fields490.length === 0) {\n return;\n }\n if (fields490.length <= fields8XX.length) {\n // Trace found for each field 490:\n fields490.forEach(f => {\n f.ind1 = '1';\n });\n return;\n }\n if (fields8XX.length === 0) { // Fields 490 are always untraced (no traces found)\n fields490.forEach(f => {\n f.ind1 = '0';\n });\n return;\n }\n // For other combinations we just can't be sure, so leave them as they are.\n}\n\n\nfunction getLanguages(record) {\n const langFields = record.get('^041$');\n\n if (langFields.length === 0) {\n return [];\n }\n\n return langFields[0].subfields.filter(sf => isRelevantSubfield(sf)).map(subfield => subfield.value);\n\n function isRelevantSubfield(subfield) {\n if (!['a', 'd', 'h'].includes(subfield.code)) {\n return false;\n }\n if (subfield.value.length !== 3) {\n return false;\n }\n // We could require /^[a-z][a-z][a-z]$/ etc as well, but it's not really that relevant.\n return true;\n }\n\n}\n\nfunction recordNormalizeIndicators(record) {\n recordNormalize490(record);\n\n // Language is used to handle non-filing indicators\n const languages = getLanguages(record);\n\n record.fields.forEach(field => fieldNormalizeIndicators(field, record, languages));\n\n}\n\nfunction fieldNormalizeIndicators(field, record, languages) {\n normalize084Indicator1(field);\n normalize245Indicator1(field, record);\n noDisplayConstantGenerated520Indicator1(field);\n normalizeNonFilingIndicator1(field, languages);\n normalizeNonFilingIndicator2(field, languages);\n normalize776Indicator2(field);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["match"]
7
7
  }
package/dist/isbn-issn.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import ISBN from "isbn3";
2
- import validateISSN from "@natlibfi/issn-verify";
2
+ import { issn as validateISSN } from "@natlibfi/issn-verify";
3
3
  export default ({ hyphenateISBN = false, handleInvalid = false } = {}) => {
4
4
  return {
5
5
  validate,
@@ -23,8 +23,12 @@ export default ({ hyphenateISBN = false, handleInvalid = false } = {}) => {
23
23
  }
24
24
  function invalidISBN(isbn) {
25
25
  const isbnOnly = getFirstWord(isbn);
26
- const auditedIsbn = ISBN.audit(isbnOnly);
27
- return !auditedIsbn.validIsbn;
26
+ try {
27
+ const auditedIsbn = ISBN.audit(isbnOnly);
28
+ return !auditedIsbn.validIsbn;
29
+ } catch {
30
+ return true;
31
+ }
28
32
  }
29
33
  function invalidSubfield(subfield) {
30
34
  if (subfield.code !== "a") {
@@ -184,8 +188,7 @@ export default ({ hyphenateISBN = false, handleInvalid = false } = {}) => {
184
188
  }
185
189
  function normalizeIsbnValue(value) {
186
190
  const trimmedValue = getFirstWord(value);
187
- const auditResult = ISBN.audit(trimmedValue);
188
- if (!auditResult.validIsbn) {
191
+ if (invalidISBN(trimmedValue)) {
189
192
  return void 0;
190
193
  }
191
194
  const numbersOnly = trimmedValue.replace(/[^0-9Xx]+/ug, "");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/isbn-issn.js"],
4
- "sourcesContent": ["import ISBN from 'isbn3';\nimport validateISSN from '@natlibfi/issn-verify';\n\n// handleInvalid: move invalid 020$a to 020$z, and invalid 022$a to 022$y\nexport default ({hyphenateISBN = false, handleInvalid = false} = {}) => {\n return {\n validate, fix,\n description: 'Validates ISBN and ISSN values'\n };\n\n function stringHasSpace(str) {\n return str.indexOf(' ') > -1;\n }\n\n function trimSpaces(value) {\n return value.replace(/^\\s+/u, '').replace(/\\s+$/u, '').replace(/\\s+/gu, ' ');\n }\n\n function isMultiWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n return stringHasSpace(trimmedString);\n }\n\n function getFirstWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n const arr = trimmedString.split(' ');\n return arr[0];\n }\n\n function invalidISBN(isbn) {\n const isbnOnly = getFirstWord(isbn);\n const auditedIsbn = ISBN.audit(isbnOnly);\n return !auditedIsbn.validIsbn;\n }\n\n function invalidSubfield(subfield) {\n if (subfield.code !== 'a') {\n return false;\n }\n return invalidISBN(subfield.value) || isMultiWord(subfield.value);\n }\n\n\n function invalidField020(field) {\n if (field.subfields && field.subfields.some(sf => invalidSubfield(sf))) {\n return true;\n }\n return false;\n }\n\n function subfieldsIsbnRequiresHyphenation(subfield) {\n if (!hyphenateISBN || !['a', 'z'].includes(subfield.code)) {\n return false;\n }\n\n const isbn = getFirstWord(subfield.value);\n if (subfield.code === 'a') {\n return requiresHyphenation(isbn);\n }\n\n // $z is a bit hacky: hyphenation is required only iff valid and no '-' chars\n if (isbn.indexOf('-') > -1) {\n return false;\n }\n return !invalidISBN(isbn);\n\n function requiresHyphenation(isbn) {\n if (!hyphenateISBN) {\n return false;\n }\n // Handle old notation such as \"978-952-396-001-5 (nid.)\"\n const isbn2 = getFirstWord(isbn);\n\n if (invalidISBN(isbn2)) {\n return false;\n }\n\n const parsedIsbn = ISBN.parse(isbn2);\n // Return true only if existing ISBN is a valid and hyphenated 10 or 13 digit ISBN:\n return !(isbn2 === parsedIsbn.isbn10h || isbn2 === parsedIsbn.isbn13h);\n }\n }\n\n function getRelevantFields(record) {\n //return record.get(/^(?:020|022)$/u).filter(field => {\n return record.fields.filter(field => {\n if (!field.subfields) {\n return false;\n }\n // Check ISBN:\n if (field.tag === '020') {\n if (invalidField020(field)) { // checks multiwordness\n return true;\n }\n return fieldsIsbnRequiresHyphenation(field);\n }\n\n // Check ISSN:\n if (field.tag === '022') {\n if (invalidField022(field)) {\n return true;\n }\n\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n return !validateISSN(subfield.value);\n }\n return false;\n });\n\n function fieldsIsbnRequiresHyphenation(field) {\n return field.subfields && field.subfields.some(sf => subfieldsIsbnRequiresHyphenation(sf));\n }\n\n function invalidField022(field) {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL === undefined) {\n const subfieldY = field.subfields.find(sf => sf.code === 'y');\n if (subfieldY) {\n return false;\n }\n\n return true;\n }\n return false;\n }\n }\n\n function validate(record) {\n const fields = getRelevantFields(record);\n\n if (fields.length === 0) {\n return {valid: true};\n }\n\n return fields\n .map(field => {\n if (field.tag === '020') {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (subfieldA) {\n return {name: 'ISBN', value: subfieldA.value};\n }\n const subfieldZ = field.subfields.find(sf => sf.code === 'z');\n if (subfieldZ) {\n return {name: 'ISBN (subfield Z)', value: subfieldZ.value};\n }\n\n return {name: 'ISBN', value: undefined};\n }\n\n return {name: 'ISSN', value: getISSN()};\n\n function getISSN() {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL) {\n return subfieldAorL.value;\n }\n\n return undefined;\n }\n })\n .reduce((acc, obj) => {\n const {name, value} = obj;\n const msg = `${name} (${value}) is not valid`;\n\n return {...acc, messages: acc.messages.concat(msg)};\n }, {valid: false, messages: []});\n }\n\n\n function fix(record) {\n getRelevantFields(record).forEach(field => {\n if (field.tag === '020') {\n field.subfields.forEach(subfield => fixField020Subfield(field, subfield));\n return;\n }\n // 022 ISSN:\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n if (subfield && handleInvalid) {\n // $a/$l => $y (bit overkill to add $z and remove $a/$l instead of just renaming)\n field.subfields.push({code: 'y', value: subfield.value});\n record.removeSubfield(subfield, field);\n }\n });\n\n\n function fixField020Subfield(field, subfield) {\n split020A(); // subfield and field are in the scope\n addHyphens(subfield);\n handleInvalidIsbn(field, subfield); // remove 020$a, add 020$z, Do this last, as it uses deletion\n return;\n\n function addHyphens(subfield) {\n if (!subfieldsIsbnRequiresHyphenation(subfield)) {\n return;\n }\n // ISBN is valid but is missing hyphens\n const normalizedValue = normalizeIsbnValue(subfield.value);\n if (normalizedValue !== undefined) {\n subfield.value = normalizedValue;\n }\n }\n\n function handleInvalidIsbn(field, subfield) {\n if (subfield.code !== 'a' || !handleInvalid) {\n return;\n }\n const head = getFirstWord(subfield.value);\n if (!invalidISBN(head)) {\n return;\n }\n // $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)\n field.subfields.push({code: 'z', value: subfield.value});\n record.removeSubfield(subfield, field);\n }\n\n function split020A() {\n // Move non-initial words from $a to $q:\n if (subfield.code !== 'a') {\n return;\n }\n const value = trimSpaces(subfield.value);\n const position = value.indexOf(' ');\n if (position === -1) {\n return;\n }\n const head = getFirstWord(value);\n if (invalidISBN(head)) { // Don't split, if first word ain't ISBN\n return;\n }\n const tail = value.substring(position + 1);\n subfield.value = head;\n field.subfields.push({code: 'q', value: tail});\n }\n\n function normalizeIsbnValue(value) {\n const trimmedValue = getFirstWord(value);\n //const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...\n const auditResult = ISBN.audit(trimmedValue);\n if (!auditResult.validIsbn) {\n return undefined;\n }\n const numbersOnly = trimmedValue.replace(/[^0-9Xx]+/ug, '');\n const parsedIsbn = ISBN.parse(trimmedValue);\n if (hyphenateISBN) {\n return numbersOnly.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h;\n }\n return numbersOnly.length === 10 ? parsedIsbn.isbn10 : parsedIsbn.isbn13;\n }\n }\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import ISBN from 'isbn3';\nimport {issn as validateISSN} from '@natlibfi/issn-verify';\n\n// handleInvalid: move invalid 020$a to 020$z, and invalid 022$a to 022$y\nexport default ({hyphenateISBN = false, handleInvalid = false} = {}) => {\n return {\n validate, fix,\n description: 'Validates ISBN and ISSN values'\n };\n\n function stringHasSpace(str) {\n return str.indexOf(' ') > -1;\n }\n\n function trimSpaces(value) {\n return value.replace(/^\\s+/u, '').replace(/\\s+$/u, '').replace(/\\s+/gu, ' ');\n }\n\n function isMultiWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n return stringHasSpace(trimmedString);\n }\n\n function getFirstWord(inputString) {\n const trimmedString = trimSpaces(inputString);\n const arr = trimmedString.split(' ');\n return arr[0];\n }\n\n function invalidISBN(isbn) {\n const isbnOnly = getFirstWord(isbn);\n try {\n const auditedIsbn = ISBN.audit(isbnOnly);\n return !auditedIsbn.validIsbn;\n }\n catch {\n return true;\n }\n\n }\n\n function invalidSubfield(subfield) {\n if (subfield.code !== 'a') {\n return false;\n }\n return invalidISBN(subfield.value) || isMultiWord(subfield.value);\n }\n\n\n function invalidField020(field) {\n if (field.subfields && field.subfields.some(sf => invalidSubfield(sf))) {\n return true;\n }\n return false;\n }\n\n function subfieldsIsbnRequiresHyphenation(subfield) {\n if (!hyphenateISBN || !['a', 'z'].includes(subfield.code)) {\n return false;\n }\n\n const isbn = getFirstWord(subfield.value);\n if (subfield.code === 'a') {\n return requiresHyphenation(isbn);\n }\n\n // $z is a bit hacky: hyphenation is required only iff valid and no '-' chars\n if (isbn.indexOf('-') > -1) {\n return false;\n }\n return !invalidISBN(isbn);\n\n function requiresHyphenation(isbn) {\n if (!hyphenateISBN) {\n return false;\n }\n // Handle old notation such as \"978-952-396-001-5 (nid.)\"\n const isbn2 = getFirstWord(isbn);\n\n if (invalidISBN(isbn2)) {\n return false;\n }\n\n const parsedIsbn = ISBN.parse(isbn2);\n // Return true only if existing ISBN is a valid and hyphenated 10 or 13 digit ISBN:\n return !(isbn2 === parsedIsbn.isbn10h || isbn2 === parsedIsbn.isbn13h);\n }\n }\n\n function getRelevantFields(record) {\n //return record.get(/^(?:020|022)$/u).filter(field => {\n return record.fields.filter(field => {\n if (!field.subfields) {\n return false;\n }\n // Check ISBN:\n if (field.tag === '020') {\n if (invalidField020(field)) { // checks multiwordness\n return true;\n }\n return fieldsIsbnRequiresHyphenation(field);\n }\n\n // Check ISSN:\n if (field.tag === '022') {\n if (invalidField022(field)) {\n return true;\n }\n\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n return !validateISSN(subfield.value);\n }\n return false;\n });\n\n function fieldsIsbnRequiresHyphenation(field) {\n return field.subfields && field.subfields.some(sf => subfieldsIsbnRequiresHyphenation(sf));\n }\n\n function invalidField022(field) {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL === undefined) {\n const subfieldY = field.subfields.find(sf => sf.code === 'y');\n if (subfieldY) {\n return false;\n }\n\n return true;\n }\n return false;\n }\n }\n\n function validate(record) {\n const fields = getRelevantFields(record);\n\n if (fields.length === 0) {\n return {valid: true};\n }\n\n return fields\n .map(field => {\n if (field.tag === '020') {\n const subfieldA = field.subfields.find(sf => sf.code === 'a');\n if (subfieldA) {\n return {name: 'ISBN', value: subfieldA.value};\n }\n const subfieldZ = field.subfields.find(sf => sf.code === 'z');\n if (subfieldZ) {\n return {name: 'ISBN (subfield Z)', value: subfieldZ.value};\n }\n\n return {name: 'ISBN', value: undefined};\n }\n\n return {name: 'ISSN', value: getISSN()};\n\n function getISSN() {\n const subfieldAorL = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n\n if (subfieldAorL) {\n return subfieldAorL.value;\n }\n\n return undefined;\n }\n })\n .reduce((acc, obj) => {\n const {name, value} = obj;\n const msg = `${name} (${value}) is not valid`;\n\n return {...acc, messages: acc.messages.concat(msg)};\n }, {valid: false, messages: []});\n }\n\n\n function fix(record) {\n getRelevantFields(record).forEach(field => {\n if (field.tag === '020') {\n field.subfields.forEach(subfield => fixField020Subfield(field, subfield));\n return;\n }\n // 022 ISSN:\n const subfield = field.subfields.find(sf => sf.code === 'a' || sf.code === 'l');\n if (subfield && handleInvalid) {\n // $a/$l => $y (bit overkill to add $z and remove $a/$l instead of just renaming)\n field.subfields.push({code: 'y', value: subfield.value});\n record.removeSubfield(subfield, field);\n }\n });\n\n\n function fixField020Subfield(field, subfield) {\n split020A(); // subfield and field are in the scope\n addHyphens(subfield);\n handleInvalidIsbn(field, subfield); // remove 020$a, add 020$z, Do this last, as it uses deletion\n return;\n\n function addHyphens(subfield) {\n if (!subfieldsIsbnRequiresHyphenation(subfield)) {\n return;\n }\n // ISBN is valid but is missing hyphens\n const normalizedValue = normalizeIsbnValue(subfield.value);\n if (normalizedValue !== undefined) {\n subfield.value = normalizedValue;\n }\n }\n\n function handleInvalidIsbn(field, subfield) {\n if (subfield.code !== 'a' || !handleInvalid) {\n return;\n }\n const head = getFirstWord(subfield.value);\n if (!invalidISBN(head)) {\n return;\n }\n // $a => $z (bit overkill to add $z and remove $a instead of just renaming, but too lazy to fix/test thorougly)\n field.subfields.push({code: 'z', value: subfield.value});\n record.removeSubfield(subfield, field);\n }\n\n function split020A() {\n // Move non-initial words from $a to $q:\n if (subfield.code !== 'a') {\n return;\n }\n const value = trimSpaces(subfield.value);\n const position = value.indexOf(' ');\n if (position === -1) {\n return;\n }\n const head = getFirstWord(value);\n if (invalidISBN(head)) { // Don't split, if first word ain't ISBN\n return;\n }\n const tail = value.substring(position + 1);\n subfield.value = head;\n field.subfields.push({code: 'q', value: tail});\n }\n\n function normalizeIsbnValue(value) {\n const trimmedValue = getFirstWord(value);\n //const trimmedValue = trimISBN(value); // NB! This might lose information that should be stored in $q...\n if (invalidISBN(trimmedValue)) {\n return undefined; // should this return value (= nothing normalized), not undefined?\n }\n const numbersOnly = trimmedValue.replace(/[^0-9Xx]+/ug, '');\n const parsedIsbn = ISBN.parse(trimmedValue);\n if (hyphenateISBN) {\n return numbersOnly.length === 10 ? parsedIsbn.isbn10h : parsedIsbn.isbn13h;\n }\n return numbersOnly.length === 10 ? parsedIsbn.isbn10 : parsedIsbn.isbn13;\n }\n }\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["isbn", "isbn2", "subfield", "field"]
7
7
  }
@@ -1,4 +1,4 @@
1
- export const melindaCustomMergeFields = { "fields": [
1
+ export const melindaFieldSpecs = { "fields": [
2
2
  {
3
3
  "tag": "leader",
4
4
  "repeatable": false,