@natlibfi/marc-record-validators-melinda 12.0.0-alpha.9 → 12.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-rights.test.js +1 -1
- package/dist/access-rights.test.js.map +1 -1
- package/dist/addMissingField337.test.js +1 -1
- package/dist/addMissingField337.test.js.map +1 -1
- package/dist/addMissingField338.test.js +1 -1
- package/dist/addMissingField338.test.js.map +1 -1
- package/dist/cyrillux-usemarcon-replacement.test.js +4 -7
- package/dist/cyrillux-usemarcon-replacement.test.js.map +2 -2
- package/dist/cyrillux.test.js +1 -1
- package/dist/cyrillux.test.js.map +1 -1
- package/dist/disambiguateSeriesStatements.test.js +1 -7
- package/dist/disambiguateSeriesStatements.test.js.map +2 -2
- package/dist/double-commas.test.js +1 -1
- package/dist/double-commas.test.js.map +1 -1
- package/dist/drop-terms.js +122 -0
- package/dist/drop-terms.js.map +7 -0
- package/dist/drop-terms.test.js +56 -0
- package/dist/drop-terms.test.js.map +7 -0
- package/dist/empty-fields.test.js +1 -1
- package/dist/empty-fields.test.js.map +1 -1
- package/dist/ending-punctuation.test.js +39 -19
- package/dist/ending-punctuation.test.js.map +2 -2
- package/dist/field-008-18-34-character-groups.test.js +2 -8
- package/dist/field-008-18-34-character-groups.test.js.map +2 -2
- package/dist/field-505-separators.test.js +1 -7
- package/dist/field-505-separators.test.js.map +2 -2
- package/dist/field-521-fix.test.js +1 -7
- package/dist/field-521-fix.test.js.map +2 -2
- package/dist/field-exclusion.test.js +11 -8
- package/dist/field-exclusion.test.js.map +2 -2
- package/dist/field-structure.test.js +1 -1
- package/dist/field-structure.test.js.map +1 -1
- package/dist/fields-present.test.js +1 -1
- package/dist/fields-present.test.js.map +1 -1
- package/dist/fix-33X.test.js +1 -1
- package/dist/fix-33X.test.js.map +1 -1
- package/dist/fix-country-codes.test.js +1 -7
- package/dist/fix-country-codes.test.js.map +2 -2
- package/dist/fix-sami-041.js +87 -0
- package/dist/fix-sami-041.js.map +7 -0
- package/dist/fix-sami-041.test.js +40 -0
- package/dist/fix-sami-041.test.js.map +7 -0
- package/dist/fixRelatorTerms.test.js +2 -8
- package/dist/fixRelatorTerms.test.js.map +2 -2
- package/dist/fixed-fields.test.js +29 -18
- package/dist/fixed-fields.test.js.map +2 -2
- package/dist/identical-fields.test.js +1 -1
- package/dist/identical-fields.test.js.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +2 -2
- package/dist/indicator-fixes.js +10 -0
- package/dist/indicator-fixes.js.map +2 -2
- package/dist/indicator-fixes.test.js +1 -7
- package/dist/indicator-fixes.test.js.map +2 -2
- package/dist/isbn-issn.js +1 -1
- package/dist/isbn-issn.js.map +2 -2
- package/dist/isbn-issn.test.js +9 -6
- package/dist/isbn-issn.test.js.map +2 -2
- package/dist/item-language.test.js +1 -1
- package/dist/item-language.test.js.map +2 -2
- package/dist/merge-fields.test.js +2 -7
- package/dist/merge-fields.test.js.map +2 -2
- package/dist/mergeField500Lisapainokset.test.js +1 -7
- package/dist/mergeField500Lisapainokset.test.js.map +2 -2
- package/dist/mergeRelatorTermFields.test.js +1 -7
- package/dist/mergeRelatorTermFields.test.js.map +2 -2
- package/dist/multiple-subfield-0.test.js +1 -7
- package/dist/multiple-subfield-0.test.js.map +2 -2
- package/dist/normalize-dashes.test.js +1 -7
- package/dist/normalize-dashes.test.js.map +2 -2
- package/dist/normalize-identifiers.test.js +1 -7
- package/dist/normalize-identifiers.test.js.map +2 -2
- package/dist/normalize-qualifying-information.test.js +1 -7
- package/dist/normalize-qualifying-information.test.js.map +2 -2
- package/dist/normalize-utf8-diacritics.test.js +1 -7
- package/dist/normalize-utf8-diacritics.test.js.map +2 -2
- package/dist/normalizeFieldForComparison.js +24 -0
- package/dist/normalizeFieldForComparison.js.map +2 -2
- package/dist/punctuation.test.js +1 -7
- package/dist/punctuation.test.js.map +2 -2
- package/dist/punctuation2.test.js +2 -8
- package/dist/punctuation2.test.js.map +2 -2
- package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
- package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
- package/dist/remove-041-zxx.js +56 -0
- package/dist/remove-041-zxx.js.map +7 -0
- package/dist/remove-041-zxx.test.js +40 -0
- package/dist/remove-041-zxx.test.js.map +7 -0
- package/dist/removeDuplicateDataFields.test.js +2 -8
- package/dist/removeDuplicateDataFields.test.js.map +2 -2
- package/dist/removeInferiorDataFields.js +1 -9
- package/dist/removeInferiorDataFields.js.map +2 -2
- package/dist/removeInferiorDataFields.test.js +1 -7
- package/dist/removeInferiorDataFields.test.js.map +2 -2
- package/dist/resolvable-ext-references-melinda.test.js +1 -1
- package/dist/resolvable-ext-references-melinda.test.js.map +2 -2
- package/dist/resolveOrphanedSubfield6s.js +1 -3
- package/dist/resolveOrphanedSubfield6s.js.map +2 -2
- package/dist/resolveOrphanedSubfield6s.test.js +1 -7
- package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
- package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
- package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
- package/dist/sort-tags.test.js +1 -1
- package/dist/sort-tags.test.js.map +1 -1
- package/dist/sortFields.js +16 -1
- package/dist/sortFields.js.map +2 -2
- package/dist/sortFields.test.js +1 -7
- package/dist/sortFields.test.js.map +2 -2
- package/dist/sortRelatorTerms.test.js +1 -7
- package/dist/sortRelatorTerms.test.js.map +2 -2
- package/dist/sortSubfields.js +3 -1
- package/dist/sortSubfields.js.map +2 -2
- package/dist/sortSubfields.test.js +1 -7
- package/dist/sortSubfields.test.js.map +2 -2
- package/dist/stripPunctuation.js +7 -4
- package/dist/stripPunctuation.js.map +2 -2
- package/dist/stripPunctuation.test.js +1 -7
- package/dist/stripPunctuation.test.js.map +2 -2
- package/dist/subfield-exclusion.test.js +1 -1
- package/dist/subfield-exclusion.test.js.map +1 -1
- package/dist/subfield6Utils.js +1 -13
- package/dist/subfield6Utils.js.map +2 -2
- package/dist/subfieldValueNormalizations.test.js +1 -7
- package/dist/subfieldValueNormalizations.test.js.map +2 -2
- package/dist/sync-007-and-300.test.js +1 -7
- package/dist/sync-007-and-300.test.js.map +2 -2
- package/dist/sync-language.js +103 -0
- package/dist/sync-language.js.map +7 -0
- package/dist/sync-language.test.js +40 -0
- package/dist/sync-language.test.js.map +7 -0
- package/dist/translate-terms.js +121 -85
- package/dist/translate-terms.js.map +3 -3
- package/dist/translate-terms.test.js +5 -8
- package/dist/translate-terms.test.js.map +2 -2
- package/dist/unicode-decomposition.test.js +1 -1
- package/dist/unicode-decomposition.test.js.map +1 -1
- package/dist/update-field-540.test.js +2 -8
- package/dist/update-field-540.test.js.map +2 -2
- package/dist/urn.test.js +2 -8
- package/dist/urn.test.js.map +2 -2
- package/package.json +18 -16
- package/src/access-rights.test.js +1 -1
- package/src/addMissingField337.test.js +1 -1
- package/src/addMissingField338.test.js +1 -1
- package/src/cyrillux-usemarcon-replacement.test.js +4 -9
- package/src/cyrillux.test.js +1 -1
- package/src/disambiguateSeriesStatements.test.js +3 -8
- package/src/double-commas.test.js +1 -1
- package/src/drop-terms.js +162 -0
- package/src/drop-terms.test.js +81 -0
- package/src/empty-fields.test.js +1 -1
- package/src/ending-punctuation.test.js +28 -20
- package/src/field-008-18-34-character-groups.test.js +4 -9
- package/src/field-505-separators.test.js +3 -8
- package/src/field-521-fix.test.js +3 -8
- package/src/field-exclusion.test.js +10 -8
- package/src/field-structure.test.js +1 -1
- package/src/fields-present.test.js +1 -1
- package/src/fix-33X.test.js +1 -1
- package/src/fix-country-codes.test.js +3 -8
- package/src/fix-sami-041.js +113 -0
- package/src/fix-sami-041.test.js +52 -0
- package/src/fixRelatorTerms.test.js +4 -9
- package/src/fixed-fields.test.js +24 -18
- package/src/identical-fields.test.js +1 -1
- package/src/index.js +8 -1
- package/src/indicator-fixes.js +12 -0
- package/src/indicator-fixes.test.js +3 -8
- package/src/isbn-issn.js +1 -1
- package/src/isbn-issn.test.js +8 -6
- package/src/item-language.test.js +2 -2
- package/src/merge-fields.test.js +3 -8
- package/src/mergeField500Lisapainokset.test.js +3 -8
- package/src/mergeRelatorTermFields.test.js +3 -8
- package/src/multiple-subfield-0.test.js +3 -8
- package/src/normalize-dashes.test.js +3 -8
- package/src/normalize-identifiers.test.js +3 -8
- package/src/normalize-qualifying-information.test.js +3 -8
- package/src/normalize-utf8-diacritics.test.js +3 -8
- package/src/normalizeFieldForComparison.js +26 -0
- package/src/punctuation.test.js +3 -8
- package/src/punctuation2.test.js +4 -9
- package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
- package/src/remove-041-zxx.js +85 -0
- package/src/remove-041-zxx.test.js +52 -0
- package/src/removeDuplicateDataFields.test.js +4 -9
- package/src/removeInferiorDataFields.js +7 -7
- package/src/removeInferiorDataFields.test.js +3 -8
- package/src/resolvable-ext-references-melinda.test.js +5 -5
- package/src/resolveOrphanedSubfield6s.js +3 -3
- package/src/resolveOrphanedSubfield6s.test.js +3 -8
- package/src/sanitize-vocabulary-source-codes.test.js +3 -8
- package/src/sort-tags.test.js +1 -1
- package/src/sortFields.js +20 -1
- package/src/sortFields.test.js +3 -8
- package/src/sortRelatorTerms.test.js +3 -8
- package/src/sortSubfields.js +3 -1
- package/src/sortSubfields.test.js +3 -8
- package/src/stripPunctuation.js +9 -6
- package/src/stripPunctuation.test.js +3 -8
- package/src/subfield-exclusion.test.js +1 -1
- package/src/subfield6Utils.js +13 -13
- package/src/subfieldValueNormalizations.test.js +3 -8
- package/src/sync-007-and-300.test.js +3 -8
- package/src/sync-language.js +148 -0
- package/src/sync-language.test.js +52 -0
- package/src/translate-terms.js +158 -103
- package/src/translate-terms.test.js +12 -16
- package/src/unicode-decomposition.test.js +1 -1
- package/src/update-field-540.test.js +4 -9
- package/src/urn.test.js +4 -9
- package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
- package/test-fixtures/drop-terms/01/metadata.json +6 -0
- package/test-fixtures/drop-terms/01/record.json +35 -0
- package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
- package/test-fixtures/drop-terms/02/metadata.json +6 -0
- package/test-fixtures/drop-terms/02/record.json +40 -0
- package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
- package/test-fixtures/drop-terms/03/metadata.json +18 -0
- package/test-fixtures/drop-terms/03/record.json +39 -0
- package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
- package/test-fixtures/drop-terms/04/metadata.json +19 -0
- package/test-fixtures/drop-terms/04/record.json +24 -0
- package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
- package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
- package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/01/record.json +13 -0
- package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
- package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/02/record.json +8 -0
- package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
- package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
- package/test-fixtures/fix-sami-041/03/record.json +8 -0
- package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
- package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
- package/test-fixtures/fix-sami-041/04/record.json +10 -0
- package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
- package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
- package/test-fixtures/fix-sami-041/05/record.json +8 -0
- package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
- package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
- package/test-fixtures/indicator-fixes/11/record.json +10 -0
- package/test-fixtures/merge-fields/f05/metadata.json +1 -1
- package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
- package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/01/record.json +10 -0
- package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
- package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/02/record.json +9 -0
- package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
- package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/11/record.json +9 -0
- package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
- package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
- package/test-fixtures/remove-041-zxx/12/record.json +9 -0
- package/test-fixtures/sort-fields/15/input.json +9 -0
- package/test-fixtures/sort-fields/15/metadata.json +5 -0
- package/test-fixtures/sort-fields/15/result.json +10 -0
- package/test-fixtures/sync-language/01/expectedResult.json +5 -0
- package/test-fixtures/sync-language/01/metadata.json +5 -0
- package/test-fixtures/sync-language/01/record.json +7 -0
- package/test-fixtures/sync-language/02/expectedResult.json +6 -0
- package/test-fixtures/sync-language/02/metadata.json +5 -0
- package/test-fixtures/sync-language/02/record.json +10 -0
- package/test-fixtures/sync-language/03/expectedResult.json +6 -0
- package/test-fixtures/sync-language/03/metadata.json +5 -0
- package/test-fixtures/sync-language/03/record.json +6 -0
- package/test-fixtures/sync-language/10/expectedResult.json +10 -0
- package/test-fixtures/sync-language/10/metadata.json +5 -0
- package/test-fixtures/sync-language/10/record.json +8 -0
- package/test-fixtures/sync-language/11/expectedResult.json +10 -0
- package/test-fixtures/sync-language/11/metadata.json +5 -0
- package/test-fixtures/sync-language/11/record.json +7 -0
- package/test-fixtures/sync-language/12/expectedResult.json +9 -0
- package/test-fixtures/sync-language/12/metadata.json +6 -0
- package/test-fixtures/sync-language/12/record.json +6 -0
- package/test-fixtures/sync-language/13/expectedResult.json +10 -0
- package/test-fixtures/sync-language/13/metadata.json +5 -0
- package/test-fixtures/sync-language/13/record.json +8 -0
- package/test-fixtures/sync-language/14/expectedResult.json +9 -0
- package/test-fixtures/sync-language/14/metadata.json +5 -0
- package/test-fixtures/sync-language/14/record.json +7 -0
- package/test-fixtures/sync-language/15/expectedResult.json +9 -0
- package/test-fixtures/sync-language/15/metadata.json +5 -0
- package/test-fixtures/sync-language/15/record.json +7 -0
- package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
- package/test-fixtures/translate-terms/05/metadata.json +7 -0
- package/test-fixtures/translate-terms/05/record.json +11 -0
- package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
- package/test-fixtures/translate-terms/06/metadata.json +7 -0
- package/test-fixtures/translate-terms/06/record.json +11 -0
- package/test-fixtures/translate-terms-data.js +23 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/stripPunctuation.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './stripPunctuation.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './stripPunctuation.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'strip-punctuation'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/stripPunctuation: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.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\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
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,mBAAmB;AAAA,EACtE,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;AAID,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,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,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,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { MarcRecord } from "@natlibfi/marc-record";
|
|
3
|
-
import validatorFactory from "
|
|
3
|
+
import validatorFactory from "./subfield-exclusion.js";
|
|
4
4
|
import { describe, it } from "node:test";
|
|
5
5
|
describe("subfield-exclusion", () => {
|
|
6
6
|
describe("#validate: Check configuration validation", () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/subfield-exclusion.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from '../src/subfield-exclusion.js';\nimport {describe, it} from 'node:test';\n\n//chai.use(chaiAsPromised);\n\n// Factory validation\ndescribe('subfield-exclusion', () => {\n describe('#validate: Check configuration validation', () => {\n it('Creates a validator from simple config', async () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: /4/u}]\n }\n ];\n\n const validator = await validatorFactory(config);\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n it('Creates a validator from complex config', async () => {\n const config = [\n {\n tag: /^210$/u,\n ind2: /\\s/u,\n subfields: [\n {\n code: /2/u,\n value: /.+/u\n }\n ]\n }\n ];\n\n const validator = await validatorFactory(config);\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n it('Fails to create a validator from invalid config - subfields missing', () => {\n const config = [\n {\n tag: /^210$/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 - missing mandatory element: subfields');\n }\n });\n\n it('Fails to create a validator from invalid config - tag', () => {\n const config = [\n {\n tag: '500',\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/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 - invalid data type for: tag');\n }\n });\n\n it('Fails to create a validator from invalid config - missing array', () => {\n const config = {\n tag: '500',\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/u}]\n };\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration array not provided');\n }\n });\n\n it('Fails to create a validator from invalid config - code', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: 9, value: /^(?!FENNI<KEEP>).*$/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 - invalid data type for: code');\n }\n });\n\n it('Fails to create a validator from invalid config - value', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: /9/u, value: 'Fenni'}]\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: value');\n }\n });\n\n\n it('Fails to create a validator from invalid config - missing mandatory: tag', () => {\n const config = [\n {\n value: /^500$/u,\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/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 - missing mandatory element: tag');\n }\n });\n\n it('Fails to create a validator from invalid config - subfield not object: array', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n ['/9/', '/^(?!FENNI<KEEP>).*$/'],\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - subfield: /9/,/^(?!FENNI<KEEP>).*$/ not object');\n }\n });\n\n it('Fails to create a validator from invalid config - subfield not object: string', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n '/9/',\n '/^(?!FENNI<KEEP>).*$/',\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - subfield: /9/ not object');\n }\n });\n\n it('Fails to create a validator from invalid config - missing mandatory: subfield.code', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n {code: /9/u, value: /^(?!FENNI<KEEP>).*$/u},\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - missing mandatory element: code');\n }\n });\n\n it('Fails to create a validator from invalid config - unidentified field: unidentified', () => {\n const config = [\n {\n tag: /^500$/u,\n unidentified: /^500$/u,\n subfields: [\n {code: /9/u, value: /^(?!FENNI<KEEP>).*$/u},\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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: unidentified');\n //assert(error).to.be.an('error').with.property('message', 'Configuration not valid - unidentified value: unidentified');\n }\n });\n });\n\n // Simple configuration https://github.com/NatLibFi/marc-record-validators-melinda/issues/46\n describe('#validate: Simple configuration (spec)', () => {\n const config = [\n {\n tag: /^100$/u,\n subfields: [{code: /4/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo Bar'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {code: 'a', value: 'Foo Bar'},\n {code: '4', value: 'att'}\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo Bar'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record valid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $100$$4should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordInvalid);\n //assert(recordInvalid.equalsTo(recordInvalidFixed)).to.eql(true);\n assert(recordInvalid.equalsTo(recordInvalidFixed), true);\n });\n });\n\n\n describe('#validate: Remove only subfield -> remove field as well', () => {\n const config = [\n {\n tag: /^041$/u,\n subfields: [{code: /^[ad]$/u, value: /^zxx$/u}]\n }\n ];\n\n const recordOriginal = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '041',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'zxx'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordModified = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record with 041$a zxx invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordOriginal);\n assert.deepEqual(result, {valid: false, message: ['Subfield $041$$ashould be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordOriginal);\n //assert(recordOriginal.equalsTo(recordModified)).to.eql(true);\n assert.equal(recordOriginal.equalsTo(recordModified), true);\n });\n });\n\n // Complex configuration https://github.com/NatLibFi/marc-record-validators-melinda/issues/46\n describe('#validate: Complex configuration (spec)', () => {\n const config = [\n {\n tag: /^210$/u,\n ind2: /\\s/u,\n subfields: [{code: /2/u, value: /.+/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record valid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $210$$2should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordInvalid);\n // assert(recordInvalid.equalsTo(recordInvalidFixed)).to.eql(true);\n assert.equal(recordInvalid.equalsTo(recordInvalidFixed), true);\n });\n });\n\n // More special cases to increase coverage\n describe('#validate: Custom configuration', () => {\n const configInd = [\n {\n tag: /^500$/u,\n ind1: /^8$/u,\n ind2: /^4$/u,\n subfields: [{code: /2/u, value: /.+/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '500',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }\n ]\n });\n\n const recordIndInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }, {\n tag: '500',\n ind1: '8',\n ind2: '4',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }\n ]\n });\n\n const recordIndInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }, {\n tag: '500',\n ind1: '8',\n ind2: '4',\n subfields: [{code: 'a', value: 'Foo'}]\n }\n ]\n });\n\n it('Finds the record valid - Ind1&Ind2', async () => {\n const validator = await validatorFactory(configInd);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid - Ind', async () => {\n const validator = await validatorFactory(configInd);\n const result = await validator.validate(recordIndInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $500$$2should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(configInd);\n await validator.fix(recordIndInvalid);\n // assert(recordIndInvalid.equalsTo(recordIndInvalidFixed)).to.eql(true);\n assert.equal(recordIndInvalid.equalsTo(recordIndInvalidFixed), true);\n });\n });\n});\n"],
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './subfield-exclusion.js';\nimport {describe, it} from 'node:test';\n\n//chai.use(chaiAsPromised);\n\n// Factory validation\ndescribe('subfield-exclusion', () => {\n describe('#validate: Check configuration validation', () => {\n it('Creates a validator from simple config', async () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: /4/u}]\n }\n ];\n\n const validator = await validatorFactory(config);\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n it('Creates a validator from complex config', async () => {\n const config = [\n {\n tag: /^210$/u,\n ind2: /\\s/u,\n subfields: [\n {\n code: /2/u,\n value: /.+/u\n }\n ]\n }\n ];\n\n const validator = await validatorFactory(config);\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n });\n\n it('Fails to create a validator from invalid config - subfields missing', () => {\n const config = [\n {\n tag: /^210$/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 - missing mandatory element: subfields');\n }\n });\n\n it('Fails to create a validator from invalid config - tag', () => {\n const config = [\n {\n tag: '500',\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/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 - invalid data type for: tag');\n }\n });\n\n it('Fails to create a validator from invalid config - missing array', () => {\n const config = {\n tag: '500',\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/u}]\n };\n\n try {\n validatorFactory(config);\n } catch (error) {\n assert.equal(error instanceof Error, true);\n assert.equal(error.message, 'Configuration array not provided');\n }\n });\n\n it('Fails to create a validator from invalid config - code', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: 9, value: /^(?!FENNI<KEEP>).*$/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 - invalid data type for: code');\n }\n });\n\n it('Fails to create a validator from invalid config - value', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [{code: /9/u, value: 'Fenni'}]\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: value');\n }\n });\n\n\n it('Fails to create a validator from invalid config - missing mandatory: tag', () => {\n const config = [\n {\n value: /^500$/u,\n subfields: [{code: /9/u, value: /^(?!FENNI<KEEP>).*$/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 - missing mandatory element: tag');\n }\n });\n\n it('Fails to create a validator from invalid config - subfield not object: array', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n ['/9/', '/^(?!FENNI<KEEP>).*$/'],\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - subfield: /9/,/^(?!FENNI<KEEP>).*$/ not object');\n }\n });\n\n it('Fails to create a validator from invalid config - subfield not object: string', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n '/9/',\n '/^(?!FENNI<KEEP>).*$/',\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - subfield: /9/ not object');\n }\n });\n\n it('Fails to create a validator from invalid config - missing mandatory: subfield.code', () => {\n const config = [\n {\n tag: /^500$/u,\n subfields: [\n {code: /9/u, value: /^(?!FENNI<KEEP>).*$/u},\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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 - missing mandatory element: code');\n }\n });\n\n it('Fails to create a validator from invalid config - unidentified field: unidentified', () => {\n const config = [\n {\n tag: /^500$/u,\n unidentified: /^500$/u,\n subfields: [\n {code: /9/u, value: /^(?!FENNI<KEEP>).*$/u},\n {value: /^(?!FENNI<KEEP>).*$/u}\n ]\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: unidentified');\n //assert(error).to.be.an('error').with.property('message', 'Configuration not valid - unidentified value: unidentified');\n }\n });\n });\n\n // Simple configuration https://github.com/NatLibFi/marc-record-validators-melinda/issues/46\n describe('#validate: Simple configuration (spec)', () => {\n const config = [\n {\n tag: /^100$/u,\n subfields: [{code: /4/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo Bar'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {code: 'a', value: 'Foo Bar'},\n {code: '4', value: 'att'}\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '100',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo Bar'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record valid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $100$$4should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordInvalid);\n //assert(recordInvalid.equalsTo(recordInvalidFixed)).to.eql(true);\n assert(recordInvalid.equalsTo(recordInvalidFixed), true);\n });\n });\n\n\n describe('#validate: Remove only subfield -> remove field as well', () => {\n const config = [\n {\n tag: /^041$/u,\n subfields: [{code: /^[ad]$/u, value: /^zxx$/u}]\n }\n ];\n\n const recordOriginal = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '041',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'zxx'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordModified = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record with 041$a zxx invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordOriginal);\n assert.deepEqual(result, {valid: false, message: ['Subfield $041$$ashould be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordOriginal);\n //assert(recordOriginal.equalsTo(recordModified)).to.eql(true);\n assert.equal(recordOriginal.equalsTo(recordModified), true);\n });\n });\n\n // Complex configuration https://github.com/NatLibFi/marc-record-validators-melinda/issues/46\n describe('#validate: Complex configuration (spec)', () => {\n const config = [\n {\n tag: /^210$/u,\n ind2: /\\s/u,\n subfields: [{code: /2/u, value: /.+/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n const recordInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }\n ]\n });\n\n it('Finds the record valid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid (spec)', async () => {\n const validator = await validatorFactory(config);\n const result = await validator.validate(recordInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $210$$2should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(config);\n await validator.fix(recordInvalid);\n // assert(recordInvalid.equalsTo(recordInvalidFixed)).to.eql(true);\n assert.equal(recordInvalid.equalsTo(recordInvalidFixed), true);\n });\n });\n\n // More special cases to increase coverage\n describe('#validate: Custom configuration', () => {\n const configInd = [\n {\n tag: /^500$/u,\n ind1: /^8$/u,\n ind2: /^4$/u,\n subfields: [{code: /2/u, value: /.+/u}]\n }\n ];\n\n const recordValid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '210',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Foo'}]\n }, {\n tag: '500',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }\n ]\n });\n\n const recordIndInvalid = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }, {\n tag: '500',\n ind1: '8',\n ind2: '4',\n subfields: [\n {code: 'a', value: 'Foo'},\n {code: '2', value: 'dnlm'}\n ]\n }\n ]\n });\n\n const recordIndInvalidFixed = new MarcRecord({\n leader: 'foo',\n fields: [\n {\n tag: '245',\n ind1: ' ',\n ind2: ' ',\n subfields: [{code: 'a', value: 'Fubar'}]\n }, {\n tag: '500',\n ind1: '8',\n ind2: '4',\n subfields: [{code: 'a', value: 'Foo'}]\n }\n ]\n });\n\n it('Finds the record valid - Ind1&Ind2', async () => {\n const validator = await validatorFactory(configInd);\n const result = await validator.validate(recordValid);\n assert.deepEqual(result, {valid: true, message: []});\n });\n\n it('Finds the record invalid - Ind', async () => {\n const validator = await validatorFactory(configInd);\n const result = await validator.validate(recordIndInvalid);\n assert.deepEqual(result, {valid: false, message: ['Subfield $500$$2should be excluded']});\n });\n\n it('Repairs invalid record', async () => {\n const validator = await validatorFactory(configInd);\n await validator.fix(recordIndInvalid);\n // assert(recordIndInvalid.equalsTo(recordIndInvalidFixed)).to.eql(true);\n assert.equal(recordIndInvalid.equalsTo(recordIndInvalidFixed), true);\n });\n });\n});\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/subfield6Utils.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import createDebugLogger from "debug";
|
|
2
1
|
import { add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8 } from "./subfield8Utils.js";
|
|
3
|
-
import { fieldHasSubfield, fieldToString,
|
|
4
|
-
const debug = createDebugLogger("@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils");
|
|
5
|
-
const debugDev = debug.extend("dev");
|
|
2
|
+
import { fieldHasSubfield, fieldToString, nvdebug, subfieldToString } from "./utils.js";
|
|
6
3
|
const sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;
|
|
7
4
|
export function isValidSubfield6(subfield) {
|
|
8
5
|
if (subfield.code !== "6") {
|
|
@@ -49,7 +46,6 @@ export function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurre
|
|
|
49
46
|
return false;
|
|
50
47
|
}
|
|
51
48
|
const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, "$1");
|
|
52
|
-
nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);
|
|
53
49
|
return key === tagAndOccurrenceNumber;
|
|
54
50
|
}
|
|
55
51
|
export function fieldGetUnambiguousTag(field) {
|
|
@@ -145,7 +141,6 @@ export function fieldGetOccurrenceNumberPairs(field, candFields) {
|
|
|
145
141
|
nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);
|
|
146
142
|
return pairs;
|
|
147
143
|
}
|
|
148
|
-
nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);
|
|
149
144
|
pairs.forEach((pairedField) => nvdebug(` '${fieldToString(pairedField)}'`));
|
|
150
145
|
return pairs;
|
|
151
146
|
}
|
|
@@ -221,7 +216,6 @@ function guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {
|
|
|
221
216
|
}
|
|
222
217
|
export function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag2 = false) {
|
|
223
218
|
const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);
|
|
224
|
-
nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);
|
|
225
219
|
const strings = fields.map((field) => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag2));
|
|
226
220
|
strings.sort();
|
|
227
221
|
return strings.join(" __SEPARATOR__ ");
|
|
@@ -270,7 +264,6 @@ export function isFirstLinkedSubfield6Field(field, record) {
|
|
|
270
264
|
}
|
|
271
265
|
const chain = getAllLinkedSubfield6Fields(field, record);
|
|
272
266
|
if (!isRelevantSubfield6Chain(chain)) {
|
|
273
|
-
nvdebug(`Rejected 6: ${fieldsToString(chain)}`);
|
|
274
267
|
return false;
|
|
275
268
|
}
|
|
276
269
|
return fieldIsFirstFieldInChain(field, chain, record);
|
|
@@ -290,12 +283,8 @@ export function get6s(field, candidateFields) {
|
|
|
290
283
|
if (sixes.length === 0) {
|
|
291
284
|
return [field];
|
|
292
285
|
}
|
|
293
|
-
nvdebug(`SIXES: ${sixes.length}`);
|
|
294
286
|
const occurrenceNumbers = sixes.map((sf) => subfield6GetOccurrenceNumber(sf)).filter((value) => value !== void 0 && value !== "00");
|
|
295
|
-
nvdebug(occurrenceNumbers.join(" -- "));
|
|
296
287
|
const relevantFields = candidateFields.filter((f) => occurrenceNumbers.some((o) => fieldHasOccurrenceNumber(f, o)));
|
|
297
|
-
nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);
|
|
298
|
-
relevantFields.forEach((f) => nvdebug(fieldToString(f)));
|
|
299
288
|
return relevantFields;
|
|
300
289
|
}
|
|
301
290
|
export function resetSubfield6Tag(subfield, tag) {
|
|
@@ -303,7 +292,6 @@ export function resetSubfield6Tag(subfield, tag) {
|
|
|
303
292
|
return;
|
|
304
293
|
}
|
|
305
294
|
const newValue = `${tag}-${subfield.value.substring(4)}`;
|
|
306
|
-
nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);
|
|
307
295
|
subfield.value = newValue;
|
|
308
296
|
}
|
|
309
297
|
//# sourceMappingURL=subfield6Utils.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/subfield6Utils.js"],
|
|
4
|
-
"sourcesContent": ["import createDebugLogger from 'debug';\n// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');\n\nimport {add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils.js';\nimport {fieldHasSubfield, fieldToString, fieldsToString, nvdebug, subfieldToString} from './utils.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n// NB! Subfield 6 is non-repeatable and it should always comes first!\n// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.\n// NB! Index value '00' are left as they are (is not paired/indexed/whatever.\nconst sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;\n\nexport function isValidSubfield6(subfield) {\n if (subfield.code !== '6') {\n return false;\n }\n return subfield.value.match(sf6Regexp);\n}\n\nexport function subfield6GetTag(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumber(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumberAsInteger(subfield) {\n const index = subfield6GetOccurrenceNumber(subfield);\n if (index === undefined || index === '00') {\n return 0;\n }\n const result = parseInt(index, 10);\n //nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debug);\n return result;\n}\n\nexport function subfield6ResetOccurrenceNumber(subfield, occurrenceNumber) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;\n\n const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield);\n //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue;\n}\n\n\nfunction subfield6GetTail(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.replace(/^\\d+-\\d+/u, '');\n }\n return '';\n}\n\nexport function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurrenceNumber) {\n if (subfield.code !== '6') {\n return false;\n }\n // We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...\n const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1');\n nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);\n return key === tagAndOccurrenceNumber;\n}\n\n// <= SUBFIELD, FIELD =>\n\nexport function fieldGetUnambiguousTag(field) {\n const tags = field.subfields.filter(sf => subfield6GetTag(sf));\n if (tags.length === 1) {\n return subfield6GetTag(tags[0]);\n }\n return undefined;\n}\n\nexport function fieldGetUnambiguousOccurrenceNumber(field) {\n const occurrenceNumbers = field.subfields.filter(sf => subfield6GetOccurrenceNumber(sf));\n if (occurrenceNumbers.length === 1) {\n return subfield6GetOccurrenceNumber(occurrenceNumbers[0]);\n }\n return undefined;\n}\n\nexport function fieldHasOccurrenceNumber(field, occurrenceNumber) {\n //nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`);\n return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);\n}\n\nexport function fieldResetOccurrenceNumber(field, newOccurrenceNumber, oldOccurrenceNumber = undefined) {\n field.subfields.forEach(subfield => innerReset(subfield));\n\n function innerReset(subfield) {\n // (Optional) Check that this is really the occurrence number we wan't to reseot\n if (oldOccurrenceNumber !== undefined) {\n const currOccurrenceNumber = subfield6GetOccurrenceNumber(subfield);\n if (currOccurrenceNumber !== oldOccurrenceNumber) {\n return;\n }\n }\n subfield6ResetOccurrenceNumber(subfield, newOccurrenceNumber);\n }\n}\n\nexport function intToOccurrenceNumberString(i) {\n return i < 10 ? `0${i}` : `${i}`;\n}\n\nexport function fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {\n // used by reducer!\n //nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`);\n const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];\n if (sf6s.length === 0) {\n return 0;\n }\n // There should always be one, but here we check every subfield.\n //nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debug);\n const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));\n return Math.max(...vals);\n}\n\nexport function fieldHasWantedTagAndOccurrenceNumber(field, tagAndOccurrenceNumber) {\n return field.subfields && field.subfields.some(sf => subfield6HasWantedTagAndOccurrenceNumber(sf, tagAndOccurrenceNumber));\n}\n\n\n/*\nexport function getFieldsWithGivenOccurrenceNumberSubfield6(record, occurrenceNumberAsString) {\n const record.fields.filter(field => field\n\n function fieldHasIndex(field, index) {\n if (!field.subfields) {\n return false;\n }\n return field.subfields.find(sf => isValidSubfield6(sf) && subfieldGetOccurrenceNumber6(sf) === index);\n }\n}\n*/\n\n\nexport function fieldHasValidSubfield6(field) {\n return field.subfields && field.subfields.some(sf => isValidSubfield6(sf));\n}\n\nexport function isSubfield6Pair(field, otherField) {\n // No need to log this:\n //nvdebug(`LOOK for $6-pair:\\n ${fieldToString(field)}\\n ${fieldToString(otherField)}`);\n if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {\n return false;\n }\n\n if (!tagsArePairable6(field.tag, otherField.tag)) {\n //nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`);\n return false;\n }\n\n\n const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);\n if (fieldIndex === undefined || fieldIndex === '00') {\n //nvdebug(` FAILED. REASON: NO INDEX FOUND`);\n return false;\n }\n\n const otherFieldIndex = fieldGetUnambiguousOccurrenceNumber(otherField);\n\n\n if (fieldIndex !== otherFieldIndex) {\n //nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`);\n return false;\n }\n\n if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {\n //nvdebug(` FAILURE: TAG vs $6 TAG`);\n return false;\n }\n return true;\n\n function tagsArePairable6(tag1, tag2) {\n // How to do XOR operation in one line? Well, this is probably more readable...\n if (tag1 === '880' && tag2 === '880') {\n return false;\n }\n if (tag1 !== '880' && tag2 !== '880') {\n return false;\n }\n return true;\n }\n}\n\n\nfunction subfieldSevenToOneOccurrenceNumber(subfield) {\n if (subfield.code !== '6' || subfield.value.substring(0, 1) !== '7') {\n return;\n }\n subfield.value = `1${subfield.value.substring(1)}`;\n}\n\nexport function fieldSevenToOneOccurrenceNumber(field) {\n if (field.tag !== '880') {\n return;\n }\n field.subfields.forEach(sf => subfieldSevenToOneOccurrenceNumber(sf));\n}\n\n\nexport function fieldGetOccurrenceNumberPairs(field, candFields) {\n // NB! TAG!=880 returns 880 fields, TAG==880 returns non-880 field\n //nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);\n const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairs.length === 0) {\n nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);\n return pairs;\n }\n nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);\n pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));\n return pairs;\n}\n\nexport function fieldGetOccurrenceNumbers(field) {\n let occurrenceNumbers = [];\n field.subfields?.forEach(sf => subfieldExtractOccurrenceNumber(sf));\n\n function subfieldExtractOccurrenceNumber(sf) {\n if (!isValidSubfield6(sf)) {\n return;\n }\n const occurrenceNumber = subfield6GetOccurrenceNumber(sf);\n if (occurrenceNumber === '00' || occurrenceNumbers.includes(occurrenceNumber)) {\n return;\n }\n occurrenceNumbers.push(occurrenceNumber);\n }\n return occurrenceNumbers;\n}\n\nexport function fieldsGetOccurrenceNumbers(fields) {\n let occurrenceNumbers = [];\n\n fields.forEach(f => fieldProcessOccurrenceNumbers(f));\n\n function fieldProcessOccurrenceNumbers(f) {\n const newOccurrenceNumbers = fieldGetOccurrenceNumbers(f);\n newOccurrenceNumbers.forEach(occurrenceNumber => {\n if (!occurrenceNumbers.includes(occurrenceNumber)) {\n occurrenceNumbers.push(occurrenceNumber);\n }\n\n });\n }\n return occurrenceNumbers;\n}\n\n/*\nexport function fieldGetSubfield6Pair(field, record) {\n const pairedFields = record.fields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairedFields.length !== 1) {\n return undefined;\n }\n // NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)\n nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`);\n return pairedFields[0];\n}\n*/\n\n/*\nexport function pairAndStringify6(field, record) {\n const pair6 = fieldGetSubfield6Pair(field, record);\n if (!pair6) {\n return fieldToNormalizedString(field);\n }\n return fieldsToNormalizedString([field, pair6]);\n}\n*/\n\n// Frequencly list for $6 subfields in 1XX/7XX fields:\n// 231115 100\n// 183832 700\n// 28773 710\n// 2047 711\n// 661 110\n// 341 111\n// 284 130\n// 63 730\n// Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.\n// Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:\n\nexport function is7XX(tag) {\n return ['700', '710', '711', '730'].includes(tag);\n}\n\n\nfunction normalizeEntryTag(tag) {\n if (tag.match(/^[17](?:00|10|11|30)$/u)) {\n return `X${tag.substring(1)}`;\n }\n return tag;\n}\n\nfunction subfieldToNormalizedString(sf, tag, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {\n // targetLinkingNumber refers to $8.\n // normalizeEntryTagBoolean refers to 1XX/7XX tag values in subfield $6 value.\n if (isValidSubfield6(sf)) { // && targetLinkingNumber === 0) {\n // 1XX/7XX (entry tag) normalization:\n const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(tag) : tag;\n\n const occurrenceNumber = normalizeOccurrenceNumber ? 'XX' : subfield6GetOccurrenceNumber(sf);\n // If we are normalizing a $8 chain, don't normalize $6 occurrence number!\n // Replace $6 occurrence number with XX:\n return ` \u2021${sf.code} ${tag2}-${occurrenceNumber}${subfield6GetTail(sf)}`;\n }\n\n if (isValidSubfield8(sf)) {\n const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);\n if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {\n // For $8 we should only XX the index we are looking at...\n const normVal = sf.value.replace(/^[0-9]+/u, 'XX');\n return ` \u2021${sf.code} ${normVal}`;\n }\n return ''; // Other $8 subfields are meaningless in this context\n }\n return ` ${subfieldToString(sf)}`; // `\u2021${sf.code} ${sf.value}`;\n}\n\nexport function fieldToNormalizedString(field, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {\n if ('subfields' in field) {\n const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(field.tag) : field.tag;\n return `${tag2} ${field.ind1}${field.ind2}${formatAndNormalizeSubfields(field)}`;\n }\n return `${field.tag} ${field.value}`;\n\n function formatAndNormalizeSubfields(field) {\n return field.subfields.map(sf => subfieldToNormalizedString(sf, field.tag, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTagBoolean)).join('');\n }\n\n}\n\n\nfunction guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {\n if (defaultTargetLinkingNumber !== 0) {\n return defaultTargetLinkingNumber;\n }\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);\n return linkingNumbers.length === 1 ? linkingNumbers[0] : 0;\n}\n\nexport function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag = false) {\n const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);\n\n nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);\n const strings = fields.map(field => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag));\n strings.sort();\n return strings.join('\\t__SEPARATOR__\\t');\n}\n\n\n/*\n\nexport function removeField6IfNeeded(field, record, fieldsAsString) {\n const pairField = fieldGetSubfield6Pair(field, record);\n const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);\n nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`);\n const tmp = pairField ? fieldToString(pairField) : 'HUTI';\n nvdebug(`PAIR: ${tmp}`);\n nvdebug(`BASE:\\n ${fieldsAsString.join('\\n ')}`);\n if (!fieldsAsString.includes(asString)) {\n return;\n }\n nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`);\n record.removeField(field);\n\n if (pairField === undefined) {\n return;\n }\n nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`);\n record.removeField(pairField);\n}\n*/\n\nfunction getFirstField(record, fields) {\n const fieldsAsStrings = fields.map(field => fieldToString(field));\n //record.fields.forEach((field, i) => nvdebug(`${i}:\\t${fieldToString(field)}`));\n //nvdebug(`getFirstField: ${fieldsAsStrings.join('\\t')}`);\n const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));\n if (i > -1) {\n const field = record.fields[i];\n //nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`);\n return field;\n }\n return undefined;\n}\n\nfunction isRelevantSubfield6Chain(fields) {\n if (fields.length < 2) { // 1 non-880-field and 1+ 880 fields\n return false;\n }\n const non880 = fields.filter(f => f.tag !== '880');\n if (non880.length !== 1) {\n return false;\n }\n\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);\n if (linkingNumbers.length !== 0) {\n return false;\n }\n\n return fields.every(f => fieldHasSubfield(f, '6'));\n}\n\nexport function fieldIsFirstFieldInChain(field, chain, record) {\n // Interpretation of first: position of field in record (however, we might have a duplicate field. See tests...)\n const firstField = getFirstField(record, chain);\n if (firstField) {\n return fieldToString(field) === fieldToString(firstField);\n }\n return false;\n\n}\n\n\nexport function getAllLinkedSubfield6Fields(field, record) {\n const fields = get6s(field, record);\n const moreFields = add8s(fields, record);\n\n // Currently we don't handle fields with more than one $6 and/or $8 subfield.\n if (moreFields.length > fields.length) {\n return []; // Don't fix!\n }\n return moreFields;\n}\n\nexport function isFirstLinkedSubfield6Field(field, record) {\n if (!field.subfields) { // Is not a datafield\n return false;\n }\n const chain = getAllLinkedSubfield6Fields(field, record);\n if (!isRelevantSubfield6Chain(chain)) {\n nvdebug(`Rejected 6: ${fieldsToString(chain)}`);\n return false;\n }\n\n return fieldIsFirstFieldInChain(field, chain, record);\n}\n\nexport function recordGetSubfield6ChainHeads(record) {\n return record.fields.filter(field => isFirstLinkedSubfield6Field(field, record));\n}\n\nexport function recordGetMaxSubfield6OccurrenceNumberAsInteger(record) {\n if (record.fields.length === 0) {\n return 0;\n }\n // Should we cache the value here?\n const vals = record.fields.map((field) => fieldGetMaxSubfield6OccurrenceNumberAsInteger(field));\n return Math.max(...vals);\n}\n\nexport function get6s(field, candidateFields) { // NB! Convert field to fields!!!\n // Get all fields with given occurrence number\n const sixes = field.subfields.filter(sf => isValidSubfield6(sf));\n\n if (sixes.length === 0) {\n return [field];\n }\n nvdebug(`SIXES: ${sixes.length}`);\n const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');\n nvdebug(occurrenceNumbers.join(' -- '));\n\n const relevantFields = candidateFields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));\n nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);\n relevantFields.forEach(f => nvdebug(fieldToString(f)));\n return relevantFields;\n}\n\nexport function resetSubfield6Tag(subfield, tag) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n // NB! mainly for 1XX<->7XX transfers\n const newValue = `${tag}-${subfield.value.substring(4)}`;\n nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);\n subfield.value = newValue;\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["//import createDebugLogger from 'debug';\n// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield6Utils');\n\nimport {add8s, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, isValidSubfield8} from './subfield8Utils.js';\nimport {fieldHasSubfield, fieldToString, /* fieldsToString, */ nvdebug, subfieldToString} from './utils.js';\n\n//const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:subfield6Utils');\n//const debugData = debug.extend('data');\n//const debugDev = debug.extend('dev');\n\n// NB! Subfield 6 is non-repeatable and it should always comes first!\n// NB! Index size should always be 2 (preceding 0 required for 01..09) However, support for 100+ was added on 2023-02-27.\n// NB! Index value '00' are left as they are (is not paired/indexed/whatever.\nconst sf6Regexp = /^[0-9][0-9][0-9]-(?:[0-9][0-9]|[1-9][0-9]+)(?:[^0-9].*)?$/u;\n\nexport function isValidSubfield6(subfield) {\n if (subfield.code !== '6') {\n return false;\n }\n return subfield.value.match(sf6Regexp);\n}\n\nexport function subfield6GetTag(subfield) {\n if (isValidSubfield6(subfield)) {\n return subfield.value.substring(0, 3);\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumber(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.substring(4).replace(/\\D.*$/u, '');\n }\n return undefined;\n}\n\nexport function subfield6GetOccurrenceNumberAsInteger(subfield) {\n const index = subfield6GetOccurrenceNumber(subfield);\n if (index === undefined || index === '00') {\n return 0;\n }\n const result = parseInt(index, 10);\n //nvdebug(`SF6: ${subfield.value} => ${index} => ${result}`, debug);\n return result;\n}\n\nexport function subfield6ResetOccurrenceNumber(subfield, occurrenceNumber) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n const occurrenceNumberAsString = typeof occurrenceNumber === 'number' ? intToOccurrenceNumberString(occurrenceNumber) : occurrenceNumber;\n\n const newValue = subfield.value.substring(0, 4) + occurrenceNumberAsString + subfield6GetTail(subfield);\n //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`);\n subfield.value = newValue;\n}\n\n\nfunction subfield6GetTail(subfield) {\n if (isValidSubfield6(subfield)) {\n // Skip \"TAG-\" prefix. 2023-02-20: removed 2-digit requirement from here...\n return subfield.value.replace(/^\\d+-\\d+/u, '');\n }\n return '';\n}\n\nexport function subfield6HasWantedTagAndOccurrenceNumber(subfield, tagAndOccurrenceNumber) {\n if (subfield.code !== '6') {\n return false;\n }\n // We could also use generic code and go getTag()+'-'+getIndex() instead of regexp...\n const key = subfield.value.replace(/^([0-9][0-9][0-9]-[0-9][0-9]+).*$/u, '$1');\n //nvdebug(` Compare '${key}' vs '${tagAndOccurrenceNumber}'`);\n return key === tagAndOccurrenceNumber;\n}\n\n// <= SUBFIELD, FIELD =>\n\nexport function fieldGetUnambiguousTag(field) {\n const tags = field.subfields.filter(sf => subfield6GetTag(sf));\n if (tags.length === 1) {\n return subfield6GetTag(tags[0]);\n }\n return undefined;\n}\n\nexport function fieldGetUnambiguousOccurrenceNumber(field) {\n const occurrenceNumbers = field.subfields.filter(sf => subfield6GetOccurrenceNumber(sf));\n if (occurrenceNumbers.length === 1) {\n return subfield6GetOccurrenceNumber(occurrenceNumbers[0]);\n }\n return undefined;\n}\n\nexport function fieldHasOccurrenceNumber(field, occurrenceNumber) {\n //nvdebug(`${occurrenceNumber} vs ${fieldToString(field)}`);\n return field.subfields && field.subfields.some(sf => subfield6GetOccurrenceNumber(sf) === occurrenceNumber);\n}\n\nexport function fieldResetOccurrenceNumber(field, newOccurrenceNumber, oldOccurrenceNumber = undefined) {\n field.subfields.forEach(subfield => innerReset(subfield));\n\n function innerReset(subfield) {\n // (Optional) Check that this is really the occurrence number we wan't to reseot\n if (oldOccurrenceNumber !== undefined) {\n const currOccurrenceNumber = subfield6GetOccurrenceNumber(subfield);\n if (currOccurrenceNumber !== oldOccurrenceNumber) {\n return;\n }\n }\n subfield6ResetOccurrenceNumber(subfield, newOccurrenceNumber);\n }\n}\n\nexport function intToOccurrenceNumberString(i) {\n return i < 10 ? `0${i}` : `${i}`;\n}\n\nexport function fieldGetMaxSubfield6OccurrenceNumberAsInteger(field) {\n // used by reducer!\n //nvdebug(`Checking subfields $6 from ${JSON.stringify(field)}`);\n const sf6s = field.subfields ? field.subfields.filter(subfield => isValidSubfield6(subfield)) : [];\n if (sf6s.length === 0) {\n return 0;\n }\n // There should always be one, but here we check every subfield.\n //nvdebug(`Got ${field.subfields} $6-subfield(s) from ${JSON.stringify(field)}`, debug);\n const vals = sf6s.map(sf => subfield6GetOccurrenceNumberAsInteger(sf));\n return Math.max(...vals);\n}\n\nexport function fieldHasWantedTagAndOccurrenceNumber(field, tagAndOccurrenceNumber) {\n return field.subfields && field.subfields.some(sf => subfield6HasWantedTagAndOccurrenceNumber(sf, tagAndOccurrenceNumber));\n}\n\n\n/*\nexport function getFieldsWithGivenOccurrenceNumberSubfield6(record, occurrenceNumberAsString) {\n const record.fields.filter(field => field\n\n function fieldHasIndex(field, index) {\n if (!field.subfields) {\n return false;\n }\n return field.subfields.find(sf => isValidSubfield6(sf) && subfieldGetOccurrenceNumber6(sf) === index);\n }\n}\n*/\n\n\nexport function fieldHasValidSubfield6(field) {\n return field.subfields && field.subfields.some(sf => isValidSubfield6(sf));\n}\n\nexport function isSubfield6Pair(field, otherField) {\n // No need to log this:\n //nvdebug(`LOOK for $6-pair:\\n ${fieldToString(field)}\\n ${fieldToString(otherField)}`);\n if (!fieldHasValidSubfield6(field) || !fieldHasValidSubfield6(otherField)) {\n return false;\n }\n\n if (!tagsArePairable6(field.tag, otherField.tag)) {\n //nvdebug(` FAILED. REASON: TAGS NOT PAIRABLE!`);\n return false;\n }\n\n\n const fieldIndex = fieldGetUnambiguousOccurrenceNumber(field);\n if (fieldIndex === undefined || fieldIndex === '00') {\n //nvdebug(` FAILED. REASON: NO INDEX FOUND`);\n return false;\n }\n\n const otherFieldIndex = fieldGetUnambiguousOccurrenceNumber(otherField);\n\n\n if (fieldIndex !== otherFieldIndex) {\n //nvdebug(` FAILURE: INDEXES: ${fieldIndex} vs ${otherFieldIndex}`);\n return false;\n }\n\n if (fieldGetUnambiguousTag(field) !== otherField.tag || field.tag !== fieldGetUnambiguousTag(otherField)) {\n //nvdebug(` FAILURE: TAG vs $6 TAG`);\n return false;\n }\n return true;\n\n function tagsArePairable6(tag1, tag2) {\n // How to do XOR operation in one line? Well, this is probably more readable...\n if (tag1 === '880' && tag2 === '880') {\n return false;\n }\n if (tag1 !== '880' && tag2 !== '880') {\n return false;\n }\n return true;\n }\n}\n\n\nfunction subfieldSevenToOneOccurrenceNumber(subfield) {\n if (subfield.code !== '6' || subfield.value.substring(0, 1) !== '7') {\n return;\n }\n subfield.value = `1${subfield.value.substring(1)}`;\n}\n\nexport function fieldSevenToOneOccurrenceNumber(field) {\n if (field.tag !== '880') {\n return;\n }\n field.subfields.forEach(sf => subfieldSevenToOneOccurrenceNumber(sf));\n}\n\n\nexport function fieldGetOccurrenceNumberPairs(field, candFields) {\n // NB! TAG!=880 returns 880 fields, TAG==880 returns non-880 field\n //nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);\n const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairs.length === 0) {\n nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);\n return pairs;\n }\n //nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);\n pairs.forEach(pairedField => nvdebug(` '${fieldToString(pairedField)}'`));\n return pairs;\n}\n\nexport function fieldGetOccurrenceNumbers(field) {\n let occurrenceNumbers = [];\n field.subfields?.forEach(sf => subfieldExtractOccurrenceNumber(sf));\n\n function subfieldExtractOccurrenceNumber(sf) {\n if (!isValidSubfield6(sf)) {\n return;\n }\n const occurrenceNumber = subfield6GetOccurrenceNumber(sf);\n if (occurrenceNumber === '00' || occurrenceNumbers.includes(occurrenceNumber)) {\n return;\n }\n occurrenceNumbers.push(occurrenceNumber);\n }\n return occurrenceNumbers;\n}\n\nexport function fieldsGetOccurrenceNumbers(fields) {\n let occurrenceNumbers = [];\n\n fields.forEach(f => fieldProcessOccurrenceNumbers(f));\n\n function fieldProcessOccurrenceNumbers(f) {\n const newOccurrenceNumbers = fieldGetOccurrenceNumbers(f);\n newOccurrenceNumbers.forEach(occurrenceNumber => {\n if (!occurrenceNumbers.includes(occurrenceNumber)) {\n occurrenceNumbers.push(occurrenceNumber);\n }\n\n });\n }\n return occurrenceNumbers;\n}\n\n/*\nexport function fieldGetSubfield6Pair(field, record) {\n const pairedFields = record.fields.filter(otherField => isSubfield6Pair(field, otherField));\n if (pairedFields.length !== 1) {\n return undefined;\n }\n // NB! It is theoretically possible to have multiple pairable 880 fields (one for each encoding)\n nvdebug(`fieldGetSubfield6Pair(): ${fieldToString(field)} => ${fieldToString(pairedFields[0])}`);\n return pairedFields[0];\n}\n*/\n\n/*\nexport function pairAndStringify6(field, record) {\n const pair6 = fieldGetSubfield6Pair(field, record);\n if (!pair6) {\n return fieldToNormalizedString(field);\n }\n return fieldsToNormalizedString([field, pair6]);\n}\n*/\n\n// Frequencly list for $6 subfields in 1XX/7XX fields:\n// 231115 100\n// 183832 700\n// 28773 710\n// 2047 711\n// 661 110\n// 341 111\n// 284 130\n// 63 730\n// Thus there's a real risk of ending up with, say, identical 100 vs 700 chains.\n// Semi-hackily support 1XX/7XX-version: 7XX can be deleted if corresponding 1XX exists:\n\nexport function is7XX(tag) {\n return ['700', '710', '711', '730'].includes(tag);\n}\n\n\nfunction normalizeEntryTag(tag) {\n if (tag.match(/^[17](?:00|10|11|30)$/u)) {\n return `X${tag.substring(1)}`;\n }\n return tag;\n}\n\nfunction subfieldToNormalizedString(sf, tag, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {\n // targetLinkingNumber refers to $8.\n // normalizeEntryTagBoolean refers to 1XX/7XX tag values in subfield $6 value.\n if (isValidSubfield6(sf)) { // && targetLinkingNumber === 0) {\n // 1XX/7XX (entry tag) normalization:\n const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(tag) : tag;\n\n const occurrenceNumber = normalizeOccurrenceNumber ? 'XX' : subfield6GetOccurrenceNumber(sf);\n // If we are normalizing a $8 chain, don't normalize $6 occurrence number!\n // Replace $6 occurrence number with XX:\n return ` \u2021${sf.code} ${tag2}-${occurrenceNumber}${subfield6GetTail(sf)}`;\n }\n\n if (isValidSubfield8(sf)) {\n const currLinkingNumber = getSubfield8LinkingNumber(sf); //getSubfield8Index(sf);\n if (targetLinkingNumber > 0 && currLinkingNumber === targetLinkingNumber) {\n // For $8 we should only XX the index we are looking at...\n const normVal = sf.value.replace(/^[0-9]+/u, 'XX');\n return ` \u2021${sf.code} ${normVal}`;\n }\n return ''; // Other $8 subfields are meaningless in this context\n }\n return ` ${subfieldToString(sf)}`; // `\u2021${sf.code} ${sf.value}`;\n}\n\nexport function fieldToNormalizedString(field, targetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTagBoolean = false) {\n if ('subfields' in field) {\n const tag2 = normalizeEntryTagBoolean ? normalizeEntryTag(field.tag) : field.tag;\n return `${tag2} ${field.ind1}${field.ind2}${formatAndNormalizeSubfields(field)}`;\n }\n return `${field.tag} ${field.value}`;\n\n function formatAndNormalizeSubfields(field) {\n return field.subfields.map(sf => subfieldToNormalizedString(sf, field.tag, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTagBoolean)).join('');\n }\n\n}\n\n\nfunction guessTargetLinkingNumber(fields, defaultTargetLinkingNumber) {\n if (defaultTargetLinkingNumber !== 0) {\n return defaultTargetLinkingNumber;\n }\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);\n return linkingNumbers.length === 1 ? linkingNumbers[0] : 0;\n}\n\nexport function fieldsToNormalizedString(fields, defaultTargetLinkingNumber = 0, normalizeOccurrenceNumber = false, normalizeEntryTag = false) {\n const targetLinkingNumber = guessTargetLinkingNumber(fields, defaultTargetLinkingNumber);\n\n //nvdebug(`fieldsToNormalizedString: OCC: ${normalizeOccurrenceNumber}`);\n const strings = fields.map(field => fieldToNormalizedString(field, targetLinkingNumber, normalizeOccurrenceNumber, normalizeEntryTag));\n strings.sort();\n return strings.join('\\t__SEPARATOR__\\t');\n}\n\n\n/*\n\nexport function removeField6IfNeeded(field, record, fieldsAsString) {\n const pairField = fieldGetSubfield6Pair(field, record);\n const asString = pairField ? fieldsToNormalizedString([field, pairField]) : fieldToNormalizedString(field);\n nvdebug(`SOURCE: ${asString} -- REALITY: ${fieldToString(field)}`);\n const tmp = pairField ? fieldToString(pairField) : 'HUTI';\n nvdebug(`PAIR: ${tmp}`);\n nvdebug(`BASE:\\n ${fieldsAsString.join('\\n ')}`);\n if (!fieldsAsString.includes(asString)) {\n return;\n }\n nvdebug(`Duplicate $6 removal: ${fieldToString(field)}`);\n record.removeField(field);\n\n if (pairField === undefined) {\n return;\n }\n nvdebug(`Duplicate $6 removal (pair): ${fieldToString(pairField)}`);\n record.removeField(pairField);\n}\n*/\n\nfunction getFirstField(record, fields) {\n const fieldsAsStrings = fields.map(field => fieldToString(field));\n //record.fields.forEach((field, i) => nvdebug(`${i}:\\t${fieldToString(field)}`));\n //nvdebug(`getFirstField: ${fieldsAsStrings.join('\\t')}`);\n const i = record.fields.findIndex(field => fieldsAsStrings.includes(fieldToString(field)));\n if (i > -1) {\n const field = record.fields[i];\n //nvdebug(`1st F: ${i + 1}/${record.fields.length} ${fieldToString(field)}`);\n return field;\n }\n return undefined;\n}\n\nfunction isRelevantSubfield6Chain(fields) {\n if (fields.length < 2) { // 1 non-880-field and 1+ 880 fields\n return false;\n }\n const non880 = fields.filter(f => f.tag !== '880');\n if (non880.length !== 1) {\n return false;\n }\n\n const linkingNumbers = fieldsGetAllSubfield8LinkingNumbers(fields);\n if (linkingNumbers.length !== 0) {\n return false;\n }\n\n return fields.every(f => fieldHasSubfield(f, '6'));\n}\n\nexport function fieldIsFirstFieldInChain(field, chain, record) {\n // Interpretation of first: position of field in record (however, we might have a duplicate field. See tests...)\n const firstField = getFirstField(record, chain);\n if (firstField) {\n return fieldToString(field) === fieldToString(firstField);\n }\n return false;\n\n}\n\n\nexport function getAllLinkedSubfield6Fields(field, record) {\n const fields = get6s(field, record);\n const moreFields = add8s(fields, record);\n\n // Currently we don't handle fields with more than one $6 and/or $8 subfield.\n if (moreFields.length > fields.length) {\n return []; // Don't fix!\n }\n return moreFields;\n}\n\nexport function isFirstLinkedSubfield6Field(field, record) {\n if (!field.subfields) { // Is not a datafield\n return false;\n }\n const chain = getAllLinkedSubfield6Fields(field, record);\n if (!isRelevantSubfield6Chain(chain)) {\n //nvdebug(`Rejected 6: ${fieldsToString(chain)}`);\n return false;\n }\n\n return fieldIsFirstFieldInChain(field, chain, record);\n}\n\nexport function recordGetSubfield6ChainHeads(record) {\n return record.fields.filter(field => isFirstLinkedSubfield6Field(field, record));\n}\n\nexport function recordGetMaxSubfield6OccurrenceNumberAsInteger(record) {\n if (record.fields.length === 0) {\n return 0;\n }\n // Should we cache the value here?\n const vals = record.fields.map((field) => fieldGetMaxSubfield6OccurrenceNumberAsInteger(field));\n return Math.max(...vals);\n}\n\nexport function get6s(field, candidateFields) { // NB! Convert field to fields!!!\n // Get all fields with given occurrence number\n const sixes = field.subfields.filter(sf => isValidSubfield6(sf));\n\n if (sixes.length === 0) {\n return [field];\n }\n //nvdebug(`SIXES: ${sixes.length}`);\n const occurrenceNumbers = sixes.map(sf => subfield6GetOccurrenceNumber(sf)).filter(value => value !== undefined && value !== '00');\n //nvdebug(occurrenceNumbers.join(' -- '));\n\n const relevantFields = candidateFields.filter(f => occurrenceNumbers.some(o => fieldHasOccurrenceNumber(f, o)));\n //nvdebug(`${fieldToString(field)}: $6-RELFIELDS FOUND: ${relevantFields.length}...`);\n //relevantFields.forEach(f => nvdebug(fieldToString(f)));\n return relevantFields;\n}\n\nexport function resetSubfield6Tag(subfield, tag) {\n if (!isValidSubfield6(subfield)) {\n return;\n }\n // NB! mainly for 1XX<->7XX transfers\n const newValue = `${tag}-${subfield.value.substring(4)}`;\n //nvdebug(`Set subfield $6 value from ${subfieldToString(subfield)} to ${newValue}`, debugDev);\n subfield.value = newValue;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["field", "normalizeEntryTag"]
|
|
7
7
|
}
|
|
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
|
|
|
3
3
|
import validatorFactory from "./subfieldValueNormalizations.js";
|
|
4
4
|
import { READERS } from "@natlibfi/fixura";
|
|
5
5
|
import generateTests from "@natlibfi/fixugen";
|
|
6
|
-
import createDebugLogger from "debug";
|
|
7
6
|
generateTests({
|
|
8
7
|
callback,
|
|
9
8
|
path: [import.meta.dirname, "..", "test-fixtures", "normalize-subfield-value"],
|
|
@@ -18,18 +17,13 @@ generateTests({
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/subfieldValueNormalizations:test");
|
|
22
20
|
async function testValidatorFactory() {
|
|
23
21
|
const validator = await validatorFactory();
|
|
24
22
|
assert.equal(typeof validator, "object");
|
|
25
23
|
assert.equal(typeof validator, "string");
|
|
26
24
|
assert.equal(typeof validator, "function");
|
|
27
25
|
}
|
|
28
|
-
async function callback({ getFixture,
|
|
29
|
-
if (enabled === false) {
|
|
30
|
-
debug("TEST SKIPPED!");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
33
27
|
const validator = await validatorFactory();
|
|
34
28
|
const recordFixture = getFixture("record.json");
|
|
35
29
|
const record = recordFixture._validationOptions ? new MarcRecord(recordFixture, recordFixture._validationOptions) : new MarcRecord(recordFixture);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/subfieldValueNormalizations.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './subfieldValueNormalizations.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './subfieldValueNormalizations.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'normalize-subfield-value'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/subfieldValueNormalizations:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator, 'string');\n assert.equal(typeof validator, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n\n const recordFixture = getFixture('record.json');\n\n const record = recordFixture._validationOptions ? new MarcRecord(recordFixture, recordFixture._validationOptions) : new MarcRecord(recordFixture);\n //const record = new MarcRecord(recordFixture, {\"subfields\": false}); // works\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
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,0BAA0B;AAAA,EAC7E,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;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,WAAW,UAAU;AAC3C;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AAEzC,QAAM,gBAAgB,WAAW,aAAa;AAE9C,QAAM,SAAS,cAAc,qBAAqB,IAAI,WAAW,eAAe,cAAc,kBAAkB,IAAI,IAAI,WAAW,aAAa;AAEhJ,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
|
}
|
|
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
|
|
|
3
3
|
import validatorFactory from "./sync-007-and-300.js";
|
|
4
4
|
import { READERS } from "@natlibfi/fixura";
|
|
5
5
|
import generateTests from "@natlibfi/fixugen";
|
|
6
|
-
import createDebugLogger from "debug";
|
|
7
6
|
generateTests({
|
|
8
7
|
callback,
|
|
9
8
|
path: [import.meta.dirname, "..", "test-fixtures", "sync-007-and-300"],
|
|
@@ -18,18 +17,13 @@ generateTests({
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
});
|
|
21
|
-
const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/sync-007-and-300:test");
|
|
22
20
|
async function testValidatorFactory() {
|
|
23
21
|
const validator = await validatorFactory();
|
|
24
22
|
assert.equal(typeof validator, "object");
|
|
25
23
|
assert.equal(typeof validator.description, "string");
|
|
26
24
|
assert.equal(typeof validator.validate, "function");
|
|
27
25
|
}
|
|
28
|
-
async function callback({ getFixture,
|
|
29
|
-
if (enabled === false) {
|
|
30
|
-
debug("TEST SKIPPED!");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
33
27
|
const validator = await validatorFactory();
|
|
34
28
|
const record = new MarcRecord(getFixture("record.json"));
|
|
35
29
|
const expectedResult = getFixture("expectedResult.json");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/sync-007-and-300.test.js"],
|
|
4
|
-
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './sync-007-and-300.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './sync-007-and-300.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'sync-007-and-300'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/sync-007-and-300: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.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\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
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,kBAAkB;AAAA,EACrE,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;AAEF,CAAC;AAGD,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,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,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
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import clone from "clone";
|
|
2
|
+
import { fieldToString } from "./utils.js";
|
|
3
|
+
export default function() {
|
|
4
|
+
return {
|
|
5
|
+
description: "Sync 008/35-37 and 041$a/$d",
|
|
6
|
+
validate,
|
|
7
|
+
fix
|
|
8
|
+
};
|
|
9
|
+
function getSubfieldCodeFor041(record) {
|
|
10
|
+
const c = record?.leader[6];
|
|
11
|
+
if (c === "i" || c === "j") {
|
|
12
|
+
return "d";
|
|
13
|
+
}
|
|
14
|
+
return "a";
|
|
15
|
+
}
|
|
16
|
+
function transferableValue(val) {
|
|
17
|
+
if (val.match(/^[a-z]{3}$/u)) {
|
|
18
|
+
if (val === "zxx") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function zxxRemoval041(record, field, validateMode) {
|
|
26
|
+
const fields041 = record.fields.filter((f) => f.tag === "041");
|
|
27
|
+
return handleZxx(fields041);
|
|
28
|
+
function handleZxx(fields, result = []) {
|
|
29
|
+
const [currField, ...remainingFields] = fields;
|
|
30
|
+
if (!currField) {
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
if (!field.subfields || field.subfields.some((sf) => sf.code === "2")) {
|
|
34
|
+
return handleZxx(remainingFields, result);
|
|
35
|
+
}
|
|
36
|
+
const otherSubfields = field.subfields.some((sf) => !sf.code.match(/^[a-z]$/u));
|
|
37
|
+
if (otherSubfields.length === field.subfields.length) {
|
|
38
|
+
return handleZxx(remainingFields, result);
|
|
39
|
+
}
|
|
40
|
+
const originalString = fieldToString(field);
|
|
41
|
+
if (otherSubfields.length === 0) {
|
|
42
|
+
const message2 = `Remove '${originalString}'`;
|
|
43
|
+
if (!validateMode) {
|
|
44
|
+
record.removeField(field);
|
|
45
|
+
}
|
|
46
|
+
return handleZxx(remainingFields, [...result, message2]);
|
|
47
|
+
}
|
|
48
|
+
if (validateMode) {
|
|
49
|
+
const clonedField = clone(field);
|
|
50
|
+
clonedField.subfields = otherSubfields;
|
|
51
|
+
const modifiedString2 = fieldToString(clonedField);
|
|
52
|
+
const message2 = `Modify '${originalString}' => '${modifiedString2}`;
|
|
53
|
+
return handleZxx(remainingFields, [...result, message2]);
|
|
54
|
+
}
|
|
55
|
+
field.subfields = otherSubfields;
|
|
56
|
+
const modifiedString = fieldToString(field);
|
|
57
|
+
const message = `Modify '${originalString}' => '${modifiedString}`;
|
|
58
|
+
return handleZxx(remainingFields, [...result, message]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function sync008And041(record, validateMode) {
|
|
62
|
+
const f008 = record.fields.find((f) => f.tag === "008");
|
|
63
|
+
const f041 = record.fields.find((f) => f.tag === "041");
|
|
64
|
+
if (!f008 || f008.value.length !== 40) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const subfieldCode = getSubfieldCodeFor041(record);
|
|
68
|
+
const lang008 = f008.value.substring(35, 38);
|
|
69
|
+
if (!f041) {
|
|
70
|
+
if (transferableValue(lang008)) {
|
|
71
|
+
const newField = { "tag": "041", "ind1": " ", "ind2": " ", "subfields": [{ "code": subfieldCode, "value": lang008 }] };
|
|
72
|
+
if (!validateMode) {
|
|
73
|
+
record.insertField(newField);
|
|
74
|
+
}
|
|
75
|
+
return [`Add '${fieldToString(newField)}'`];
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const firstRelevantSubfield = f041.subfields.find((sf) => sf.code === subfieldCode);
|
|
80
|
+
if (!firstRelevantSubfield || !transferableValue(firstRelevantSubfield.value) || f041.subfields.some((sf) => sf.code === "2") || lang008 === firstRelevantSubfield.value) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const cloned008 = clone(f008);
|
|
84
|
+
cloned008.value = `${f008.value.substring(0, 35)}${firstRelevantSubfield.value}${f008.value.substring(38)}`;
|
|
85
|
+
if (!validateMode) {
|
|
86
|
+
f008.value = cloned008.value;
|
|
87
|
+
}
|
|
88
|
+
return [`Modify '${f008.value}' to '${cloned008.value}'`];
|
|
89
|
+
}
|
|
90
|
+
function fix(record, validateMode = false) {
|
|
91
|
+
const zxxMessages = zxxRemoval041(record, validateMode);
|
|
92
|
+
const syncMessages = sync008And041(record, validateMode);
|
|
93
|
+
const messages = [...zxxMessages, ...syncMessages];
|
|
94
|
+
if (validateMode) {
|
|
95
|
+
return { message: messages, valid: messages.length === 0 };
|
|
96
|
+
}
|
|
97
|
+
return { message: [], fix: messages, valid: true };
|
|
98
|
+
}
|
|
99
|
+
function validate(record) {
|
|
100
|
+
return fix(record, true);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=sync-language.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/sync-language.js"],
|
|
4
|
+
"sourcesContent": ["// Author(s): Nicholas Volk\n\n//import createDebugLogger from 'debug';\nimport clone from 'clone';\n\nimport {fieldToString} from './utils.js';\n\n// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sync-language');\n\nexport default function () {\n\n return {\n description: 'Sync 008/35-37 and 041$a/$d',\n validate, fix\n };\n\n function getSubfieldCodeFor041(record) {\n const c = record?.leader[6];\n if (c === 'i' || c === 'j') {\n return 'd';\n }\n return 'a';\n }\n\n function transferableValue(val) {\n if (val.match(/^[a-z]{3}$/u)) {\n // 'zxx' is an exception to the otherwise relatively transitive 008/35-37 <=> 041$a relationship...\n // https://wiki.helsinki.fi/xwiki/bin/view/rdasovellusohje/RDA-kuvailu%20MARC%2021%20-formaatilla/RDA-sovellusohje/008%20Kontrollikentt%C3%A4/#Hmp.35-37Kieli\n // \"008-kielikoodi on sama kuin ensimm\u00E4inen 041-kent\u00E4n a- (tai d-) osakentt\u00E4. Poikkeuksen muodostaa koodi zxx:\n // jos tietueen 008ssa on kielikoodi zxx (ei kielellist\u00E4 sis\u00E4lt\u00F6\u00E4, esim. soitinmusiikki), tietueessa ei voi olla 041 a- eik\u00E4 d-osakentt\u00E4\u00E4.\"\n // So 'zxx' ain't transferable (done here), and it should be removed from 041 ($a and $d at least, not done here nor elsewhere at the moment...)\n // Note that 'mul' and 'und' are treated (in this validator) the same as normal values.\n if (val === 'zxx') {\n return false;\n }\n return true;\n }\n return false;\n }\n\n\n function zxxRemoval041(record, field, validateMode) {\n const fields041 = record.fields.filter(f => f.tag === '041');\n\n return handleZxx(fields041);\n\n function handleZxx(fields, result = []) {\n const [currField, ...remainingFields] = fields;\n if ( !currField) {\n return result;\n }\n // Theoretically 'zxx' might mean something in ISO-639-3 or some other language code list:\n if (!field.subfields || field.subfields.some(sf => sf.code === '2')) {\n return handleZxx(remainingFields, result);\n }\n // Presumable 'zxx' is bad in any data subfield, not just 'a' and 'd':\n const otherSubfields = field.subfields.some(sf => !sf.code.match(/^[a-z]$/u || sf.value !== 'zxx'));\n if (otherSubfields.length === field.subfields.length) {\n return handleZxx(remainingFields, result);\n }\n const originalString = fieldToString(field);\n if (otherSubfields.length === 0) {\n const message = `Remove '${originalString}'`;\n if (!validateMode) {\n record.removeField(field);\n }\n return handleZxx(remainingFields, [...result, message]);\n }\n // Some subfields are removed:\n if (validateMode) {\n // NB! In validation field is not really deleted, and the non-deleted field might trigger other fixes (than won't be done to a deleted field) later on\n const clonedField = clone(field);\n clonedField.subfields = otherSubfields;\n const modifiedString = fieldToString(clonedField);\n const message = `Modify '${originalString}' => '${modifiedString}`;\n return handleZxx(remainingFields, [...result, message]);\n }\n field.subfields = otherSubfields;\n const modifiedString = fieldToString(field);\n const message = `Modify '${originalString}' => '${modifiedString}`;\n return handleZxx(remainingFields, [...result, message]);\n }\n\n\n }\n\n function sync008And041(record, validateMode) {\n const f008 = record.fields.find(f => f.tag === '008');\n const f041 = record.fields.find(f => f.tag === '041');\n\n if (!f008 || f008.value.length !== 40) { // Some sanity checks\n return [];\n }\n\n const subfieldCode = getSubfieldCodeFor041(record);\n const lang008 = f008.value.substring(35, 38);\n\n if (!f041) {\n // Insert missing 041\n if (transferableValue(lang008)) {\n const newField = {'tag': '041', 'ind1': ' ', 'ind2': ' ', 'subfields': [ {'code': subfieldCode, 'value': lang008}]};\n if (!validateMode) {\n record.insertField(newField);\n }\n return [ `Add '${fieldToString(newField)}'` ];\n }\n // Can't do anything, and we only report this we can fix...\n return [];\n }\n\n const firstRelevantSubfield = f041.subfields.find(sf => sf.code === subfieldCode);\n\n // NB! If $2 is set, *never* copy it's value to 008/35-37... Otherwise we might a loop in Aleph.\n // Note that if $2 is used, 008/35-37 should actually be '|||'. Now we just aggressively leave it alone.\n if (!firstRelevantSubfield || !transferableValue(firstRelevantSubfield.value) || f041.subfields.some(sf => sf.code === '2') || lang008 === firstRelevantSubfield.value) {\n return []\n }\n\n // Update 008/35-37:\n const cloned008 = clone(f008);\n cloned008.value = `${f008.value.substring(0, 35)}${firstRelevantSubfield.value}${f008.value.substring(38)}`;\n\n\n if (!validateMode) {\n f008.value = cloned008.value;\n }\n return [ `Modify '${f008.value}' to '${cloned008.value}'` ];\n }\n\n function fix(record, validateMode = false) {\n const zxxMessages = zxxRemoval041(record, validateMode);\n\n const syncMessages = sync008And041(record, validateMode);\n\n const messages = [...zxxMessages, ...syncMessages];\n\n if (validateMode) {\n return {message: messages, valid: messages.length === 0};\n }\n return {message: [], fix: messages, valid: true};\n }\n\n\n function validate(record) {\n return fix(record, true);\n }\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["message", "modifiedString"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import validatorFactory from "./sync-language.js";
|
|
3
|
+
import { MarcRecord } from "@natlibfi/marc-record";
|
|
4
|
+
import { READERS } from "@natlibfi/fixura";
|
|
5
|
+
import generateTests from "@natlibfi/fixugen";
|
|
6
|
+
generateTests({
|
|
7
|
+
callback,
|
|
8
|
+
path: [import.meta.dirname, "..", "test-fixtures", "sync-language"],
|
|
9
|
+
useMetadataFile: true,
|
|
10
|
+
recurse: false,
|
|
11
|
+
fixura: {
|
|
12
|
+
reader: READERS.JSON
|
|
13
|
+
},
|
|
14
|
+
hooks: {
|
|
15
|
+
before: async () => {
|
|
16
|
+
testValidatorFactory();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
async function testValidatorFactory() {
|
|
21
|
+
const validator = await validatorFactory();
|
|
22
|
+
assert.equal(typeof validator, "object");
|
|
23
|
+
assert.equal(typeof validator.description, "string");
|
|
24
|
+
assert.equal(typeof validator.validate, "function");
|
|
25
|
+
}
|
|
26
|
+
async function callback({ getFixture, fix = false }) {
|
|
27
|
+
const validator = await validatorFactory();
|
|
28
|
+
const record = new MarcRecord(getFixture("record.json"));
|
|
29
|
+
const expectedResult = getFixture("expectedResult.json");
|
|
30
|
+
if (!fix) {
|
|
31
|
+
const result = await validator.validate(record);
|
|
32
|
+
assert.deepEqual(result, expectedResult);
|
|
33
|
+
const originalRecord = new MarcRecord(getFixture("record.json"));
|
|
34
|
+
assert.deepEqual(record, originalRecord);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
await validator.fix(record);
|
|
38
|
+
assert.deepEqual(record, new MarcRecord(expectedResult));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sync-language.test.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/sync-language.test.js"],
|
|
4
|
+
"sourcesContent": ["import assert from 'node:assert/strict';\n//import createDebugLogger from 'debug';\n\nimport validatorFactory from './sync-language.js';\n\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'sync-language'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/drop-terms: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.validate, 'function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n //const expectedResult = new MarcRecord(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 const originalRecord = new MarcRecord(getFixture('record.json'));\n assert.deepEqual(record, originalRecord); // The record should now change in validation-only\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, new MarcRecord(expectedResult));\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AAGnB,OAAO,sBAAsB;AAE7B,SAAQ,kBAAiB;AACzB,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAE1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,eAAe;AAAA,EAClE,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;AAID,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,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAIvD,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC,UAAM,iBAAiB,IAAI,WAAW,WAAW,aAAa,CAAC;AAC/D,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,IAAI,WAAW,cAAc,CAAC;AACzD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|