marc-ts 0.2.0 → 0.4.2

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 CHANGED
@@ -8,9 +8,9 @@
8
8
  ## Features
9
9
 
10
10
  - **Four formats** — ISO2709 binary, MARCXML, MARC-in-JSON, MARCBreaker/marctxt
11
- - **Consistent API** — every format uses `parse*(input) → MarcRecord[]` and `serialize*(records[]) → <native>`
12
- - **Immutable** — all operations return new objects, never mutate
13
- - **Zero dependencies** — works in Node.js and modern browsers
11
+ - **Consistent API** — every format uses `parse*(input) → MarcRecord[]` and `serialize*(records) → output`
12
+ - **Functional-style** — all operations return new objects; originals are never mutated
13
+ - **Zero dependencies** — no runtime deps, including no XML parser. MARCXML has only 5 element types with no arbitrary nesting, so it's parsed with a lightweight hand-rolled tokenizer instead of a full DOM/SAX library. Works in Node.js and modern browsers.
14
14
  - **Fully typed** — strict TypeScript throughout
15
15
 
16
16
  ## Installation
@@ -27,21 +27,15 @@ import { parseMarcXml, serializeMarcXml } from 'marc-ts/xml';
27
27
  import { parseMarcJson, serializeMarcJsonString } from 'marc-ts/json';
28
28
  import { parseMarcTxt, serializeMarcTxt } from 'marc-ts/txt';
29
29
 
30
- // Binary (ISO2709) — splits on 0x1D, returns all records
31
30
  const records = parseMarcBinary(buffer);
32
31
  console.log(title(records[0]));
33
- console.log(author(records[0]));
34
- const binary = serializeMarcBinary(records);
35
32
 
36
- // MARCXML — parses <collection> or bare <record> elements
37
33
  const xmlRecords = parseMarcXml(xmlString);
38
34
  const xml = serializeMarcXml(xmlRecords);
39
35
 
40
- // MARC-in-JSON — accepts array, single object, or JSON string
41
36
  const jsonRecords = parseMarcJson(jsonString);
42
37
  const json = serializeMarcJsonString(jsonRecords);
43
38
 
44
- // MARCBreaker — records separated by blank lines
45
39
  const txtRecords = parseMarcTxt(txtString);
46
40
  const txt = serializeMarcTxt(txtRecords);
47
41
  ```
@@ -52,41 +46,33 @@ const txt = serializeMarcTxt(txtRecords);
52
46
 
53
47
  ```typescript
54
48
  import { parseMarcBinary, serializeMarcBinary } from 'marc-ts';
55
- import type { ParseOptions, SerializeOptions } from 'marc-ts';
56
49
  ```
57
50
 
58
51
  #### `parseMarcBinary(buffer, options?): MarcRecord[]`
59
52
 
60
- Parse a concatenated ISO2709 binary stream. Splits on `0x1D` (RECORD_TERMINATOR) and parses each record. Records that fail to parse are silently skipped in lenient mode; with `strict: true` the first error throws.
61
-
62
- ```typescript
63
- const records = parseMarcBinary(buffer);
64
- const strict = parseMarcBinary(buffer, { strict: true });
65
- ```
66
-
67
- **`ParseOptions`**
53
+ Splits on `0x1D` record terminators and parses each record. Failed records are skipped in lenient mode; `strict: true` throws on the first error.
68
54
 
69
55
  | Option | Type | Default | Description |
70
56
  |--------|------|---------|-------------|
71
57
  | `strict` | `boolean` | `false` | Throw on fatal parse errors instead of skipping |
72
- | `maxWarnings` | `number` | `100` | Stop collecting warnings after this many |
58
+ | `maxWarnings` | `number` | `100` | Stop collecting warnings after this many (per record) |
73
59
 
74
- **Character encoding.** Leader byte 9 controls decoding: `'a'` = UTF-8, `' '` (space) = MARC-8. MARC-8 decoding handles ANSEL Latin, Greek, Hebrew, Cyrillic, Arabic, and subscript/superscript scripts via escape-designated sequences. EACC/CJK coverage is limited (~33 of ~16,000 official triples); records with substantial CJK content will mostly decode to U+FFFD — prefer UTF-8 sources for CJK catalogs.
60
+ Leader byte 9 controls character decoding: `'a'` = UTF-8, `' '` = MARC-8. MARC-8 handles ANSEL Latin, Greek, Hebrew, Cyrillic, Arabic, and sub/superscript scripts. EACC/CJK coverage is minimal (~33 of ~16k triples) — prefer UTF-8 sources for CJK catalogs.
75
61
 
76
- #### `serializeMarcBinary(records, options?): Uint8Array`
62
+ #### `parseMarcBinaryWithWarnings(buffer, options?): ParseBatchResult`
77
63
 
78
- Serialize an array of records to a concatenated ISO2709 binary stream. Each record is individually serialized with its own `0x1D` terminator.
64
+ Same as `parseMarcBinary`, but returns per-record results with warnings. Failed records appear with `record: null`.
79
65
 
80
- ```typescript
81
- const buffer = serializeMarcBinary(records);
82
- const marc8Buffer = serializeMarcBinary(records, { encoding: 'marc8' });
83
- ```
84
-
85
- **`SerializeOptions`**
66
+ #### `serializeMarcBinary(records, options?): Uint8Array`
86
67
 
87
68
  | Option | Type | Default | Description |
88
69
  |--------|------|---------|-------------|
89
70
  | `encoding` | `'utf8' \| 'marc8'` | `'utf8'` | Character encoding; `'marc8'` replaces unsupported Unicode with `?` |
71
+ | `maxWarnings` | `number` | `100` | Stop collecting warnings after this many (per record) |
72
+
73
+ #### `serializeMarcBinaryWithWarnings(records, options?): SerializeBatchResult`
74
+
75
+ Same as `serializeMarcBinary`, but returns per-record serialization warnings alongside the bytes.
90
76
 
91
77
  ---
92
78
 
@@ -98,19 +84,11 @@ import { parseMarcXml, serializeMarcXml } from 'marc-ts/xml';
98
84
 
99
85
  #### `parseMarcXml(xml): MarcRecord[]`
100
86
 
101
- Parse a MARCXML string. Accepts a `<collection>` document, bare `<record>` elements, or namespace-prefixed variants (e.g. `marc:record`). Returns all records found; returns `[]` for empty or record-free input.
102
-
103
- ```typescript
104
- const records = parseMarcXml(xmlString);
105
- ```
87
+ Accepts `<collection>`, bare `<record>` elements, or namespace-prefixed variants. Returns `[]` for empty input.
106
88
 
107
89
  #### `serializeMarcXml(records): string`
108
90
 
109
- Serialize records to a full MARCXML `<collection>` document with XML declaration and MARC21 namespace.
110
-
111
- ```typescript
112
- const xml = serializeMarcXml(records);
113
- ```
91
+ Produces a full MARCXML `<collection>` document with XML declaration and MARC21 namespace.
114
92
 
115
93
  ---
116
94
 
@@ -118,52 +96,18 @@ const xml = serializeMarcXml(records);
118
96
 
119
97
  ```typescript
120
98
  import { parseMarcJson, serializeMarcJson, serializeMarcJsonString } from 'marc-ts/json';
