@biblioteksentralen/marc 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/index.cjs +98 -86
- package/dist/index.d.cts +13 -4
- package/dist/index.d.ts +13 -4
- package/dist/index.js +99 -87
- package/package.json +1 -2
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -59,8 +59,14 @@ var DataField = class {
|
|
|
59
59
|
subfields: this.subfields.map((subfield) => subfield.toJSON())
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns a human-readable string representation of this MARC data field.
|
|
64
|
+
*
|
|
65
|
+
* The result is intended for debugging, logging, and test output. The format is not guaranteed to
|
|
66
|
+
* be stable and should not be parsed or relied upon.
|
|
67
|
+
*/
|
|
62
68
|
toString() {
|
|
63
|
-
return `${this.tag} ${this.subfields.map((subfield) => subfield.toString()).join(" ")}`;
|
|
69
|
+
return `${this.tag} ${this.ind1 ?? " "}${this.ind2 ?? " "} ${this.subfields.map((subfield) => subfield.toString()).join(" ")}`;
|
|
64
70
|
}
|
|
65
71
|
};
|
|
66
72
|
var isControlField = (field) => field instanceof ControlField;
|
|
@@ -180,9 +186,10 @@ function createMarcSchema({
|
|
|
180
186
|
|
|
181
187
|
// src/marc-record/errors.ts
|
|
182
188
|
var MarcRecordSchemaValidationError = class extends Error {
|
|
183
|
-
constructor(errors) {
|
|
189
|
+
constructor(errors, sourceData) {
|
|
184
190
|
super("MarcRecord schema validation failed");
|
|
185
191
|
this.errors = errors;
|
|
192
|
+
this.sourceData = sourceData;
|
|
186
193
|
}
|
|
187
194
|
};
|
|
188
195
|
var MarcParseError = class extends Error {
|
|
@@ -191,6 +198,80 @@ var MarcParseError = class extends Error {
|
|
|
191
198
|
this.record = record;
|
|
192
199
|
}
|
|
193
200
|
};
|
|
201
|
+
function buildRecordXml(input) {
|
|
202
|
+
const fields = [
|
|
203
|
+
xmlUtils.createXmlElement("leader", { text: input.leader }),
|
|
204
|
+
...input.getControlFields().map(
|
|
205
|
+
(field) => xmlUtils.createXmlElement("controlfield", {
|
|
206
|
+
attributes: { tag: field.tag },
|
|
207
|
+
text: field.value
|
|
208
|
+
})
|
|
209
|
+
),
|
|
210
|
+
...input.getDataFields().map(
|
|
211
|
+
(field) => xmlUtils.createXmlElement("datafield", {
|
|
212
|
+
attributes: withoutEmptyValues({
|
|
213
|
+
tag: field.tag,
|
|
214
|
+
ind1: field.ind1,
|
|
215
|
+
ind2: field.ind2
|
|
216
|
+
}),
|
|
217
|
+
children: field.subfields.map(
|
|
218
|
+
(subfield) => xmlUtils.createXmlElement("subfield", {
|
|
219
|
+
attributes: { code: subfield.code },
|
|
220
|
+
text: subfield.value
|
|
221
|
+
})
|
|
222
|
+
)
|
|
223
|
+
})
|
|
224
|
+
)
|
|
225
|
+
];
|
|
226
|
+
const recordNode = xmlUtils.createXmlElement("record", {
|
|
227
|
+
children: fields
|
|
228
|
+
});
|
|
229
|
+
return recordNode;
|
|
230
|
+
}
|
|
231
|
+
function serializeMarcXml(input, pretty = false) {
|
|
232
|
+
const record = buildRecordXml(input);
|
|
233
|
+
record.setAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
|
|
234
|
+
return xmlUtils.serializeXml(record, pretty);
|
|
235
|
+
}
|
|
236
|
+
var withoutEmptyValues = (obj) => Object.keys(obj).reduce(
|
|
237
|
+
(acc, key) => obj[key] === void 0 ? { ...acc } : { ...acc, [key]: obj[key] },
|
|
238
|
+
{}
|
|
239
|
+
);
|
|
240
|
+
function serializeMarcXmlCollection(input, pretty = false) {
|
|
241
|
+
const records = input.map(buildRecordXml);
|
|
242
|
+
const collectionNode = xmlUtils.createXmlElement("collection", {
|
|
243
|
+
attributes: { xmlns: "http://www.loc.gov/MARC21/slim" },
|
|
244
|
+
children: records
|
|
245
|
+
});
|
|
246
|
+
return xmlUtils.serializeXml(collectionNode, pretty);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/marc-record/serializeLineMarc.ts
|
|
250
|
+
function serializeLineMarc(input) {
|
|
251
|
+
const leader = serializer.leader(input.leader);
|
|
252
|
+
const control = input.getControlFields().map(serializer.controlfield).join("");
|
|
253
|
+
const data = input.getDataFields().map(serializer.datafield).join("");
|
|
254
|
+
return `${leader}${control}${data}^
|
|
255
|
+
`;
|
|
256
|
+
}
|
|
257
|
+
var serializer = {
|
|
258
|
+
leader: (leader) => `*LDR${leader}
|
|
259
|
+
`,
|
|
260
|
+
controlfield: (field) => `*${field.tag}${field.value}
|
|
261
|
+
`,
|
|
262
|
+
datafield: (field) => {
|
|
263
|
+
const ind1 = field.ind1 ?? " ";
|
|
264
|
+
const ind2 = field.ind2 ?? " ";
|
|
265
|
+
const subfields = field.subfields.map(
|
|
266
|
+
(subfield) => `$${subfield.code}${escapeSubfieldValue(subfield.value)}`
|
|
267
|
+
).join("");
|
|
268
|
+
return `*${field.tag}${ind1}${ind2}${subfields}
|
|
269
|
+
`;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var escapeSubfieldValue = (value) => {
|
|
273
|
+
return value.replace(/\n/g, " ").replace(/\$/g, "@{2}");
|
|
274
|
+
};
|
|
194
275
|
|
|
195
276
|
// src/marc-record/MarcRecord.ts
|
|
196
277
|
var validator = new ajv.Ajv().compile(createMarcSchema());
|
|
@@ -207,10 +288,9 @@ var MarcRecord = class _MarcRecord {
|
|
|
207
288
|
this.leader = leader;
|
|
208
289
|
this.fields = fields;
|
|
209
290
|
}
|
|
210
|
-
static fromJSON(data
|
|
291
|
+
static fromJSON(data) {
|
|
211
292
|
const { format, leader, fields } = this.validateJSON(
|
|
212
|
-
fixInvalidMarcRecordSerialization(data)
|
|
213
|
-
log
|
|
293
|
+
fixInvalidMarcRecordSerialization(data)
|
|
214
294
|
);
|
|
215
295
|
return new _MarcRecord({
|
|
216
296
|
leader,
|
|
@@ -227,17 +307,23 @@ var MarcRecord = class _MarcRecord {
|
|
|
227
307
|
fields: this.fields.map((field) => field.toJSON())
|
|
228
308
|
};
|
|
229
309
|
}
|
|
230
|
-
|
|
310
|
+
toXML(pretty = false) {
|
|
311
|
+
return serializeMarcXml(this, pretty);
|
|
312
|
+
}
|
|
313
|
+
toXmlElement() {
|
|
314
|
+
return buildRecordXml(this);
|
|
315
|
+
}
|
|
316
|
+
toLineMarc() {
|
|
317
|
+
return serializeLineMarc(this);
|
|
318
|
+
}
|
|
319
|
+
static validateJSON(data) {
|
|
231
320
|
if (validator(data)) {
|
|
232
321
|
return data;
|
|
233
322
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
Data:
|
|
238
|
-
${JSON.stringify(data)}`
|
|
323
|
+
throw new MarcRecordSchemaValidationError(
|
|
324
|
+
validator.errors ?? [],
|
|
325
|
+
JSON.stringify(data)
|
|
239
326
|
);
|
|
240
|
-
throw new MarcRecordSchemaValidationError(validator.errors ?? []);
|
|
241
327
|
}
|
|
242
328
|
getControlFields() {
|
|
243
329
|
return this.fields.filter(isControlField);
|
|
@@ -382,80 +468,6 @@ var marcRecordZodSchema = zod.z.object({
|
|
|
382
468
|
fields: zod.z.array(zod.z.union([controlFieldSchema, dataFieldSchema]))
|
|
383
469
|
});
|
|
384
470
|
|
|
385
|
-
// src/marc-record/serializeLineMarc.ts
|
|
386
|
-
function serializeLineMarc(input) {
|
|
387
|
-
const leader = serializer.leader(input.leader);
|
|
388
|
-
const control = input.getControlFields().map(serializer.controlfield).join("");
|
|
389
|
-
const data = input.getDataFields().map(serializer.datafield).join("");
|
|
390
|
-
return `${leader}${control}${data}^
|
|
391
|
-
`;
|
|
392
|
-
}
|
|
393
|
-
var serializer = {
|
|
394
|
-
leader: (leader) => `*LDR${leader}
|
|
395
|
-
`,
|
|
396
|
-
controlfield: (field) => `*${field.tag}${field.value}
|
|
397
|
-
`,
|
|
398
|
-
datafield: (field) => {
|
|
399
|
-
const ind1 = field.ind1 ?? " ";
|
|
400
|
-
const ind2 = field.ind2 ?? " ";
|
|
401
|
-
const subfields = field.subfields.map(
|
|
402
|
-
(subfield) => `$${subfield.code}${escapeSubfieldValue(subfield.value)}`
|
|
403
|
-
).join("");
|
|
404
|
-
return `*${field.tag}${ind1}${ind2}${subfields}
|
|
405
|
-
`;
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
var escapeSubfieldValue = (value) => {
|
|
409
|
-
return value.replace(/\n/g, " ").replace(/\$/g, "@{2}");
|
|
410
|
-
};
|
|
411
|
-
function buildRecordXml(input) {
|
|
412
|
-
const fields = [
|
|
413
|
-
xmlUtils.createXmlElement("leader", { text: input.leader }),
|
|
414
|
-
...input.getControlFields().map(
|
|
415
|
-
(field) => xmlUtils.createXmlElement("controlfield", {
|
|
416
|
-
attributes: { tag: field.tag },
|
|
417
|
-
text: field.value
|
|
418
|
-
})
|
|
419
|
-
),
|
|
420
|
-
...input.getDataFields().map(
|
|
421
|
-
(field) => xmlUtils.createXmlElement("datafield", {
|
|
422
|
-
attributes: withoutEmptyValues({
|
|
423
|
-
tag: field.tag,
|
|
424
|
-
ind1: field.ind1,
|
|
425
|
-
ind2: field.ind2
|
|
426
|
-
}),
|
|
427
|
-
children: field.subfields.map(
|
|
428
|
-
(subfield) => xmlUtils.createXmlElement("subfield", {
|
|
429
|
-
attributes: { code: subfield.code },
|
|
430
|
-
text: subfield.value
|
|
431
|
-
})
|
|
432
|
-
)
|
|
433
|
-
})
|
|
434
|
-
)
|
|
435
|
-
];
|
|
436
|
-
const recordNode = xmlUtils.createXmlElement("record", {
|
|
437
|
-
children: fields
|
|
438
|
-
});
|
|
439
|
-
return recordNode;
|
|
440
|
-
}
|
|
441
|
-
function serializeMarcXml(input, pretty = false) {
|
|
442
|
-
const record = buildRecordXml(input);
|
|
443
|
-
record.setAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
|
|
444
|
-
return xmlUtils.serializeXml(record, pretty);
|
|
445
|
-
}
|
|
446
|
-
var withoutEmptyValues = (obj) => Object.keys(obj).reduce(
|
|
447
|
-
(acc, key) => obj[key] === void 0 ? { ...acc } : { ...acc, [key]: obj[key] },
|
|
448
|
-
{}
|
|
449
|
-
);
|
|
450
|
-
function serializeMarcXmlCollection(input, pretty = false) {
|
|
451
|
-
const records = input.map(buildRecordXml);
|
|
452
|
-
const collectionNode = xmlUtils.createXmlElement("collection", {
|
|
453
|
-
attributes: { xmlns: "http://www.loc.gov/MARC21/slim" },
|
|
454
|
-
children: records
|
|
455
|
-
});
|
|
456
|
-
return xmlUtils.serializeXml(collectionNode, pretty);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
471
|
exports.ControlField = ControlField;
|
|
460
472
|
exports.DataField = DataField;
|
|
461
473
|
exports.MarcParseError = MarcParseError;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { XmlElement } from '@biblioteksentralen/xml-utils';
|
|
2
|
-
import { Logger } from 'ts-log';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { ErrorObject } from 'ajv';
|
|
5
4
|
|
|
@@ -42,6 +41,12 @@ declare class DataField {
|
|
|
42
41
|
getFirstSubfield(code: string | RegExp): Subfield | undefined;
|
|
43
42
|
getFirstSubfieldValue(code: string | RegExp): string | undefined;
|
|
44
43
|
toJSON(): SerializedDataField;
|
|
44
|
+
/**
|
|
45
|
+
* Returns a human-readable string representation of this MARC data field.
|
|
46
|
+
*
|
|
47
|
+
* The result is intended for debugging, logging, and test output. The format is not guaranteed to
|
|
48
|
+
* be stable and should not be parsed or relied upon.
|
|
49
|
+
*/
|
|
45
50
|
toString(): string;
|
|
46
51
|
}
|
|
47
52
|
type MarcField = ControlField | DataField;
|
|
@@ -75,9 +80,12 @@ declare class MarcRecord {
|
|
|
75
80
|
fields: MarcField[];
|
|
76
81
|
format?: string;
|
|
77
82
|
});
|
|
78
|
-
static fromJSON(data: unknown
|
|
83
|
+
static fromJSON(data: unknown): MarcRecord;
|
|
79
84
|
toJSON(): SerializedMarcRecord;
|
|
80
|
-
|
|
85
|
+
toXML(pretty?: boolean): string;
|
|
86
|
+
toXmlElement(): XmlElement;
|
|
87
|
+
toLineMarc(): string;
|
|
88
|
+
static validateJSON(data: unknown): SerializedMarcRecord;
|
|
81
89
|
getControlFields(): ControlField[];
|
|
82
90
|
getControlField(tag: string): ControlField | undefined;
|
|
83
91
|
getDataFields(tag?: string | RegExp, indicators?: Indicators): DataField[];
|
|
@@ -210,7 +218,8 @@ declare function serializeMarcXmlCollection(input: MarcRecord[], pretty?: boolea
|
|
|
210
218
|
|
|
211
219
|
declare class MarcRecordSchemaValidationError extends Error {
|
|
212
220
|
readonly errors: ErrorObject[];
|
|
213
|
-
|
|
221
|
+
readonly sourceData?: string | undefined;
|
|
222
|
+
constructor(errors: ErrorObject[], sourceData?: string | undefined);
|
|
214
223
|
}
|
|
215
224
|
declare class MarcParseError extends Error {
|
|
216
225
|
readonly record: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { XmlElement } from '@biblioteksentralen/xml-utils';
|
|
2
|
-
import { Logger } from 'ts-log';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { ErrorObject } from 'ajv';
|
|
5
4
|
|
|
@@ -42,6 +41,12 @@ declare class DataField {
|
|
|
42
41
|
getFirstSubfield(code: string | RegExp): Subfield | undefined;
|
|
43
42
|
getFirstSubfieldValue(code: string | RegExp): string | undefined;
|
|
44
43
|
toJSON(): SerializedDataField;
|
|
44
|
+
/**
|
|
45
|
+
* Returns a human-readable string representation of this MARC data field.
|
|
46
|
+
*
|
|
47
|
+
* The result is intended for debugging, logging, and test output. The format is not guaranteed to
|
|
48
|
+
* be stable and should not be parsed or relied upon.
|
|
49
|
+
*/
|
|
45
50
|
toString(): string;
|
|
46
51
|
}
|
|
47
52
|
type MarcField = ControlField | DataField;
|
|
@@ -75,9 +80,12 @@ declare class MarcRecord {
|
|
|
75
80
|
fields: MarcField[];
|
|
76
81
|
format?: string;
|
|
77
82
|
});
|
|
78
|
-
static fromJSON(data: unknown
|
|
83
|
+
static fromJSON(data: unknown): MarcRecord;
|
|
79
84
|
toJSON(): SerializedMarcRecord;
|
|
80
|
-
|
|
85
|
+
toXML(pretty?: boolean): string;
|
|
86
|
+
toXmlElement(): XmlElement;
|
|
87
|
+
toLineMarc(): string;
|
|
88
|
+
static validateJSON(data: unknown): SerializedMarcRecord;
|
|
81
89
|
getControlFields(): ControlField[];
|
|
82
90
|
getControlField(tag: string): ControlField | undefined;
|
|
83
91
|
getDataFields(tag?: string | RegExp, indicators?: Indicators): DataField[];
|
|
@@ -210,7 +218,8 @@ declare function serializeMarcXmlCollection(input: MarcRecord[], pretty?: boolea
|
|
|
210
218
|
|
|
211
219
|
declare class MarcRecordSchemaValidationError extends Error {
|
|
212
220
|
readonly errors: ErrorObject[];
|
|
213
|
-
|
|
221
|
+
readonly sourceData?: string | undefined;
|
|
222
|
+
constructor(errors: ErrorObject[], sourceData?: string | undefined);
|
|
214
223
|
}
|
|
215
224
|
declare class MarcParseError extends Error {
|
|
216
225
|
readonly record: string;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { serializeXml, createXmlElement, parseXml } from '@biblioteksentralen/xml-utils';
|
|
2
2
|
import { Ajv } from 'ajv';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
@@ -57,8 +57,14 @@ var DataField = class {
|
|
|
57
57
|
subfields: this.subfields.map((subfield) => subfield.toJSON())
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns a human-readable string representation of this MARC data field.
|
|
62
|
+
*
|
|
63
|
+
* The result is intended for debugging, logging, and test output. The format is not guaranteed to
|
|
64
|
+
* be stable and should not be parsed or relied upon.
|
|
65
|
+
*/
|
|
60
66
|
toString() {
|
|
61
|
-
return `${this.tag} ${this.subfields.map((subfield) => subfield.toString()).join(" ")}`;
|
|
67
|
+
return `${this.tag} ${this.ind1 ?? " "}${this.ind2 ?? " "} ${this.subfields.map((subfield) => subfield.toString()).join(" ")}`;
|
|
62
68
|
}
|
|
63
69
|
};
|
|
64
70
|
var isControlField = (field) => field instanceof ControlField;
|
|
@@ -178,9 +184,10 @@ function createMarcSchema({
|
|
|
178
184
|
|
|
179
185
|
// src/marc-record/errors.ts
|
|
180
186
|
var MarcRecordSchemaValidationError = class extends Error {
|
|
181
|
-
constructor(errors) {
|
|
187
|
+
constructor(errors, sourceData) {
|
|
182
188
|
super("MarcRecord schema validation failed");
|
|
183
189
|
this.errors = errors;
|
|
190
|
+
this.sourceData = sourceData;
|
|
184
191
|
}
|
|
185
192
|
};
|
|
186
193
|
var MarcParseError = class extends Error {
|
|
@@ -189,6 +196,80 @@ var MarcParseError = class extends Error {
|
|
|
189
196
|
this.record = record;
|
|
190
197
|
}
|
|
191
198
|
};
|
|
199
|
+
function buildRecordXml(input) {
|
|
200
|
+
const fields = [
|
|
201
|
+
createXmlElement("leader", { text: input.leader }),
|
|
202
|
+
...input.getControlFields().map(
|
|
203
|
+
(field) => createXmlElement("controlfield", {
|
|
204
|
+
attributes: { tag: field.tag },
|
|
205
|
+
text: field.value
|
|
206
|
+
})
|
|
207
|
+
),
|
|
208
|
+
...input.getDataFields().map(
|
|
209
|
+
(field) => createXmlElement("datafield", {
|
|
210
|
+
attributes: withoutEmptyValues({
|
|
211
|
+
tag: field.tag,
|
|
212
|
+
ind1: field.ind1,
|
|
213
|
+
ind2: field.ind2
|
|
214
|
+
}),
|
|
215
|
+
children: field.subfields.map(
|
|
216
|
+
(subfield) => createXmlElement("subfield", {
|
|
217
|
+
attributes: { code: subfield.code },
|
|
218
|
+
text: subfield.value
|
|
219
|
+
})
|
|
220
|
+
)
|
|
221
|
+
})
|
|
222
|
+
)
|
|
223
|
+
];
|
|
224
|
+
const recordNode = createXmlElement("record", {
|
|
225
|
+
children: fields
|
|
226
|
+
});
|
|
227
|
+
return recordNode;
|
|
228
|
+
}
|
|
229
|
+
function serializeMarcXml(input, pretty = false) {
|
|
230
|
+
const record = buildRecordXml(input);
|
|
231
|
+
record.setAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
|
|
232
|
+
return serializeXml(record, pretty);
|
|
233
|
+
}
|
|
234
|
+
var withoutEmptyValues = (obj) => Object.keys(obj).reduce(
|
|
235
|
+
(acc, key) => obj[key] === void 0 ? { ...acc } : { ...acc, [key]: obj[key] },
|
|
236
|
+
{}
|
|
237
|
+
);
|
|
238
|
+
function serializeMarcXmlCollection(input, pretty = false) {
|
|
239
|
+
const records = input.map(buildRecordXml);
|
|
240
|
+
const collectionNode = createXmlElement("collection", {
|
|
241
|
+
attributes: { xmlns: "http://www.loc.gov/MARC21/slim" },
|
|
242
|
+
children: records
|
|
243
|
+
});
|
|
244
|
+
return serializeXml(collectionNode, pretty);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/marc-record/serializeLineMarc.ts
|
|
248
|
+
function serializeLineMarc(input) {
|
|
249
|
+
const leader = serializer.leader(input.leader);
|
|
250
|
+
const control = input.getControlFields().map(serializer.controlfield).join("");
|
|
251
|
+
const data = input.getDataFields().map(serializer.datafield).join("");
|
|
252
|
+
return `${leader}${control}${data}^
|
|
253
|
+
`;
|
|
254
|
+
}
|
|
255
|
+
var serializer = {
|
|
256
|
+
leader: (leader) => `*LDR${leader}
|
|
257
|
+
`,
|
|
258
|
+
controlfield: (field) => `*${field.tag}${field.value}
|
|
259
|
+
`,
|
|
260
|
+
datafield: (field) => {
|
|
261
|
+
const ind1 = field.ind1 ?? " ";
|
|
262
|
+
const ind2 = field.ind2 ?? " ";
|
|
263
|
+
const subfields = field.subfields.map(
|
|
264
|
+
(subfield) => `$${subfield.code}${escapeSubfieldValue(subfield.value)}`
|
|
265
|
+
).join("");
|
|
266
|
+
return `*${field.tag}${ind1}${ind2}${subfields}
|
|
267
|
+
`;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
var escapeSubfieldValue = (value) => {
|
|
271
|
+
return value.replace(/\n/g, " ").replace(/\$/g, "@{2}");
|
|
272
|
+
};
|
|
192
273
|
|
|
193
274
|
// src/marc-record/MarcRecord.ts
|
|
194
275
|
var validator = new Ajv().compile(createMarcSchema());
|
|
@@ -205,10 +286,9 @@ var MarcRecord = class _MarcRecord {
|
|
|
205
286
|
this.leader = leader;
|
|
206
287
|
this.fields = fields;
|
|
207
288
|
}
|
|
208
|
-
static fromJSON(data
|
|
289
|
+
static fromJSON(data) {
|
|
209
290
|
const { format, leader, fields } = this.validateJSON(
|
|
210
|
-
fixInvalidMarcRecordSerialization(data)
|
|
211
|
-
log
|
|
291
|
+
fixInvalidMarcRecordSerialization(data)
|
|
212
292
|
);
|
|
213
293
|
return new _MarcRecord({
|
|
214
294
|
leader,
|
|
@@ -225,17 +305,23 @@ var MarcRecord = class _MarcRecord {
|
|
|
225
305
|
fields: this.fields.map((field) => field.toJSON())
|
|
226
306
|
};
|
|
227
307
|
}
|
|
228
|
-
|
|
308
|
+
toXML(pretty = false) {
|
|
309
|
+
return serializeMarcXml(this, pretty);
|
|
310
|
+
}
|
|
311
|
+
toXmlElement() {
|
|
312
|
+
return buildRecordXml(this);
|
|
313
|
+
}
|
|
314
|
+
toLineMarc() {
|
|
315
|
+
return serializeLineMarc(this);
|
|
316
|
+
}
|
|
317
|
+
static validateJSON(data) {
|
|
229
318
|
if (validator(data)) {
|
|
230
319
|
return data;
|
|
231
320
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
Data:
|
|
236
|
-
${JSON.stringify(data)}`
|
|
321
|
+
throw new MarcRecordSchemaValidationError(
|
|
322
|
+
validator.errors ?? [],
|
|
323
|
+
JSON.stringify(data)
|
|
237
324
|
);
|
|
238
|
-
throw new MarcRecordSchemaValidationError(validator.errors ?? []);
|
|
239
325
|
}
|
|
240
326
|
getControlFields() {
|
|
241
327
|
return this.fields.filter(isControlField);
|
|
@@ -380,78 +466,4 @@ var marcRecordZodSchema = z.object({
|
|
|
380
466
|
fields: z.array(z.union([controlFieldSchema, dataFieldSchema]))
|
|
381
467
|
});
|
|
382
468
|
|
|
383
|
-
// src/marc-record/serializeLineMarc.ts
|
|
384
|
-
function serializeLineMarc(input) {
|
|
385
|
-
const leader = serializer.leader(input.leader);
|
|
386
|
-
const control = input.getControlFields().map(serializer.controlfield).join("");
|
|
387
|
-
const data = input.getDataFields().map(serializer.datafield).join("");
|
|
388
|
-
return `${leader}${control}${data}^
|
|
389
|
-
`;
|
|
390
|
-
}
|
|
391
|
-
var serializer = {
|
|
392
|
-
leader: (leader) => `*LDR${leader}
|
|
393
|
-
`,
|
|
394
|
-
controlfield: (field) => `*${field.tag}${field.value}
|
|
395
|
-
`,
|
|
396
|
-
datafield: (field) => {
|
|
397
|
-
const ind1 = field.ind1 ?? " ";
|
|
398
|
-
const ind2 = field.ind2 ?? " ";
|
|
399
|
-
const subfields = field.subfields.map(
|
|
400
|
-
(subfield) => `$${subfield.code}${escapeSubfieldValue(subfield.value)}`
|
|
401
|
-
).join("");
|
|
402
|
-
return `*${field.tag}${ind1}${ind2}${subfields}
|
|
403
|
-
`;
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
var escapeSubfieldValue = (value) => {
|
|
407
|
-
return value.replace(/\n/g, " ").replace(/\$/g, "@{2}");
|
|
408
|
-
};
|
|
409
|
-
function buildRecordXml(input) {
|
|
410
|
-
const fields = [
|
|
411
|
-
createXmlElement("leader", { text: input.leader }),
|
|
412
|
-
...input.getControlFields().map(
|
|
413
|
-
(field) => createXmlElement("controlfield", {
|
|
414
|
-
attributes: { tag: field.tag },
|
|
415
|
-
text: field.value
|
|
416
|
-
})
|
|
417
|
-
),
|
|
418
|
-
...input.getDataFields().map(
|
|
419
|
-
(field) => createXmlElement("datafield", {
|
|
420
|
-
attributes: withoutEmptyValues({
|
|
421
|
-
tag: field.tag,
|
|
422
|
-
ind1: field.ind1,
|
|
423
|
-
ind2: field.ind2
|
|
424
|
-
}),
|
|
425
|
-
children: field.subfields.map(
|
|
426
|
-
(subfield) => createXmlElement("subfield", {
|
|
427
|
-
attributes: { code: subfield.code },
|
|
428
|
-
text: subfield.value
|
|
429
|
-
})
|
|
430
|
-
)
|
|
431
|
-
})
|
|
432
|
-
)
|
|
433
|
-
];
|
|
434
|
-
const recordNode = createXmlElement("record", {
|
|
435
|
-
children: fields
|
|
436
|
-
});
|
|
437
|
-
return recordNode;
|
|
438
|
-
}
|
|
439
|
-
function serializeMarcXml(input, pretty = false) {
|
|
440
|
-
const record = buildRecordXml(input);
|
|
441
|
-
record.setAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
|
|
442
|
-
return serializeXml(record, pretty);
|
|
443
|
-
}
|
|
444
|
-
var withoutEmptyValues = (obj) => Object.keys(obj).reduce(
|
|
445
|
-
(acc, key) => obj[key] === void 0 ? { ...acc } : { ...acc, [key]: obj[key] },
|
|
446
|
-
{}
|
|
447
|
-
);
|
|
448
|
-
function serializeMarcXmlCollection(input, pretty = false) {
|
|
449
|
-
const records = input.map(buildRecordXml);
|
|
450
|
-
const collectionNode = createXmlElement("collection", {
|
|
451
|
-
attributes: { xmlns: "http://www.loc.gov/MARC21/slim" },
|
|
452
|
-
children: records
|
|
453
|
-
});
|
|
454
|
-
return serializeXml(collectionNode, pretty);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
469
|
export { ControlField, DataField, MarcParseError, MarcRecord, MarcRecordSchemaValidationError, Subfield, createControlField, createDataField, marcRecordZodSchema, parseMarcXml, serializeLineMarc, serializeMarcXml, serializeMarcXmlCollection };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@biblioteksentralen/marc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "MARC record parser and serializer",
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ajv": "^8.17.1",
|
|
29
|
-
"ts-log": "^2.2.5",
|
|
30
29
|
"zod": "^3.23.8",
|
|
31
30
|
"@biblioteksentralen/xml-utils": "^0.0.3"
|
|
32
31
|
},
|