taglib-wasm 1.5.2 → 1.6.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.
Files changed (51) hide show
  1. package/LICENSE +12 -9
  2. package/README.md +6 -3
  3. package/dist/index.browser.js +255 -85
  4. package/dist/index.d.ts +1 -1
  5. package/dist/simple.browser.js +253 -84
  6. package/dist/src/constants/complex-properties.d.ts +18 -12
  7. package/dist/src/constants/complex-properties.d.ts.map +1 -1
  8. package/dist/src/constants/properties.d.ts +24 -0
  9. package/dist/src/constants/properties.d.ts.map +1 -1
  10. package/dist/src/constants/properties.js +34 -0
  11. package/dist/src/constants/specialized-properties.d.ts +23 -0
  12. package/dist/src/constants/specialized-properties.d.ts.map +1 -1
  13. package/dist/src/constants/specialized-properties.js +20 -0
  14. package/dist/src/constants/tags.d.ts.map +1 -1
  15. package/dist/src/constants/tags.js +2 -1
  16. package/dist/src/deno-compile.d.ts +12 -0
  17. package/dist/src/deno-compile.d.ts.map +1 -1
  18. package/dist/src/deno-compile.js +9 -8
  19. package/dist/src/msgpack/encoder.d.ts.map +1 -1
  20. package/dist/src/msgpack/encoder.js +6 -4
  21. package/dist/src/runtime/detector.d.ts +0 -6
  22. package/dist/src/runtime/detector.d.ts.map +1 -1
  23. package/dist/src/runtime/detector.js +1 -14
  24. package/dist/src/runtime/wasi-adapter/file-handle.d.ts +2 -0
  25. package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
  26. package/dist/src/runtime/wasi-adapter/file-handle.js +61 -52
  27. package/dist/src/taglib/audio-file-base.d.ts.map +1 -1
  28. package/dist/src/taglib/audio-file-base.js +33 -77
  29. package/dist/src/taglib/mp4-item-names.d.ts +12 -0
  30. package/dist/src/taglib/mp4-item-names.d.ts.map +1 -0
  31. package/dist/src/taglib/mp4-item-names.js +4 -0
  32. package/dist/src/taglib/mutable-tag-impl.d.ts +14 -0
  33. package/dist/src/taglib/mutable-tag-impl.d.ts.map +1 -0
  34. package/dist/src/taglib/mutable-tag-impl.js +88 -0
  35. package/dist/src/taglib/save-reconstruct.d.ts.map +1 -1
  36. package/dist/src/taglib/save-reconstruct.js +4 -0
  37. package/dist/src/types/metadata-mappings.d.ts.map +1 -1
  38. package/dist/src/types/metadata-mappings.js +14 -0
  39. package/dist/src/types/tags.d.ts +16 -0
  40. package/dist/src/types/tags.d.ts.map +1 -1
  41. package/dist/src/utils/mirror-fields.d.ts +79 -0
  42. package/dist/src/utils/mirror-fields.d.ts.map +1 -0
  43. package/dist/src/utils/mirror-fields.js +67 -0
  44. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  45. package/dist/src/utils/tag-mapping.js +47 -5
  46. package/dist/src/version.d.ts +1 -1
  47. package/dist/src/version.js +1 -1
  48. package/dist/taglib-wasi.wasm +0 -0
  49. package/dist/taglib-web.wasm +0 -0
  50. package/dist/taglib-wrapper.js +1 -1
  51. package/package.json +8 -5