121
- import type { MarcJsonObject } from 'marc-ts/json';
122
99
  ```
123
100
 
124
- The [MARC-in-JSON](https://wiki.code4lib.org/MARCJSONification) format represents each field as a single-key object:
125
-
126
- ```json
127
- {
128
- "leader": "01142cam a2200301 a 4500",
129
- "fields": [
130
- { "001": "5490" },
131
- { "245": { "subfields": [{ "a": "The Hobbit" }], "ind1": "1", "ind2": "0" } }
132
- ]
133
- }
134
- ```
101
+ Implements the [MARC-in-JSON](https://wiki.code4lib.org/MARCJSONification) spec.
135
102
 
136
103
  #### `parseMarcJson(json): MarcRecord[]`
137
104
 
138
- Parse MARC-in-JSON into records. Accepts:
139
- - A JSON string whose top-level value is an array or a single object
140
- - A `MarcJsonObject[]` array
141
- - A single `MarcJsonObject`
142
-
143
- Always returns `MarcRecord[]`. Throws on structural errors.
144
-
145
- ```typescript
146
- const records = parseMarcJson(jsonString); // JSON string (array or single)
147
- const records = parseMarcJson([obj1, obj2]); // plain object array
148
- const records = parseMarcJson(singleObj); // single object → one-element array
149
- ```
105
+ Accepts a JSON string (array or single object), a `MarcJsonObject[]`, or a single `MarcJsonObject`.
150
106
 
151
107
  #### `serializeMarcJson(records): MarcJsonObject[]`
152
108
 
153
- Serialize records to an array of MARC-in-JSON plain objects.
154
-
155
- ```typescript
156
- const objs = serializeMarcJson(records);
157
- ```
158
-
159
109
  #### `serializeMarcJsonString(records): string`
160
110
 
161
- Serialize records directly to a JSON string (a JSON array).
162
-
163
- ```typescript
164
- const json = serializeMarcJsonString(records);
165
- ```
166
-
167
111
  ---
168
112
 
169
113
  ### MARCBreaker / marctxt (`marc-ts/txt`)
@@ -172,49 +116,18 @@ const json = serializeMarcJsonString(records);
172
116
  import { parseMarcTxt, serializeMarcTxt } from 'marc-ts/txt';
173
117
  ```
174
118
 
175
- MARCBreaker is a human-readable line-oriented format. Each field occupies one line; blank indicators are written as `\`; subfields use `$` followed by a single-character code. Records are separated by blank lines:
176
-
177
- ```
178
- =LDR 00706cam a2200217 a 4500
179
- =001 5490
180
- =003 OCoLC
181
- =245 14$aThe Hobbit /$cJ.R.R. Tolkien.
182
- =650 \1$aHobbits (Fictitious characters)$vFiction.
183
- ```
184
-
185
- **Value escaping** — reserved characters in field values are escaped as follows:
186
-
187
- | Character | Escaped form |
188
- |-----------|-------------|
189
- | `$` | `{dollar}` |
190
- | `{` | `{lcub}` |
191
- | `}` | `{rcub}` |
192
- | `\` | `{bsol}` |
119
+ Line-oriented format: one field per line, blank lines between records, `$` for subfield delimiters, `\` for blank indicators.
193
120
 
194
- Embedded newlines in values are replaced with a space on serialize.
121
+ Reserved characters are escaped: `$` `{dollar}`, `{` `{lcub}`, `}` → `{rcub}`, `\` → `{bsol}`.
195
122
 
196
123
  #### `parseMarcTxt(text): MarcRecord[]`
197
124
 
198
- Parse a marctxt string. Accepts `\n` and `\r\n` line endings. Records are separated by blank lines. Returns all records found.
199
-
200
- ```typescript
201
- const records = parseMarcTxt(txtString);
202
- ```
203
-
204
125
  #### `serializeMarcTxt(records): string`
205
126
 
206
- Serialize records to a marctxt string, with records separated by blank lines.
207
-
208
- ```typescript
209
- const txt = serializeMarcTxt(records);
210
- ```
211
-
212
127
  ---
213
128
 
214
129
  ## Convenience Accessors
215
130
 
216
- Extract common bibliographic metadata from any `MarcRecord`:
217
-
218
131
  ```typescript
219
132
  import { title, titleProper, author, edition, publisher, publicationDate,
220
133
  isbn, issn, lccn, subjects, seriesStatement } from 'marc-ts';
@@ -243,46 +156,32 @@ import { getField, getFields, getSubfield, getSubfields, getAllSubfields } from
243
156
  import { isControlField, isDataField } from 'marc-ts';
244
157
  ```
245
158
 
246
- #### `getField(record, tag)` / `getFields(record, tag)`
247
-
248
159
  ```typescript
249
160
  const field = getField(record, '245'); // first match or undefined
250
161
  const fields = getFields(record, '650'); // all matches
251
- ```
252
-
253
- #### `getSubfield(field, code)` / `getSubfields(field, code)`
254
162
 
255
- ```typescript
256
163
  if (field && isDataField(field)) {
257
- const a = getSubfield(field, 'a'); // first $a or undefined
258
- const xs = getSubfields(field, 'x'); // all $x values
164
+ const a = getSubfield(field, 'a');
165
+ const xs = getSubfields(field, 'x');
166
+ const all = getAllSubfields(field); // [{ code, value }, ...]
259
167
  }
260
168
  ```
261
169
 
262
- #### `getAllSubfields(field)`
263
-
264
- ```typescript
265
- const all = getAllSubfields(field); // [{ code, value }, ...]
266
- ```
267
-
268
- ---
269
-
270
170
  ## Wildcard Querying
271
171
 
272
172
  ```typescript
273
173
  import { getFieldsByPattern, getFirstFieldByPattern } from 'marc-ts';
274
174
 
275
175
  const subjects = getFieldsByPattern(record, '6..'); // all 6XX fields
276
- const first7xx = getFirstFieldByPattern(record, '7XX');
277
176
  ```
278
177
 
279
178
  `.` and `X` each match any single digit.
280
179
 
281
180
  ---
282
181
 
283
- ## Field Operations (Immutable)
182
+ ## Field Operations
284
183
 
285
- All operations return a new `MarcRecord` without modifying the original.
184
+ All operations return new objects originals are never mutated.
286
185
 
287
186
  ```typescript