@@ -0,0 +1,88 @@
1
+ import { toTagLibKey } from "../constants/properties.js";
2
+ const RAW_TRACK_WIRE_KEY = toTagLibKey("trackNumber");
3
+ function buildMutableTag(handle) {
4
+ let data = handle.getTagData();
5
+ const tag = {
6
+ get title() {
7
+ return data.title;
8
+ },
9
+ get artist() {
10
+ return data.artist;
11
+ },
12
+ get album() {
13
+ return data.album;
14
+ },
15
+ get comment() {
16
+ return data.comment;
17
+ },
18
+ get genre() {
19
+ return data.genre;
20
+ },
21
+ get year() {
22
+ return data.year;
23
+ },
24
+ get track() {
25
+ return data.track;
26
+ },
27
+ get date() {
28
+ return handle.getProperty("DATE") || void 0;
29
+ },
30
+ setTitle: (value) => {
31
+ handle.setTagData({ title: value });
32
+ data = handle.getTagData();
33
+ return tag;
34
+ },
35
+ setArtist: (value) => {
36
+ handle.setTagData({ artist: value });
37
+ data = handle.getTagData();
38
+ return tag;
39
+ },
40
+ setAlbum: (value) => {
41
+ handle.setTagData({ album: value });
42
+ data = handle.getTagData();
43
+ return tag;
44
+ },
45
+ setComment: (value) => {
46
+ handle.setTagData({ comment: value });
47
+ data = handle.getTagData();
48
+ return tag;
49
+ },
50
+ setGenre: (value) => {
51
+ handle.setTagData({ genre: value });
52
+ data = handle.getTagData();
53
+ return tag;
54
+ },
55
+ setYear: (value) => {
56
+ handle.setTagData({ year: value });
57
+ data = handle.getTagData();
58
+ return tag;
59
+ },
60
+ setTrack: (value) => {
61
+ const existing = value > 0 ? handle.getProperty(RAW_TRACK_WIRE_KEY) : "";
62
+ const slash = existing.indexOf("/");
63
+ if (slash !== -1) {
64
+ handle.setProperty(
65
+ RAW_TRACK_WIRE_KEY,
66
+ `${value}${existing.slice(slash)}`
67
+ );
68
+ } else {
69
+ handle.setTagData({ track: value });
70
+ }
71
+ data = handle.getTagData();
72
+ return tag;
73
+ },
74
+ setDate: (value) => {
75
+ if (value === "") {
76
+ handle.setTagData({ year: 0 });
77
+ } else {
78
+ handle.setProperty("DATE", value);
79
+ }
80
+ data = handle.getTagData();
81
+ return tag;
82
+ }
83
+ };
84
+ return tag;
85
+ }
86
+ export {
87
+ buildMutableTag
88
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"save-reconstruct.d.ts","sourceRoot":"","sources":["../../../src/taglib/save-reconstruct.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAoC3D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EAChD,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,OAAO,EACvB,WAAW,GAAE,WAAW,CAAC,MAAM,CAAa,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
1
+ {"version":3,"file":"save-reconstruct.d.ts","sourceRoot":"","sources":["../../../src/taglib/save-reconstruct.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA6C3D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EAChD,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,OAAO,EACvB,WAAW,GAAE,WAAW,CAAC,MAAM,CAAa,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -3,10 +3,14 @@ import { readFileData } from "../utils/file.js";
3
3
  import { writeFileData } from "../utils/write.js";
4
4
  import { wrapEmbindHandle } from "./embind-adapter.js";
5
5
  import { copyExtraState } from "./extra-state-registry.js";
6
+ import { mp4FreeformAtomNames } from "../constants/properties.js";
7
+ import { MP4_ITEM_NAMES_KEY } from "./mp4-item-names.js";
6
8
  function copyEditedState(target, source, sourceComplete, deletedKeys) {
7
9
  target.setTagData(source.getTagData());
8
10
  const merged = sourceComplete ? source.getProperties() : { ...target.getProperties(), ...source.getProperties() };
9
11
  for (const key of deletedKeys) delete merged[key];
12
+ const atomNames = mp4FreeformAtomNames(Object.keys(merged));
13
+ if (atomNames.length > 0) merged[MP4_ITEM_NAMES_KEY] = atomNames;
10
14
  target.setProperties(merged);
11
15
  copyExtraState(target, source, sourceComplete);
12
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-mappings.d.ts","sourceRoot":"","sources":["../../../src/types/metadata-mappings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,OAAO,CACL,MAAM,WAAW,EACf,UAAU,GACV,SAAS,GACT,QAAQ,GACR,UAAU,GACV,MAAM,GACN,UAAU,GACV,MAAM,GACN,aAAa,CAChB,EACD,YAAY,CAgNb,CAAC"}
1
+ {"version":3,"file":"metadata-mappings.d.ts","sourceRoot":"","sources":["../../../src/types/metadata-mappings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,OAAO,CACL,MAAM,WAAW,EACf,UAAU,GACV,SAAS,GACT,QAAQ,GACR,UAAU,GACV,MAAM,GACN,UAAU,GACV,MAAM,GACN,aAAa,CAChB,EACD,YAAY,CA8Nb,CAAC"}
@@ -50,6 +50,14 @@ const METADATA_MAPPINGS = {
50
50
  mp4: "trkn",
51
51
  wav: "ITRK"
52
52
  },
53
+ // Raw track string — same underlying frames as `track`, but preserves
54
+ // zero-padding and the "/total" suffix instead of collapsing to an integer.
55
+ trackNumber: {
56
+ id3v2: { frame: "TRCK" },
57
+ vorbis: "TRACKNUMBER",
58
+ mp4: "trkn",
59
+ wav: "ITRK"
60
+ },
53
61
  // Advanced fields requiring format-specific handling
54
62
  acoustidFingerprint: {
55
63
  id3v2: { frame: "TXXX", description: "Acoustid Fingerprint" },
@@ -206,6 +214,12 @@ const METADATA_MAPPINGS = {
206
214
  vorbis: "ITUNNORM",
207
215
  // Some tools store it in Vorbis comments too
208
216
  mp4: "----:com.apple.iTunes:iTunNORM"
217
+ },
218
+ // Same underlying frames pattern as appleSoundCheck, for the sibling atom.
219
+ appleGaplessInfo: {
220
+ id3v2: { frame: "TXXX", description: "iTunSMPB" },
221
+ vorbis: "ITUNSMPB",
222
+ mp4: "----:com.apple.iTunes:iTunSMPB"
209
223
  }
210
224
  };
211
225
  export {
@@ -77,7 +77,14 @@ export interface TagInput {
77
77
  readonly date?: string | string[];
78
78
  /** Track number */
79
79
  readonly track?: number;
80
+ /**
81
+ * Raw track field (e.g. "03" or "3/12"). Maps to the same TRACKNUMBER tag as
82
+ * {@link track}; when both are provided, `trackNumber` wins (it preserves
83
+ * zero-padding and the "/total" suffix that a number cannot).
84
+ */
85
+ readonly trackNumber?: string | string[];
80
86
  readonly appleSoundCheck?: string | string[];
87
+ readonly appleGaplessInfo?: string | string[];
81
88
  readonly albumArtist?: string | string[];
82
89
  readonly composer?: string | string[];
83
90
  readonly conductor?: string | string[];
@@ -135,6 +142,13 @@ export interface ExtendedTag extends Tag {
135
142
  * Preserves day/month precision that the numeric {@link Tag.year} cannot.
136
143
  */
137
144
  readonly date?: string | string[];
145
+ /**
146
+ * Raw track field as stored in TRACKNUMBER (e.g. "03" or "3/12"). Preserves
147
+ * the zero-padding and the "/total" suffix that the numeric
148
+ * {@link Tag.track} cannot, so a readTags() -> applyTags() round-trip does
149
+ * not silently drop them (taglib-qpl).
150
+ */
151
+ readonly trackNumber?: string | string[];
138
152
  /** AcoustID fingerprint (Chromaprint) */
139
153
  readonly acoustidFingerprint?: string[];
140
154
  /** AcoustID UUID */
@@ -203,6 +217,8 @@ export interface ExtendedTag extends Tag {
203
217
  readonly replayGainAlbumPeak?: string[];
204
218
  /** Apple Sound Check normalization data (iTunNORM) */
205
219
  readonly appleSoundCheck?: string[];
220
+ /** Apple gapless playback data: encoder delay and padding (iTunSMPB) */
221
+ readonly appleGaplessInfo?: string[];
206
222
  /** Embedded pictures/artwork */
207
223
  readonly pictures?: import("./pictures.js").Picture[];
208
224
  /** Popularity/rating data. Same shape as {@link AudioFile.getRatings}. */
@@ -1 +1 @@
1
- {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../src/types/tags.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../src/types/tags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @fileoverview Raw-string / numeric-mirror field pairs.
3
+ *
4
+ * Two tag fields are stored twice: a RAW string that is authoritative and can
5
+ * hold what a number cannot ("1975-10-31", "3/12", "03"), and a narrowed numeric
6
+ * MIRROR that the typed `tag()` surface promises (`year`, `track`). Both map to
7
+ * the same TagLib wire key, so exactly one of them may cross the boundary.
8
+ *
9
+ * The rules are few but easy to get subtly wrong, and they were previously
10
+ * hand-written at seven sites across two files. The copies drifted, and the
11
+ * drift was not cosmetic — every bug below came from one site knowing a rule its
12
+ * twin did not:
13
+ *
14
+ * - taglib-qpl: `setProperty` left a stale mirror when the new raw value did
15
+ * not parse, so `tag().track` reported the previous number.
16
+ * - taglib-qpl: `setProperty("")` did not clear, so a deletion was a silent
17
+ * no-op and the old number was written back to disk.
18
+ * - taglib-iyfr: both of the above were still live for `date`/`year`, because
19
+ * only the `trackNumber`/`track` copy had been fixed.
20
+ *
21
+ * So the rules live here once, and adding a third pair is a one-line change.
22
+ */
23
+ /** A raw-string field and the numeric mirror derived from it. */
24
+ export type MirrorField = {
25
+ /** camelCase key holding the raw string. Authoritative. */
26
+ readonly raw: string;
27
+ /** camelCase key holding the narrowed number. Derived, never authoritative. */
28
+ readonly numeric: string;
29
+ };
30
+ export declare const MIRROR_FIELDS: readonly MirrorField[];
31
+ /**
32
+ * Leading integer of a raw field value, or `undefined` when it does not parse.
33
+ * The single definition of the narrowing convention: `parseInt` semantics, so
34
+ * "3/12" is 3 and "03" is 3, and a non-numeric value has no mirror at all.
35
+ */
36
+ export declare function parseLeadingInt(raw: string): number | undefined;
37
+ /**
38
+ * The two pairs by name. Exported so callers need no unchecked cast over a
39
+ * lookup that can return undefined — renaming a field in MIRROR_FIELDS then
40
+ * fails at build time here instead of throwing at the first read.
41
+ */
42
+ export declare const DATE_MIRROR: MirrorField;
43
+ export declare const TRACK_MIRROR: MirrorField;
44
+ /** The pair whose raw key is `key`, if any. */
45
+ export declare function mirrorForRawKey(key: string): MirrorField | undefined;
46
+ /** The pair whose numeric key is `key`, if any. */
47
+ export declare function mirrorForNumericKey(key: string): MirrorField | undefined;
48
+ /** First element of an array value, or the scalar itself, as a string. */
49
+ export declare function firstValueString(v: unknown): string;
50
+ /**
51
+ * True when `key` is a numeric mirror whose raw partner currently holds a value.
52
+ *
53
+ * Both keys translate to one wire key, so emitting both would collide — the raw
54
+ * string wins because it carries strictly more information. Used by the WASI
55
+ * property snapshot and by the msgpack encoder, which previously each inlined
56
+ * their own copy of this test.
57
+ */
58
+ export declare function isShadowedNumericMirror(data: Record<string, unknown>, key: string): boolean;
59
+ /**
60
+ * Stage a RAW write: store the string and re-derive the mirror. An empty value
61
+ * list clears the field, which is what lets `clearTags()` remove it under WASI's
62
+ * merge model; an unparseable value drops the mirror rather than leaving a stale
63
+ * number behind. Mutates `target`.
64
+ */
65
+ export declare function stageRawWrite(target: Record<string, unknown>, field: MirrorField, values: readonly string[]): void;
66
+ /**
67
+ * Stage a NUMERIC write from the typed `tag()` surface: the number is
68
+ * authoritative, so the raw mirror is replaced rather than merged — a stale
69
+ * "3/12" must not shadow a newly set 7. A non-positive value is a clear, not a
70
+ * renumbering. Mutates `target`.
71
+ */
72
+ export declare function stageNumericWrite(target: Record<string, unknown>, field: MirrorField, value: number): void;
73
+ /**
74
+ * Numeric value for the typed surface: the mirror when present, otherwise
75
+ * narrowed from the raw string so a handle that only ever saw the raw value
76
+ * still reports a number.
77
+ */
78
+ export declare function readNumericMirror(data: Record<string, unknown>, field: MirrorField): number;
79
+ //# sourceMappingURL=mirror-fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror-fields.d.ts","sourceRoot":"","sources":["../../../src/utils/mirror-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,iEAAiE;AACjE,MAAM,MAAM,WAAW,GAAG;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAG/C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/D;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,WAA+B,CAAC;AAC1D,eAAO,MAAM,YAAY,EAAE,WAA+B,CAAC;AAE3D,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEpE;AAED,mDAAmD;AACnD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExE;AAQD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAGnD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,MAAM,GACV,OAAO,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,IAAI,CAWN;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI,CAQN;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,WAAW,GACjB,MAAM,CAIR"}
@@ -0,0 +1,67 @@
1
+ const MIRROR_FIELDS = [
2
+ { raw: "date", numeric: "year" },
3
+ { raw: "trackNumber", numeric: "track" }
4
+ ];
5
+ function parseLeadingInt(raw) {
6
+ const parsed = Number.parseInt(raw, 10);
7
+ return Number.isNaN(parsed) ? void 0 : parsed;
8
+ }
9
+ const DATE_MIRROR = MIRROR_FIELDS[0];
10
+ const TRACK_MIRROR = MIRROR_FIELDS[1];
11
+ function mirrorForRawKey(key) {
12
+ return MIRROR_FIELDS.find((f) => f.raw === key);
13
+ }
14
+ function mirrorForNumericKey(key) {
15
+ return MIRROR_FIELDS.find((f) => f.numeric === key);
16
+ }
17
+ function hasValue(v) {
18
+ if (Array.isArray(v)) return v.length > 0;
19
+ return v !== void 0 && v !== null && v !== "";
20
+ }
21
+ function firstValueString(v) {
22
+ if (Array.isArray(v)) return v[0] ?? "";
23
+ return v === void 0 || v === null ? "" : String(v);
24
+ }
25
+ function isShadowedNumericMirror(data, key) {
26
+ const field = mirrorForNumericKey(key);
27
+ return field !== void 0 && hasValue(data[field.raw]);
28
+ }
29
+ function stageRawWrite(target, field, values) {
30
+ const first = values[0] ?? "";
31
+ if (values.length === 0 || first === "") {
32
+ delete target[field.raw];
33
+ delete target[field.numeric];
34
+ return;
35
+ }
36
+ target[field.raw] = [...values];
37
+ const narrowed = parseLeadingInt(first);
38
+ if (narrowed === void 0) delete target[field.numeric];
39
+ else target[field.numeric] = narrowed;
40
+ }
41
+ function stageNumericWrite(target, field, value) {
42
+ if (value > 0) {
43
+ target[field.numeric] = value;
44
+ target[field.raw] = [String(value)];
45
+ } else {
46
+ delete target[field.numeric];
47
+ delete target[field.raw];
48
+ }
49
+ }
50
+ function readNumericMirror(data, field) {
51
+ const mirror = data[field.numeric];
52
+ if (typeof mirror === "number" && mirror !== 0) return mirror;
53
+ return parseLeadingInt(firstValueString(data[field.raw])) ?? 0;
54
+ }
55
+ export {
56
+ DATE_MIRROR,
57
+ MIRROR_FIELDS,
58
+ TRACK_MIRROR,
59
+ firstValueString,
60
+ isShadowedNumericMirror,
61
+ mirrorForNumericKey,
62
+ mirrorForRawKey,
63
+ parseLeadingInt,
64
+ readNumericMirror,
65
+ stageNumericWrite,
66
+ stageRawWrite
67
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"tag-mapping.d.ts","sourceRoot":"","sources":["../../../src/utils/tag-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAsCtE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,WAAW,CAuBjE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAmC1E;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GACtB,IAAI,CAIN;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GACvB,WAAW,CA0Cb"}
1
+ {"version":3,"file":"tag-mapping.d.ts","sourceRoot":"","sources":["../../../src/utils/tag-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAqCtE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,WAAW,CAuBjE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA8D1E;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,GACtB,IAAI,CAKN;AAoDD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GACvB,WAAW,CA+Db"}
@@ -1,4 +1,5 @@
1
1
  import { fromTagLibKey } from "../constants/properties.js";
2
+ import { parseLeadingInt as parseNumeric } from "./mirror-fields.js";
2
3
  const BASIC_PROPERTY_KEYS = {
3
4
  title: "title",
4
5
  artist: "artist",
@@ -16,7 +17,8 @@ const BASIC_FIELDS = /* @__PURE__ */ new Set([
16
17
  "genre",
17
18
  "year",
18
19
  "date",
19
- "track"
20
+ "track",
21
+ "trackNumber"
20
22
  ]);
21
23
  const NUMERIC_FIELDS = /* @__PURE__ */ new Set([
22
24
  "year",
@@ -26,10 +28,6 @@ const NUMERIC_FIELDS = /* @__PURE__ */ new Set([
26
28
  "totalDiscs",
27
29
  "bpm"
28
30
  ]);
29
- function parseNumeric(value) {
30
- const parsed = Number.parseInt(value, 10);
31
- return Number.isNaN(parsed) ? void 0 : parsed;
32
- }
33
31
  function readExtendedTag(audioFile) {
34
32
  const tag = mapPropertiesToExtendedTag(audioFile.properties());
35
33
  const pictures = audioFile.getPictures();
@@ -59,10 +57,24 @@ function mapPropertiesToExtendedTag(props) {
59
57
  if (propKey === "date") {
60
58
  tag.date = values.length === 1 ? values[0] : values;
61
59
  }
60
+ if (propKey === "trackNumber") {
61
+ tag.trackNumber = values.length === 1 ? values[0] : values;
62
+ }
62
63
  } else {
63
64
  tag[tagField] = values;
64
65
  }
65
66
  }
67
+ for (const [propKey, totalField] of [
68
+ ["trackNumber", "totalTracks"],
69
+ ["discNumber", "totalDiscs"]
70
+ ]) {
71
+ if (tag[totalField] !== void 0) continue;
72
+ const raw = props[propKey]?.[0];
73
+ const slash = raw?.indexOf("/") ?? -1;
74
+ if (raw === void 0 || slash === -1) continue;
75
+ const total = parseNumeric(raw.slice(slash + 1));
76
+ if (total !== void 0) tag[totalField] = total;
77
+ }
66
78
  for (const [key, values] of Object.entries(props)) {
67
79
  if (BASIC_PROPERTY_KEYS[key]) continue;
68
80
  if (!values || values.length === 0) continue;
@@ -81,8 +93,29 @@ function mapPropertiesToExtendedTag(props) {
81
93
  function mergeTagUpdates(file, tags) {
82
94
  const currentProps = file.properties();
83
95
  const newProps = normalizeTagInput(tags);
96
+ reconcilePairFields(currentProps, newProps, tags);
84
97
  file.setProperties({ ...currentProps, ...newProps });
85
98
  }
99
+ function reconcilePairFields(currentProps, newProps, input) {
100
+ const pairs = [
101
+ ["trackNumber", "totalTracks", "track"],
102
+ ["discNumber", "totalDiscs", "discNumber"]
103
+ ];
104
+ for (const [rawKey, totalKey, numericKey] of pairs) {
105
+ const incoming = newProps[rawKey]?.[0];
106
+ if (incoming?.includes("/")) {
107
+ newProps[totalKey] = [];
108
+ continue;
109
+ }
110
+ const numericOnly = input[numericKey] !== void 0 && input[rawKey] === void 0;
111
+ if (!numericOnly || incoming === void 0) continue;
112
+ const existing = currentProps[rawKey]?.[0];
113
+ const slash = existing?.indexOf("/") ?? -1;
114
+ if (existing !== void 0 && slash !== -1) {
115
+ newProps[rawKey] = [`${incoming}${existing.slice(slash)}`];
116
+ }
117
+ }
118
+ }
86
119
  function normalizeTagInput(input) {
87
120
  const props = {};
88
121
  for (const field of [
@@ -105,6 +138,9 @@ function normalizeTagInput(input) {
105
138
  if (input.track !== void 0) {
106
139
  props.trackNumber = [String(input.track)];
107
140
  }
141
+ if (input.trackNumber !== void 0) {
142
+ props.trackNumber = Array.isArray(input.trackNumber) ? input.trackNumber : [input.trackNumber];
143
+ }
108
144
  for (const [field, val] of Object.entries(input)) {
109
145
  if (BASIC_FIELDS.has(field) || val === void 0) continue;
110
146
  if (field === "compilation") {
@@ -117,6 +153,12 @@ function normalizeTagInput(input) {
117
153
  props[field] = val;
118
154
  }
119
155
  }
156
+ for (const [rawField, totalField] of [
157
+ ["trackNumber", "totalTracks"],
158
+ ["discNumber", "totalDiscs"]
159
+ ]) {
160
+ if (props[rawField]?.[0]?.includes("/")) delete props[totalField];
161
+ }
120
162
  return props;
121
163
  }
122
164
  export {
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.5.2";
1
+ export declare const VERSION = "1.6.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,4 +1,4 @@
1
- const VERSION = "1.5.2";
1
+ const VERSION = "1.6.0";
2
2
  export {
3
3
  VERSION
4
4
  };
Binary file
Binary file