288
187
  import {
@@ -294,11 +193,10 @@ import {
294
193
  const r1 = appendField(record, newField);
295
194
  const r2 = insertFieldBefore(record, '700', newField);
296
195
  const r3 = insertFieldAfter(record, '245', newField);
297
- const r4 = insertGroupedField(record, newField); // maintains MARC block order
196
+ const r4 = insertGroupedField(record, newField); // maintains MARC tag order
298
197
  const r5 = removeFields(record, '650');
299
- const r6 = removeField(record, specificField); // reference equality
198
+ const r6 = removeField(record, specificField); // reference equality
300
199
 
301
- // Subfield operations — return a new DataField
302
200
  const f1 = addSubfield(field, 'b', 'Subtitle');
303
201
  const f2 = removeSubfield(field, 'x');
304
202
  const f3 = replaceSubfield(field, 'a', 'New value');
@@ -330,7 +228,7 @@ import type { MarcRecord, ControlField, DataField, Subfield,
330
228
 
331
229
  ## Development
332
230
 
333
- Requires Node.js **20.19** or **22.12+** (driven by Vite 8). The compiled output targets modern browsers and any actively-supported Node release.
231
+ Requires Node.js **20.19** or **22.12+** (driven by Vite 8).
334
232
 
335
233
  ```bash
336
234
  npm test # run tests
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("./types-CJcxHJff.cjs");var ee=27,m="�",k=new Map([[33,"Ł"],[34,"Ø"],[35,"Đ"],[36,"Þ"],[37,"Æ"],[38,"Œ"],[39,"ʹ"],[40,"·"],[41,"♭"],[42,"®"],[43,"±"],[44,"Ơ"],[45,"Ư"],[46,"ʼ"],[48,"ʻ"],[49,"ł"],[50,"ø"],[51,"đ"],[52,"þ"],[53,"æ"],[54,"œ"],[55,"ʺ"],[56,"ı"],[57,"£"],[58,"ð"],[59,"ơ"],[60,"ư"],[63,"°"]]),W=new Map([[96,"̉"],[97,"̀"],[98,"́"],[99,"̂"],[100,"̃"],[101,"̄"],[102,"̆"],[103,"̇"],[104,"̈"],[105,"̌"],[106,"̊"],[107,"︠"],[108,"︡"],[109,"̕"],[110,"̋"],[111,"̐"],[112,"̧"],[113,"̨"],[114,"̣"],[115,"̤"],[116,"̥"],[117,"̳"],[118,"̲"],[119,"̦"],[120,"̜"],[121,"̮"],[122,"︢"],[123,"︣"],[126,"̓"]]),te=new Map(Array.from(W.entries()).map(([e,t])=>[t,e+128])),ne=new Map(Array.from(k.entries()).map(([e,t])=>[t,e+128])),re=M(65,"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ",97,"αβγδεζηθικλμνξοπρστυφχψω"),ie=M(96,"אבגדהוזחטיךכלםמןנסעףפץצקרשת"),se=M(65,"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",97,"абвгдежзийклмнопрстуфхцчшщъыьэюя"),oe=new Map([[33,"ء"],[34,"آ"],[35,"أ"],[36,"ؤ"],[37,"إ"],[38,"ئ"],[39,"ا"],[40,"ب"],[41,"ة"],[42,"ت"],[43,"ث"],[44,"ج"],[45,"ح"],[46,"خ"],[47,"د"],[48,"ذ"],[49,"ر"],[50,"ز"],[51,"س"],[52,"ش"],[53,"ص"],[54,"ض"],[55,"ط"],[56,"ظ"],[57,"ع"],[58,"غ"],[65,"ف"],[66,"ق"],[67,"ك"],[68,"ل"],[69,"م"],[70,"ن"],[71,"ه"],[72,"و"],[73,"ى"],[74,"ي"]]),ae=new Map([[40,"₍"],[41,"₎"],[43,"₊"],[45,"₋"],[48,"₀"],[49,"₁"],[50,"₂"],[51,"₃"],[52,"₄"],[53,"₅"],[54,"₆"],[55,"₇"],[56,"₈"],[57,"₉"]]),ce=new Map([[40,"⁽"],[41,"⁾"],[43,"⁺"],[45,"⁻"],[48,"⁰"],[49,"¹"],[50,"²"],[51,"³"],[52,"⁴"],[53,"⁵"],[54,"⁶"],[55,"⁷"],[56,"⁸"],[57,"⁹"],[110,"ⁿ"]]),le=new Map([[2171169,"一"],[2171170,"丁"],[2171171,"七"],[2171172,"万"],[2171173,"丈"],[2171174,"三"],[2171175,"上"],[2171176,"下"],[2171177,"不"],[2171178,"与"],[2171179,"丐"],[2171180,"丑"],[2171181,"且"],[2171182,"世"],[2171183,"丘"],[2171184,"丙"],[2171185,"业"],[2171186,"丛"],[2171187,"东"],[2171188,"丝"],[2171189,"丞"],[2171190,"丟"],[2171191,"丠"],[2171192,"両"],[2171193,"丢"],[2171194,"两"],[2171195,"严"],[2171196,"並"],[2171197,"丧"],[2171198,"丨"],[2171199,"个"],[2171200,"丫"],[2171201,"中"],[2171202,"丰"]]),de={ascii:new Map,ansel:fe(k,W),greek:re,hebrew:ie,cyrillic:se,arabic:oe,subscript:ae,superscript:ce};function M(...e){const t=new Map;for(let n=0;n<e.length;n+=2){const r=e[n],i=e[n+1];Array.from(i).forEach((s,o)=>t.set(r+o,s))}return t}function fe(...e){const t=new Map;for(const n of e)for(const[r,i]of n)t.set(r,i);return t}function T(e){const t=e.codePointAt(0);return t>=768&&t<=879||t>=65056&&t<=65071}function I(e,t){return t?e-128:e}function ue(e,t,n){const r=I(e,n);return t==="ascii"?r>=32&&r<=126?String.fromCharCode(r):m:de[t].get(r)??m}function ge(e,t,n){if(t+2>=e.length)return{char:m,next:e.length};const r=I(e[t],n),i=I(e[t+1],n),s=I(e[t+2],n),o=r<<16|i<<8|s;return{char:le.get(o)??m,next:t+3}}function he(e,t,n){if(t+1>=e.length)return{char:m,next:e.length};const r=e[t+1];let i,s;if(r===40||r===44)i="g0",s=t+2;else if(r===41||r===45)i="g1",s=t+2;else if(r===36){const l=e[t+2];if(l===void 0)return{char:m,next:e.length};l===40||l===44?(i="g0",s=t+3):l===41||l===45?(i="g1",s=t+3):(i="g0",s=t+2)}else return{char:m,next:t+2};if(s>=e.length)return{char:m,next:e.length};let o=e[s];if(o===33){if(s++,s>=e.length)return{char:m,next:e.length};o=e[s]}const c=Ee(o);return c?{char:"",next:pe(n,i,c,s+1)}:{char:m,next:s+1}}function pe(e,t,n,r){return e[t]=n,r}function Ee(e){switch(e){case 49:return"eacc";case 50:return"hebrew";case 51:return"arabic";case 52:return"cyrillic";case 66:return"ascii";case 69:return"ansel";case 78:return"cyrillic";case 81:return"greek";case 83:return"greek";case 98:return"subscript";case 112:return"superscript";default:return}}function j(e){const t={g0:"ascii",g1:"ansel"},n=[];let r="",i=0;const s=o=>{if(o){if(T(o)){r+=o;return}n.push(o+r),r=""}};for(;i<e.length;){const o=e[i];if(o===ee){const d=he(e,i,t);s(d.char),i=d.next;continue}if(o<32){s(String.fromCharCode(o)),i++;continue}const c=o>=160,l=c?t.g1:t.g0;if(l==="eacc"){const d=ge(e,i,c);s(d.char),i=d.next;continue}s(ue(o,l,c)),i++}return r&&n.push(r),n.join("")}function we(e){return L(e).bytes}function L(e){const t=e.normalize("NFD"),n=[];let r=0,i=0;for(;i<t.length;){const s=t.codePointAt(i),o=t[i];if(T(o)){n.push(63),r++,i++;continue}let c=i+(s>65535?2:1);const l=[];for(;c<t.length&&T(t[c]);){const d=te.get(t[c]);d!==void 0?l.push(d):(l.push(63),r++),c++}if(n.push(...l),s<128)n.push(s);else{const d=ne.get(o);d!==void 0?n.push(d):(n.push(63),r++)}i=c}return{bytes:new Uint8Array(n),lossyCount:r}}var B=31,H=30,y=24,A=12,C=3,U=4,N=new TextDecoder("utf-8",{fatal:!1});function q(e){return N.decode(e)}function z(e,t=16){const n=e.slice(0,t),r=Array.from(n,i=>i.toString(16).padStart(2,"0")).join(" ");return e.length>t?`${r} … (${e.length} bytes)`:r}function O(e,t={}){const n=t.strict??!1,r=t.maxWarnings??100,i=[];if(e.length<y+1){const a=h("truncated_record",`Record too short: ${e.length} bytes`);if(n)throw new Error(a.message);return i.push(a),{record:null,warnings:i}}const s=Se(e);if(!be(s,i,n)&&(n||i.length>=r))return{record:null,warnings:i};const o=parseInt(s.substring(0,5),10);if(isNaN(o)||o>e.length){const a=h("invalid_leader",`Invalid record length in leader: ${s.substring(0,5)}`);if(n)throw new Error(a.message);i.push(a)}else if(o<e.length){const a=h("truncated_record",`Buffer is longer than the record length declared in the leader: leader says ${o}, buffer is ${e.length} bytes. Trailing bytes ignored (likely a concatenated stream — split on 0x1D first).`);if(n)throw new Error(a.message);i.push(a),e=e.slice(0,o)}const c=parseInt(s.substring(12,17),10);if(isNaN(c)){const a=h("invalid_leader",`Invalid base address in leader: ${s.substring(12,17)}`);if(n)throw new Error(a.message);return i.push(a),{record:null,warnings:i}}const l=y,d=e.indexOf(H,l);if(d===-1){const a=h("invalid_directory","Directory terminator not found");if(n)throw new Error(a.message);return i.push(a),{record:null,warnings:i}}const g=Fe(e.slice(l,d),i,n,r);if(g.length===0){const a=h("invalid_directory","No directory entries found");if(n)throw new Error(a.message);return i.push(a),{record:null,warnings:i}}const f=s[9]===" ";if(s[9]!==" "&&s[9]!=="a"){const a=h("invalid_leader",`Leader position 9 (encoding flag) is '${s[9]}'; expected 'a' (UTF-8) or ' ' (MARC-8). Defaulting to UTF-8.`);if(n)throw new Error(a.message);i.push(a)}return{record:{leader:s,fields:ye(e,g,c,f?j:a=>N.decode(a),i,n,r)},warnings:i}}var ve=29;function me(e,t){const n=[];let r=0;for(let i=0;i<e.length;i++)if(e[i]===ve){const s=e.slice(r,i+1);if(s.length>0){const o=O(s,t);o.record&&n.push(o.record)}r=i+1}if(r<e.length){const i=O(e.slice(r),t);i.record&&n.push(i.record)}return n}function Se(e){const t=e.slice(0,y);return N.decode(t)}function be(e,t,n){if(e.length!==y){const r=h("invalid_leader",`Leader length is ${e.length}, expected ${y}`);if(n)throw new Error(r.message);return t.push(r),!1}if(e[10]!=="2"){const r=h("invalid_leader",`Leader position 10 (indicator count) is '${e[10]}', expected '2'`);t.push(r)}if(e[11]!=="2"){const r=h("invalid_leader",`Leader position 11 (subfield code length) is '${e[11]}', expected '2'`);t.push(r)}return!0}function Fe(e,t,n,r){const i=[];for(let s=0;s<e.length;s+=A){if(t.length>=r){t.push(h("truncated_record",`Directory parsing halted after reaching maxWarnings limit (${r}); remaining ${e.length-s} bytes of directory not parsed.`));break}if(s+A>e.length)break;const o=e.slice(s,s+A),c=N.decode(o),l=c.substring(0,C),d=c.substring(C,C+U),g=c.substring(C+U,A),f=parseInt(d,10),a=parseInt(g,10);if(isNaN(f)||isNaN(a)){const E=h("invalid_directory",`Invalid directory entry for tag ${l}: length=${d}, position=${g}`);if(n)throw new Error(E.message);t.push(E);continue}i.push({tag:l,fieldLength:f,startingPosition:a})}return i}function ye(e,t,n,r,i,s,o){const c=[];for(const l of t){if(i.length>=o){i.push(h("truncated_record",`Field parsing halted after reaching maxWarnings limit (${o}); not all directory entries were processed.`,void 0,l.tag));break}const d=n+l.startingPosition,g=d+l.fieldLength-1;if(d>=e.length||g>e.length){const a=h("invalid_field",`Field ${l.tag} out of bounds: start=${d}, end=${g}, buffer length=${e.length}`,d,l.tag);if(s)throw new Error(a.message);i.push(a);continue}let f;if(e[g]!==H){const a=h("invalid_field",`Field ${l.tag} does not end with a field terminator at byte ${g} (found 0x${(e[g]??0).toString(16).padStart(2,"0")}); using the full declared length without stripping a terminator byte.`,d,l.tag);if(s)throw new Error(a.message);i.push(a),f=e.slice(d,d+l.fieldLength)}else f=e.slice(d,g);if(l.tag.startsWith("00")){try{const a=r(f);c.push({tag:l.tag,data:a})}catch(a){const E=h("encoding_error",`Failed to decode control field ${l.tag}: ${a instanceof Error?a.message:String(a)}. Raw bytes (hex): ${z(f)}.`,d,l.tag);if(s)throw new Error(E.message);i.push(E),c.push({tag:l.tag,data:q(f)})}continue}if(f.length<2){const a=h("invalid_field",`Data field ${l.tag} too short for indicators: ${f.length} bytes`,d,l.tag);if(s)throw new Error(a.message);i.push(a);continue}try{const a=String.fromCharCode(f[0]??0),E=String.fromCharCode(f[1]??0),$=$e(f.slice(2),r,l.tag,i,s,o);c.push({tag:l.tag,indicator1:a,indicator2:E,subfields:$})}catch(a){const E=h("invalid_field",`Failed to parse data field ${l.tag}: ${a instanceof Error?a.message:String(a)}`,d,l.tag);if(s)throw new Error(E.message);i.push(E)}}return c}function $e(e,t,n,r,i,s){const o=[];let c=0;for(;c<e.length;){if(r.length>=s){r.push(h("truncated_record",`Subfield parsing halted after reaching maxWarnings limit (${s}) in field ${n}; not all subfields were processed.`,void 0,n));break}if(e[c]!==B){const f=h("invalid_field",`Expected subfield delimiter in field ${n} at position ${c}`,void 0,n);if(i)throw new Error(f.message);r.push(f);break}if(c++,c>=e.length)break;const l=String.fromCharCode(e[c]??0);c++;const d=c;for(;c<e.length&&e[c]!==B;)c++;const g=e.slice(d,c);try{const f=t(g);o.push({code:l,value:f})}catch(f){const a=h("encoding_error",`Failed to decode subfield ${n}$${l}: ${f instanceof Error?f.message:String(f)}. Raw bytes (hex): ${z(g)}.`,void 0,n);if(i)throw new Error(a.message);r.push(a),o.push({code:l,value:q(g)})}}return o}function h(e,t,n,r){return{type:e,message:t,position:n,tag:r}}function J(e,t,n,r){return{type:e,message:t,position:n,tag:r}}var Ae=31,P=30,Ce=29,_=24,Ie=3,_e=4,Ne=5;function Re(e,t={}){return De(e,t).bytes}function De(e,t={}){Te(e);const n=[],r=t.encoding==="marc8",i=new TextEncoder,s=r?(v,S)=>{const b=L(v);return b.lossyCount>0&&n.push(J("encoding_error",`MARC-8 encoding substituted ${b.lossyCount} character(s) with '?' because they have no MARC-8 equivalent.`,void 0,S)),b.bytes}:v=>i.encode(v),o=[],c=[];let l=0;for(const v of e.fields){const S=Me(v,Q=>s(Q,v.tag)),b=S.length+1,X=v.tag.padEnd(Ie," ")+b.toString().padStart(_e,"0")+l.toString().padStart(Ne,"0");o.push(X),c.push(S),c.push(new Uint8Array([P])),l+=b}const d=i.encode(o.join("")),g=new Uint8Array(d.length+1);g.set(d),g[d.length]=P;const f=_+g.length,a=c.reduce((v,S)=>v+S.length,0),E=new Uint8Array(a);let $=0;for(const v of c)E.set(v,$),$+=v.length;const R=f+a+1,V=Le(e.leader,R,f,r),F=new Uint8Array(R);return F.set(i.encode(V),0),F.set(g,_),F.set(E,f),F[R-1]=Ce,{bytes:F,warnings:n}}function D(e){const t=e.charCodeAt(0);return t>=32&&t<=126}function Te(e){for(const t of e.fields){if(typeof t.tag!="string"||t.tag.length!==3)throw new Error(`MARC field tag must be exactly 3 characters; got ${JSON.stringify(t.tag)}`);if(!u.isControlField(t)){if(t.indicator1.length!==1)throw new Error(`Field ${t.tag} indicator1 must be exactly 1 character; got ${JSON.stringify(t.indicator1)}`);if(!D(t.indicator1))throw new Error(`Field ${t.tag} indicator1 must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(t.indicator1)}`);if(t.indicator2.length!==1)throw new Error(`Field ${t.tag} indicator2 must be exactly 1 character; got ${JSON.stringify(t.indicator2)}`);if(!D(t.indicator2))throw new Error(`Field ${t.tag} indicator2 must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(t.indicator2)}`);for(const n of t.subfields){if(n.code.length!==1)throw new Error(`Field ${t.tag} subfield code must be exactly 1 character; got ${JSON.stringify(n.code)}`);if(!D(n.code))throw new Error(`Field ${t.tag} subfield code must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(n.code)}`)}}}}function Me(e,t){if(u.isControlField(e))return t(e.data);const n=[new Uint8Array([e.indicator1.charCodeAt(0),e.indicator2.charCodeAt(0)])];for(const o of e.subfields){const c=new Uint8Array([Ae,o.code.charCodeAt(0)]);n.push(c,t(o.value))}const r=n.reduce((o,c)=>o+c.length,0),i=new Uint8Array(r);let s=0;for(const o of n)i.set(o,s),s+=o.length;return i}function Le(e,t,n,r){let i=e.padEnd(_," ").substring(0,_);const s=t.toString().padStart(5,"0");if(s.length>5)throw new Error(`Record length ${t} exceeds maximum (99999)`);i=s+i.substring(5);const o=n.toString().padStart(5,"0");if(o.length>5)throw new Error(`Base address ${n} exceeds maximum (99999)`);return i=i.substring(0,12)+o+i.substring(17),i=i.substring(0,9)+(r?" ":"a")+i.substring(10),i}function xe(e,t={}){const n=e.map(o=>Re(o,t)),r=n.reduce((o,c)=>o+c.length,0),i=new Uint8Array(r);let s=0;for(const o of n)i.set(o,s),s+=o.length;return i}function w(e,t){return e.fields.find(n=>n.tag===t)}function Be(e,t){return e.fields.filter(n=>n.tag===t)}function p(e,t){return e.subfields.find(n=>n.code===t)?.value}function Ue(e,t){return e.subfields.filter(n=>n.code===t).map(n=>n.value)}function Oe(e){return e.subfields.map(t=>({code:t.code,value:t.value}))}function Pe(e){const t=w(e,"245");if(!t||!u.isDataField(t))return;const n=p(t,"a")??"",r=p(t,"b")??"";return(n+" "+r).trim()||void 0}function Ge(e){const t=w(e,"245");if(!(!t||!u.isDataField(t)))return p(t,"a")}function ke(e){const t=w(e,"100");if(t&&u.isDataField(t))return p(t,"a");const n=w(e,"110");if(n&&u.isDataField(n))return p(n,"a")}function We(e){const t=w(e,"250");if(!(!t||!u.isDataField(t)))return p(t,"a")}function je(e){const t=w(e,"264");if(t&&u.isDataField(t)){const r=p(t,"b");if(r)return r}const n=w(e,"260");if(n&&u.isDataField(n))return p(n,"b")}function He(e){const t=w(e,"264");if(t&&u.isDataField(t)){const r=p(t,"c");if(r)return r}const n=w(e,"260");if(n&&u.isDataField(n))return p(n,"c")}function qe(e){const t=[];for(const n of e.fields)if(n.tag==="020"&&u.isDataField(n)){const r=p(n,"a");r&&t.push(r)}return t}function ze(e){const t=w(e,"022");if(!(!t||!u.isDataField(t)))return p(t,"a")}function Je(e){const t=w(e,"010");if(!(!t||!u.isDataField(t)))return p(t,"a")}function Ye(e){const t=[];for(const n of e.fields)if(n.tag.startsWith("6")&&u.isDataField(n)){const r=p(n,"a");r&&t.push(r)}return t}function Ze(e){const t=w(e,"490");if(!(!t||!u.isDataField(t)))return p(t,"a")}function Y(e,t){if(e.length!==3||t.length!==3)return!1;for(let n=0;n<3;n++){const r=t[n],i=e[n];if(r==="."||r?.toUpperCase()==="X"){if(i&&!/\d/.test(i))return!1;continue}if(r!==i)return!1}return!0}function Ke(e,t){return e.fields.filter(n=>Y(n.tag,t))}function Ve(e,t){return e.fields.find(n=>Y(n.tag,t))}function x(e,t){return{...e,fields:[...e.fields,t]}}function Xe(e,t,n){const r=e.fields.findIndex(s=>s.tag===t);if(r===-1)return x(e,n);const i=Array.from(e.fields);return i.splice(r,0,n),{...e,fields:i}}function Qe(e,t,n){const r=e.fields.findIndex(s=>s.tag===t);if(r===-1)return x(e,n);const i=Array.from(e.fields);return i.splice(r+1,0,n),{...e,fields:i}}function et(e,t){const n=parseInt(t.tag,10);let r=e.fields.length;for(let s=0;s<e.fields.length;s++){const o=e.fields[s];if(o&&parseInt(o.tag,10)>n){r=s;break}}const i=Array.from(e.fields);return i.splice(r,0,t),{...e,fields:i}}function tt(e,t){return{...e,fields:e.fields.filter(n=>n.tag!==t)}}function nt(e,t){return{...e,fields:e.fields.filter(n=>n!==t)}}function Z(e,t,n){return{...e,subfields:[...e.subfields,{code:t,value:n}]}}function rt(e,t){return{...e,subfields:e.subfields.filter(n=>n.code!==t)}}function it(e,t,n){const r=e.subfields.findIndex(s=>s.code===t);if(r===-1)return Z(e,t,n);const i=[...e.subfields];return i[r]={code:t,value:n},{...e,subfields:i}}function st(e){const t=new Array(e.fields.length);for(let n=0;n<e.fields.length;n++){const r=e.fields[n];if(u.isControlField(r))t[n]={tag:r.tag,data:r.data};else{const i=new Array(r.subfields.length);for(let s=0;s<r.subfields.length;s++){const o=r.subfields[s];i[s]={code:o.code,value:o.value}}t[n]={tag:r.tag,indicator1:r.indicator1,indicator2:r.indicator2,subfields:i}}}return{leader:e.leader,fields:t}}function ot(e,t,n=!1){if(e.leader!==t.leader||e.fields.length!==t.fields.length)return!1;const r=n?[...e.fields].sort(G):e.fields,i=n?[...t.fields].sort(G):t.fields;for(let s=0;s<r.length;s++){const o=r[s],c=i[s];if(!o||!c||!K(o,c))return!1}return!0}function K(e,t){if(e.tag!==t.tag)return!1;if(u.isControlField(e)&&u.isControlField(t))return e.data===t.data;if(!u.isControlField(e)&&!u.isControlField(t)){if(e.indicator1!==t.indicator1||e.indicator2!==t.indicator2||e.subfields.length!==t.subfields.length)return!1;for(let n=0;n<e.subfields.length;n++){const r=e.subfields[n],i=t.subfields[n];if(!r||!i||r.code!==i.code||r.value!==i.value)return!1}return!0}return!1}function G(e,t){return e.tag.localeCompare(t.tag)}exports.addSubfield=Z;exports.appendField=x;exports.author=ke;exports.cloneRecord=st;exports.createWarning=J;exports.edition=We;exports.fieldsEqual=K;exports.getAllSubfields=Oe;exports.getField=w;exports.getFields=Be;exports.getFieldsByPattern=Ke;exports.getFirstFieldByPattern=Ve;exports.getSubfield=p;exports.getSubfields=Ue;exports.insertFieldAfter=Qe;exports.insertFieldBefore=Xe;exports.insertGroupedField=et;exports.isControlField=u.isControlField;exports.isDataField=u.isDataField;exports.isbn=qe;exports.issn=ze;exports.lccn=Je;exports.marc8ToUnicode=j;exports.parseMarcBinary=me;exports.publicationDate=He;exports.publisher=je;exports.recordsEqual=ot;exports.removeField=nt;exports.removeFields=tt;exports.removeSubfield=rt;exports.replaceSubfield=it;exports.serializeMarcBinary=xe;exports.seriesStatement=Ze;exports.subjects=Ye;exports.title=Pe;exports.titleProper=Ge;exports.unicodeToMarc8=we;exports.unicodeToMarc8WithStats=L;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("./types-CsOhH4OF.cjs"),G=require("./warnings-6yoB06xI.cjs");var ne=27,v="�",k=new Map([[33,"Ł"],[34,"Ø"],[35,"Đ"],[36,"Þ"],[37,"Æ"],[38,"Œ"],[39,"ʹ"],[40,"·"],[41,"♭"],[42,"®"],[43,"±"],[44,"Ơ"],[45,"Ư"],[46,"ʼ"],[48,"ʻ"],[49,"ł"],[50,"ø"],[51,"đ"],[52,"þ"],[53,"æ"],[54,"œ"],[55,"ʺ"],[56,"ı"],[57,"£"],[58,"ð"],[59,"ơ"],[60,"ư"],[63,"°"]]),q=new Map([[96,"̉"],[97,"̀"],[98,"́"],[99,"̂"],[100,"̃"],[101,"̄"],[102,"̆"],[103,"̇"],[104,"̈"],[105,"̌"],[106,"̊"],[107,"︠"],[108,"︡"],[109,"̕"],[110,"̋"],[111,"̐"],[112,"̧"],[113,"̨"],[114,"̣"],[115,"̤"],[116,"̥"],[117,"̳"],[118,"̲"],[119,"̦"],[120,"̜"],[121,"̮"],[122,"︢"],[123,"︣"],[126,"̓"]]),re=new Map(Array.from(q.entries()).map(([e,t])=>[t,e+128])),ie=new Map(Array.from(k.entries()).map(([e,t])=>[t,e+128])),se=T(65,"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ",97,"αβγδεζηθικλμνξοπρστυφχψω"),oe=T(96,"אבגדהוזחטיךכלםמןנסעףפץצקרשת"),ae=T(65,"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",97,"абвгдежзийклмнопрстуфхцчшщъыьэюя"),ce=new Map([[33,"ء"],[34,"آ"],[35,"أ"],[36,"ؤ"],[37,"إ"],[38,"ئ"],[39,"ا"],[40,"ب"],[41,"ة"],[42,"ت"],[43,"ث"],[44,"ج"],[45,"ح"],[46,"خ"],[47,"د"],[48,"ذ"],[49,"ر"],[50,"ز"],[51,"س"],[52,"ش"],[53,"ص"],[54,"ض"],[55,"ط"],[56,"ظ"],[57,"ع"],[58,"غ"],[65,"ف"],[66,"ق"],[67,"ك"],[68,"ل"],[69,"م"],[70,"ن"],[71,"ه"],[72,"و"],[73,"ى"],[74,"ي"]]),le=new Map([[40,"₍"],[41,"₎"],[43,"₊"],[45,"₋"],[48,"₀"],[49,"₁"],[50,"₂"],[51,"₃"],[52,"₄"],[53,"₅"],[54,"₆"],[55,"₇"],[56,"₈"],[57,"₉"]]),de=new Map([[40,"⁽"],[41,"⁾"],[43,"⁺"],[45,"⁻"],[48,"⁰"],[49,"¹"],[50,"²"],[51,"³"],[52,"⁴"],[53,"⁵"],[54,"⁶"],[55,"⁷"],[56,"⁸"],[57,"⁹"],[110,"ⁿ"]]),fe=new Map([[2171169,"一"],[2171170,"丁"],[2171171,"七"],[2171172,"万"],[2171173,"丈"],[2171174,"三"],[2171175,"上"],[2171176,"下"],[2171177,"不"],[2171178,"与"],[2171179,"丐"],[2171180,"丑"],[2171181,"且"],[2171182,"世"],[2171183,"丘"],[2171184,"丙"],[2171185,"业"],[2171186,"丛"],[2171187,"东"],[2171188,"丝"],[2171189,"丞"],[2171190,"丟"],[2171191,"丠"],[2171192,"両"],[2171193,"丢"],[2171194,"两"],[2171195,"严"],[2171196,"並"],[2171197,"丧"],[2171198,"丨"],[2171199,"个"],[2171200,"丫"],[2171201,"中"],[2171202,"丰"]]),ue={ascii:new Map,ansel:ge(k,q),greek:se,hebrew:oe,cyrillic:ae,arabic:ce,subscript:le,superscript:de};function T(...e){const t=new Map;for(let n=0;n<e.length;n+=2){const i=e[n],r=e[n+1];Array.from(r).forEach((s,o)=>t.set(i+o,s))}return t}function ge(...e){const t=new Map;for(const n of e)for(const[i,r]of n)t.set(i,r);return t}function D(e){const t=e.codePointAt(0);return t>=768&&t<=879||t>=65056&&t<=65071}function C(e,t){return t?e-128:e}function he(e,t,n){const i=C(e,n);return t==="ascii"?i>=32&&i<=126?String.fromCharCode(i):v:ue[t].get(i)??v}function pe(e,t,n){if(t+2>=e.length)return{char:v,next:e.length};const i=C(e[t],n),r=C(e[t+1],n),s=C(e[t+2],n),o=i<<16|r<<8|s;return{char:fe.get(o)??v,next:t+3}}function we(e,t,n){if(t+1>=e.length)return{char:v,next:e.length};const i=e[t+1];let r,s;if(i===40||i===44)r="g0",s=t+2;else if(i===41||i===45)r="g1",s=t+2;else if(i===36){const l=e[t+2];if(l===void 0)return{char:v,next:e.length};l===40||l===44?(r="g0",s=t+3):l===41||l===45?(r="g1",s=t+3):(r="g0",s=t+2)}else return{char:v,next:t+2};if(s>=e.length)return{char:v,next:e.length};let o=e[s];if(o===33){if(s++,s>=e.length)return{char:v,next:e.length};o=e[s]}const a=me(o);return a?{char:"",next:Ee(n,r,a,s+1)}:{char:v,next:s+1}}function Ee(e,t,n,i){return e[t]=n,i}function me(e){switch(e){case 49:return"eacc";case 50:return"hebrew";case 51:return"arabic";case 52:return"cyrillic";case 66:return"ascii";case 69:return"ansel";case 78:return"cyrillic";case 81:return"greek";case 83:return"greek";case 98:return"subscript";case 112:return"superscript";default:return}}function z(e){const t={g0:"ascii",g1:"ansel"},n=[];let i="",r=0;const s=o=>{if(o){if(D(o)){i+=o;return}n.push(o+i),i=""}};for(;r<e.length;){const o=e[r];if(o===ne){const d=we(e,r,t);s(d.char),r=d.next;continue}if(o<32){s(String.fromCharCode(o)),r++;continue}const a=o>=160,l=a?t.g1:t.g0;if(l==="eacc"){const d=pe(e,r,a);s(d.char),r=d.next;continue}s(he(o,l,a)),r++}return i&&n.push(i),n.join("")}function ve(e){return x(e).bytes}function x(e){const t=e.normalize("NFD"),n=[];let i=0,r=0;for(;r<t.length;){const s=t.codePointAt(r),o=t[r];if(D(o)){n.push(63),i++,r++;continue}let a=r+(s>65535?2:1);const l=[];for(;a<t.length&&D(t[a]);){const d=re.get(t[a]);d!==void 0?l.push(d):(l.push(63),i++),a++}if(n.push(...l),s<128)n.push(s);else{const d=ie.get(o);d!==void 0?n.push(d):(n.push(63),i++)}r=a}return{bytes:new Uint8Array(n),lossyCount:i}}var U=31,j=30,$=24,A=12,O=3,R=new TextDecoder("utf-8",{fatal:!1});function H(e){return R.decode(e)}function J(e,t=16){const n=e.slice(0,t),i=Array.from(n,r=>r.toString(16).padStart(2,"0")).join(" ");return e.length>t?`${i} … (${e.length} bytes)`:i}function I(e,t={}){const n=t.strict??!1,i=t.maxWarnings??100,r=[];if(e.length<25){const c=g("truncated_record",`Record too short: ${e.length} bytes`);if(n)throw new Error(c.message);return r.push(c),{record:null,warnings:r}}const s=Fe(e);if(!ye(s,r,n)&&(n||r.length>=i))return{record:null,warnings:r};const o=parseInt(s.substring(0,5),10);if(isNaN(o)||o>e.length){const c=g("invalid_leader",`Invalid record length in leader: ${s.substring(0,5)}`);if(n)throw new Error(c.message);r.push(c)}else if(o<e.length){const c=g("truncated_record",`Buffer is longer than the record length declared in the leader: leader says ${o}, buffer is ${e.length} bytes. Trailing bytes ignored (likely a concatenated stream — split on 0x1D first).`);if(n)throw new Error(c.message);r.push(c),e=e.slice(0,o)}const a=parseInt(s.substring(12,17),10);if(isNaN(a)){const c=g("invalid_leader",`Invalid base address in leader: ${s.substring(12,17)}`);if(n)throw new Error(c.message);return r.push(c),{record:null,warnings:r}}const l=$,d=e.indexOf(j,l);if(d===-1){const c=g("invalid_directory","Directory terminator not found");if(n)throw new Error(c.message);return r.push(c),{record:null,warnings:r}}const h=Ae(e.slice(l,d),r,n,i);if(h.length===0){const c=g("invalid_directory","No directory entries found");if(n)throw new Error(c.message);return r.push(c),{record:null,warnings:r}}const f=s[9]===" ";if(s[9]!==" "&&s[9]!=="a"){const c=g("invalid_leader",`Leader position 9 (encoding flag) is '${s[9]}'; expected 'a' (UTF-8) or ' ' (MARC-8). Defaulting to UTF-8.`);if(n)throw new Error(c.message);r.push(c)}return{record:{leader:s,fields:Ce(e,h,a,f?z:c=>R.decode(c),r,n,i)},warnings:r}}var Y=29;function Se(e,t){const n=[];let i=0;for(let r=0;r<e.length;r++)if(e[r]===Y){const s=e.slice(i,r+1);if(s.length>0){const o=I(s,t);o.record&&n.push(o.record)}i=r+1}if(i<e.length){const r=I(e.slice(i),t);r.record&&n.push(r.record)}return n}function be(e,t){const n=[];let i=0;for(let r=0;r<e.length;r++)if(e[r]===Y){const s=e.slice(i,r+1);s.length>0&&n.push(I(s,t)),i=r+1}if(i<e.length){const r=e.slice(i);n.push(I(r,t))}return{results:n}}function Fe(e){const t=e.slice(0,$);return R.decode(t)}function ye(e,t,n){if(e.length!==$){const i=g("invalid_leader",`Leader length is ${e.length}, expected ${$}`);if(n)throw new Error(i.message);return t.push(i),!1}if(e[10]!=="2"){const i=g("invalid_leader",`Leader position 10 (indicator count) is '${e[10]}', expected '2'`);t.push(i)}if(e[11]!=="2"){const i=g("invalid_leader",`Leader position 11 (subfield code length) is '${e[11]}', expected '2'`);t.push(i)}return!0}function Ae(e,t,n,i){const r=[];for(let s=0;s<e.length;s+=A){if(t.length>=i){t.push(g("truncated_record",`Directory parsing halted after reaching maxWarnings limit (${i}); remaining ${e.length-s} bytes of directory not parsed.`));break}if(s+A>e.length)break;const o=e.slice(s,s+A),a=R.decode(o),l=a.substring(0,O),d=a.substring(O,7),h=a.substring(7,A),f=parseInt(d,10),c=parseInt(h,10);if(isNaN(f)||isNaN(c)){const w=g("invalid_directory",`Invalid directory entry for tag ${l}: length=${d}, position=${h}`);if(n)throw new Error(w.message);t.push(w);continue}r.push({tag:l,fieldLength:f,startingPosition:c})}return r}function Ce(e,t,n,i,r,s,o){const a=[];for(const l of t){if(r.length>=o){r.push(g("truncated_record",`Field parsing halted after reaching maxWarnings limit (${o}); not all directory entries were processed.`,void 0,l.tag));break}const d=n+l.startingPosition,h=d+l.fieldLength-1;if(d>=e.length||h>e.length){const c=g("invalid_field",`Field ${l.tag} out of bounds: start=${d}, end=${h}, buffer length=${e.length}`,d,l.tag);if(s)throw new Error(c.message);r.push(c);continue}let f;if(e[h]!==j){const c=g("invalid_field",`Field ${l.tag} does not end with a field terminator at byte ${h} (found 0x${(e[h]??0).toString(16).padStart(2,"0")}); using the full declared length without stripping a terminator byte.`,d,l.tag);if(s)throw new Error(c.message);r.push(c),f=e.slice(d,d+l.fieldLength)}else f=e.slice(d,h);if(l.tag.startsWith("00")){try{const c=i(f);a.push({tag:l.tag,data:c})}catch(c){const w=g("encoding_error",`Failed to decode control field ${l.tag}: ${c instanceof Error?c.message:String(c)}. Raw bytes (hex): ${J(f)}.`,d,l.tag);if(s)throw new Error(w.message);r.push(w),a.push({tag:l.tag,data:H(f)})}continue}if(f.length<2){const c=g("invalid_field",`Data field ${l.tag} too short for indicators: ${f.length} bytes`,d,l.tag);if(s)throw new Error(c.message);r.push(c);continue}try{const c=String.fromCharCode(f[0]??0),w=String.fromCharCode(f[1]??0),y=$e(f.slice(2),i,l.tag,r,s,o);a.push({tag:l.tag,indicator1:c,indicator2:w,subfields:y})}catch(c){const w=g("invalid_field",`Failed to parse data field ${l.tag}: ${c instanceof Error?c.message:String(c)}`,d,l.tag);if(s)throw new Error(w.message);r.push(w)}}return a}function $e(e,t,n,i,r,s){const o=[];let a=0;for(;a<e.length;){if(i.length>=s){i.push(g("truncated_record",`Subfield parsing halted after reaching maxWarnings limit (${s}) in field ${n}; not all subfields were processed.`,void 0,n));break}if(e[a]!==U){const f=g("invalid_field",`Expected subfield delimiter in field ${n} at position ${a}`,void 0,n);if(r)throw new Error(f.message);i.push(f);break}if(a++,a>=e.length)break;const l=String.fromCharCode(e[a]??0);a++;const d=a;for(;a<e.length&&e[a]!==U;)a++;const h=e.slice(d,a);try{const f=t(h);o.push({code:l,value:f})}catch(f){const c=g("encoding_error",`Failed to decode subfield ${n}$${l}: ${f instanceof Error?f.message:String(f)}. Raw bytes (hex): ${J(h)}.`,void 0,n);if(r)throw new Error(c.message);i.push(c),o.push({code:l,value:H(h)})}}return o}function g(e,t,n,i){return{type:e,message:t,position:n,tag:i}}var Ie=31,P=30,_e=29,_=24,Re=3,Me=4,Ne=5;function De(e,t={}){return Z(e,t).bytes}function Z(e,t={}){Te(e);const n=[],i=t.maxWarnings??100,r=t.encoding==="marc8",s=new TextEncoder,o=r?(m,S)=>{const b=x(m);return b.lossyCount>0&&n.length<i&&n.push(G.createWarning("encoding_error",`MARC-8 encoding substituted ${b.lossyCount} character(s) with '?' because they have no MARC-8 equivalent.`,void 0,S)),b.bytes}:m=>s.encode(m),a=[],l=[];let d=0;for(const m of e.fields){const S=xe(m,te=>o(te,m.tag)),b=S.length+1,ee=m.tag.padEnd(Re," ")+b.toString().padStart(Me,"0")+d.toString().padStart(Ne,"0");a.push(ee),l.push(S),l.push(new Uint8Array([P])),d+=b}const h=s.encode(a.join("")),f=new Uint8Array(h.length+1);f.set(h),f[h.length]=P;const c=_+f.length,w=l.reduce((m,S)=>m+S.length,0),y=new Uint8Array(w);let B=0;for(const m of l)y.set(m,B),B+=m.length;const M=c+w+1,Q=Le(e.leader,M,c,r),F=new Uint8Array(M);return F.set(s.encode(Q),0),F.set(f,_),F.set(y,c),F[M-1]=_e,{bytes:F,warnings:n}}function N(e){const t=e.charCodeAt(0);return t>=32&&t<=126}function Te(e){for(const t of e.fields){if(typeof t.tag!="string"||t.tag.length!==3)throw new Error(`MARC field tag must be exactly 3 characters; got ${JSON.stringify(t.tag)}`);if(!u.isControlField(t)){if(t.indicator1.length!==1)throw new Error(`Field ${t.tag} indicator1 must be exactly 1 character; got ${JSON.stringify(t.indicator1)}`);if(!N(t.indicator1))throw new Error(`Field ${t.tag} indicator1 must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(t.indicator1)}`);if(t.indicator2.length!==1)throw new Error(`Field ${t.tag} indicator2 must be exactly 1 character; got ${JSON.stringify(t.indicator2)}`);if(!N(t.indicator2))throw new Error(`Field ${t.tag} indicator2 must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(t.indicator2)}`);for(const n of t.subfields){if(n.code.length!==1)throw new Error(`Field ${t.tag} subfield code must be exactly 1 character; got ${JSON.stringify(n.code)}`);if(!N(n.code))throw new Error(`Field ${t.tag} subfield code must be an ASCII printable character (U+0020–U+007E); got ${JSON.stringify(n.code)}`)}}}}function xe(e,t){if(u.isControlField(e))return t(e.data);const n=[new Uint8Array([e.indicator1.charCodeAt(0),e.indicator2.charCodeAt(0)])];for(const o of e.subfields){const a=new Uint8Array([Ie,o.code.charCodeAt(0)]);n.push(a,t(o.value))}const i=n.reduce((o,a)=>o+a.length,0),r=new Uint8Array(i);let s=0;for(const o of n)r.set(o,s),s+=o.length;return r}function Le(e,t,n,i){let r=e.padEnd(_," ").substring(0,_);const s=t.toString().padStart(5,"0");if(s.length>5)throw new Error(`Record length ${t} exceeds maximum (99999)`);r=s+r.substring(5);const o=n.toString().padStart(5,"0");if(o.length>5)throw new Error(`Base address ${n} exceeds maximum (99999)`);return r=r.substring(0,12)+o+r.substring(17),r=r.substring(0,9)+(i?" ":"a")+r.substring(10),r}function Be(e,t={}){const n=e.map(o=>De(o,t)),i=n.reduce((o,a)=>o+a.length,0),r=new Uint8Array(i);let s=0;for(const o of n)r.set(o,s),s+=o.length;return r}function Ue(e,t={}){const n=[],i=[];for(const a of e){const l=Z(a,t);n.push(l),i.push(l.bytes)}const r=i.reduce((a,l)=>a+l.length,0),s=new Uint8Array(r);let o=0;for(const a of i)s.set(a,o),o+=a.length;return{bytes:s,results:n}}function E(e,t){return e.fields.find(n=>n.tag===t)}function Oe(e,t){return e.fields.filter(n=>n.tag===t)}function p(e,t){return e.subfields.find(n=>n.code===t)?.value}function Pe(e,t){return e.subfields.filter(n=>n.code===t).map(n=>n.value)}function We(e){return e.subfields.map(t=>({code:t.code,value:t.value}))}function Ge(e){const t=E(e,"245");if(!t||!u.isDataField(t))return;const n=p(t,"a")??"",i=p(t,"b")??"";return(n+" "+i).trim()||void 0}function ke(e){const t=E(e,"245");if(!(!t||!u.isDataField(t)))return p(t,"a")}function qe(e){const t=E(e,"100");if(t&&u.isDataField(t))return p(t,"a");const n=E(e,"110");if(n&&u.isDataField(n))return p(n,"a")}function ze(e){const t=E(e,"250");if(!(!t||!u.isDataField(t)))return p(t,"a")}function je(e){const t=E(e,"264");if(t&&u.isDataField(t)){const i=p(t,"b");if(i)return i}const n=E(e,"260");if(n&&u.isDataField(n))return p(n,"b")}function He(e){const t=E(e,"264");if(t&&u.isDataField(t)){const i=p(t,"c");if(i)return i}const n=E(e,"260");if(n&&u.isDataField(n))return p(n,"c")}function Je(e){const t=[];for(const n of e.fields)if(n.tag==="020"&&u.isDataField(n)){const i=p(n,"a");i&&t.push(i)}return t}function Ye(e){const t=E(e,"022");if(!(!t||!u.isDataField(t)))return p(t,"a")}function Ze(e){const t=E(e,"010");if(!(!t||!u.isDataField(t)))return p(t,"a")}function Ke(e){const t=[];for(const n of e.fields)if(n.tag.startsWith("6")&&u.isDataField(n)){const i=p(n,"a");i&&t.push(i)}return t}function Ve(e){const t=E(e,"490");if(!(!t||!u.isDataField(t)))return p(t,"a")}function K(e,t){if(e.length!==3||t.length!==3)return!1;for(let n=0;n<3;n++){const i=t[n],r=e[n];if(i==="."||i?.toUpperCase()==="X"){if(r&&!/\d/.test(r))return!1;continue}if(i!==r)return!1}return!0}function Xe(e,t){return e.fields.filter(n=>K(n.tag,t))}function Qe(e,t){return e.fields.find(n=>K(n.tag,t))}function L(e,t){return{...e,fields:[...e.fields,t]}}function et(e,t,n){const i=e.fields.findIndex(s=>s.tag===t);if(i===-1)return L(e,n);const r=Array.from(e.fields);return r.splice(i,0,n),{...e,fields:r}}function tt(e,t,n){const i=e.fields.findIndex(s=>s.tag===t);if(i===-1)return L(e,n);const r=Array.from(e.fields);return r.splice(i+1,0,n),{...e,fields:r}}function nt(e,t){const n=parseInt(t.tag,10);let i=e.fields.length;for(let s=0;s<e.fields.length;s++){const o=e.fields[s];if(o&&parseInt(o.tag,10)>n){i=s;break}}const r=Array.from(e.fields);return r.splice(i,0,t),{...e,fields:r}}function rt(e,t){return{...e,fields:e.fields.filter(n=>n.tag!==t)}}function it(e,t){return{...e,fields:e.fields.filter(n=>n!==t)}}function V(e,t,n){return{...e,subfields:[...e.subfields,{code:t,value:n}]}}function st(e,t){return{...e,subfields:e.subfields.filter(n=>n.code!==t)}}function ot(e,t,n){const i=e.subfields.findIndex(s=>s.code===t);if(i===-1)return V(e,t,n);const r=[...e.subfields];return r[i]={code:t,value:n},{...e,subfields:r}}function at(e){const t=new Array(e.fields.length);for(let n=0;n<e.fields.length;n++){const i=e.fields[n];if(u.isControlField(i))t[n]={tag:i.tag,data:i.data};else{const r=new Array(i.subfields.length);for(let s=0;s<i.subfields.length;s++){const o=i.subfields[s];r[s]={code:o.code,value:o.value}}t[n]={tag:i.tag,indicator1:i.indicator1,indicator2:i.indicator2,subfields:r}}}return{leader:e.leader,fields:t}}function ct(e,t,n=!1){if(e.leader!==t.leader||e.fields.length!==t.fields.length)return!1;const i=n?[...e.fields].sort(W):e.fields,r=n?[...t.fields].sort(W):t.fields;for(let s=0;s<i.length;s++){const o=i[s],a=r[s];if(!o||!a||!X(o,a))return!1}return!0}function X(e,t){if(e.tag!==t.tag)return!1;if(u.isControlField(e)&&u.isControlField(t))return e.data===t.data;if(!u.isControlField(e)&&!u.isControlField(t)){if(e.indicator1!==t.indicator1||e.indicator2!==t.indicator2||e.subfields.length!==t.subfields.length)return!1;for(let n=0;n<e.subfields.length;n++){const i=e.subfields[n],r=t.subfields[n];if(!i||!r||i.code!==r.code||i.value!==r.value)return!1}return!0}return!1}function W(e,t){return e.tag.localeCompare(t.tag)}exports.addSubfield=V;exports.appendField=L;exports.author=qe;exports.cloneRecord=at;exports.createWarning=G.createWarning;exports.edition=ze;exports.fieldsEqual=X;exports.getAllSubfields=We;exports.getField=E;exports.getFields=Oe;exports.getFieldsByPattern=Xe;exports.getFirstFieldByPattern=Qe;exports.getSubfield=p;exports.getSubfields=Pe;exports.insertFieldAfter=tt;exports.insertFieldBefore=et;exports.insertGroupedField=nt;exports.isControlField=u.isControlField;exports.isDataField=u.isDataField;exports.isbn=Je;exports.issn=Ye;exports.lccn=Ze;exports.marc8ToUnicode=z;exports.parseMarcBinary=Se;exports.parseMarcBinaryWithWarnings=be;exports.publicationDate=He;exports.publisher=je;exports.recordsEqual=ct;exports.removeField=it;exports.removeFields=rt;exports.removeSubfield=st;exports.replaceSubfield=ot;exports.serializeMarcBinary=Be;exports.serializeMarcBinaryWithWarnings=Ue;exports.seriesStatement=Ve;exports.subjects=Ke;exports.title=Ge;exports.titleProper=ke;exports.unicodeToMarc8=ve;exports.unicodeToMarc8WithStats=x;
2
2
 
3
3
  //# sourceMappingURL=index.cjs.map