music-metadata 7.12.4 → 8.0.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 +47 -31
- package/lib/ParserFactory.js +37 -41
- package/lib/aiff/AiffParser.js +25 -17
- package/lib/aiff/AiffToken.js +13 -12
- package/lib/apev2/APEv2Parser.js +29 -32
- package/lib/apev2/APEv2TagMapper.js +2 -6
- package/lib/apev2/APEv2Token.js +13 -19
- package/lib/asf/AsfObject.js +42 -56
- package/lib/asf/AsfParser.js +15 -19
- package/lib/asf/AsfTagMapper.js +2 -6
- package/lib/asf/AsfUtil.js +4 -7
- package/lib/asf/GUID.js +1 -4
- package/lib/common/BasicParser.js +1 -5
- package/lib/common/CaseInsensitiveTagMap.js +2 -6
- package/lib/common/CombinedTagMapper.js +20 -24
- package/lib/common/FourCC.js +3 -6
- package/lib/common/GenericTagMapper.js +2 -6
- package/lib/common/GenericTagTypes.js +5 -10
- package/lib/common/MetadataCollector.js +20 -25
- package/lib/common/RandomFileReader.js +2 -6
- package/lib/common/RandomUint8ArrayReader.js +1 -5
- package/lib/common/Util.js +11 -25
- package/lib/core.js +18 -28
- package/lib/dsdiff/DsdiffParser.js +24 -28
- package/lib/dsdiff/DsdiffToken.js +4 -7
- package/lib/dsf/DsfChunk.js +8 -11
- package/lib/dsf/DsfParser.js +13 -17
- package/lib/flac/FlacParser.js +22 -26
- package/lib/id3v1/ID3v1Parser.js +16 -21
- package/lib/id3v1/ID3v1TagMap.js +2 -6
- package/lib/id3v2/AbstractID3Parser.js +13 -17
- package/lib/id3v2/FrameParser.js +12 -17
- package/lib/id3v2/ID3v22TagMapper.js +4 -8
- package/lib/id3v2/ID3v24TagMapper.js +5 -9
- package/lib/id3v2/ID3v2Parser.js +10 -14
- package/lib/id3v2/ID3v2Token.js +9 -12
- package/lib/iff/index.js +4 -7
- package/lib/index.js +14 -44
- package/lib/lyrics3/Lyrics3.js +3 -7
- package/lib/matroska/MatroskaDtd.js +111 -114
- package/lib/matroska/MatroskaParser.js +20 -24
- package/lib/matroska/MatroskaTagMapper.js +2 -6
- package/lib/matroska/types.js +6 -9
- package/lib/mp4/Atom.js +4 -8
- package/lib/mp4/AtomToken.js +29 -44
- package/lib/mp4/MP4Parser.js +12 -16
- package/lib/mp4/MP4TagMapper.js +4 -8
- package/lib/mpeg/ExtendedLameHeader.js +6 -9
- package/lib/mpeg/MpegParser.js +17 -21
- package/lib/mpeg/ReplayGainDataFormat.js +2 -5
- package/lib/mpeg/XingTag.js +9 -13
- package/lib/musepack/index.js +10 -12
- package/lib/musepack/sv7/BitReader.js +2 -6
- package/lib/musepack/sv7/MpcSv7Parser.js +9 -13
- package/lib/musepack/sv7/StreamVersion7.js +3 -6
- package/lib/musepack/sv8/MpcSv8Parser.js +9 -13
- package/lib/musepack/sv8/StreamVersion8.js +5 -9
- package/lib/ogg/Ogg.js +1 -2
- package/lib/ogg/OggParser.js +19 -24
- package/lib/ogg/opus/Opus.js +2 -6
- package/lib/ogg/opus/OpusParser.js +4 -8
- package/lib/ogg/speex/Speex.js +3 -6
- package/lib/ogg/speex/SpeexParser.js +5 -9
- package/lib/ogg/theora/Theora.js +2 -5
- package/lib/ogg/theora/TheoraParser.js +5 -9
- package/lib/ogg/vorbis/Vorbis.js +6 -10
- package/lib/ogg/vorbis/VorbisDecoder.js +2 -6
- package/lib/ogg/vorbis/VorbisParser.js +18 -22
- package/lib/ogg/vorbis/VorbisTagMapper.js +3 -7
- package/lib/riff/RiffChunk.js +3 -7
- package/lib/riff/RiffInfoTagMap.js +4 -8
- package/lib/type.js +1 -5
- package/lib/wav/BwfChunk.js +8 -11
- package/lib/wav/WaveChunk.js +4 -9
- package/lib/wav/WaveParser.js +17 -21
- package/lib/wavpack/WavPackParser.js +17 -21
- package/lib/wavpack/WavPackToken.js +4 -8
- package/package.json +34 -44
- package/lib/ParserFactory.d.ts +0 -48
- package/lib/aiff/AiffParser.d.ts +0 -14
- package/lib/aiff/AiffToken.d.ts +0 -22
- package/lib/apev2/APEv2Parser.d.ts +0 -30
- package/lib/apev2/APEv2TagMapper.d.ts +0 -4
- package/lib/apev2/APEv2Token.d.ts +0 -100
- package/lib/asf/AsfObject.d.ts +0 -319
- package/lib/asf/AsfParser.d.ts +0 -17
- package/lib/asf/AsfTagMapper.d.ts +0 -7
- package/lib/asf/AsfUtil.d.ts +0 -13
- package/lib/asf/GUID.d.ts +0 -84
- package/lib/common/BasicParser.d.ts +0 -17
- package/lib/common/CaseInsensitiveTagMap.d.ts +0 -10
- package/lib/common/CombinedTagMapper.d.ts +0 -19
- package/lib/common/FourCC.d.ts +0 -6
- package/lib/common/GenericTagMapper.d.ts +0 -51
- package/lib/common/GenericTagTypes.d.ts +0 -33
- package/lib/common/MetadataCollector.d.ts +0 -76
- package/lib/common/RandomFileReader.d.ts +0 -22
- package/lib/common/RandomUint8ArrayReader.d.ts +0 -18
- package/lib/common/Util.d.ts +0 -57
- package/lib/core.d.ts +0 -48
- package/lib/dsdiff/DsdiffParser.d.ts +0 -14
- package/lib/dsdiff/DsdiffToken.d.ts +0 -9
- package/lib/dsf/DsfChunk.d.ts +0 -86
- package/lib/dsf/DsfParser.d.ts +0 -9
- package/lib/flac/FlacParser.d.ts +0 -28
- package/lib/id3v1/ID3v1Parser.d.ts +0 -13
- package/lib/id3v1/ID3v1TagMap.d.ts +0 -4
- package/lib/id3v2/AbstractID3Parser.d.ts +0 -17
- package/lib/id3v2/FrameParser.d.ts +0 -31
- package/lib/id3v2/ID3v22TagMapper.d.ts +0 -9
- package/lib/id3v2/ID3v24TagMapper.d.ts +0 -14
- package/lib/id3v2/ID3v2Parser.d.ts +0 -28
- package/lib/id3v2/ID3v2Token.d.ts +0 -73
- package/lib/iff/index.d.ts +0 -33
- package/lib/index.d.ts +0 -45
- package/lib/lyrics3/Lyrics3.d.ts +0 -3
- package/lib/matroska/MatroskaDtd.d.ts +0 -8
- package/lib/matroska/MatroskaParser.d.ts +0 -37
- package/lib/matroska/MatroskaTagMapper.d.ts +0 -4
- package/lib/matroska/types.d.ts +0 -175
- package/lib/mp4/Atom.d.ts +0 -16
- package/lib/mp4/AtomToken.d.ts +0 -395
- package/lib/mp4/MP4Parser.d.ts +0 -30
- package/lib/mp4/MP4TagMapper.d.ts +0 -5
- package/lib/mpeg/ExtendedLameHeader.d.ts +0 -27
- package/lib/mpeg/MpegParser.d.ts +0 -49
- package/lib/mpeg/ReplayGainDataFormat.d.ts +0 -55
- package/lib/mpeg/XingTag.d.ts +0 -45
- package/lib/musepack/index.d.ts +0 -5
- package/lib/musepack/sv7/BitReader.d.ts +0 -13
- package/lib/musepack/sv7/MpcSv7Parser.d.ts +0 -8
- package/lib/musepack/sv7/StreamVersion7.d.ts +0 -28
- package/lib/musepack/sv8/MpcSv8Parser.d.ts +0 -6
- package/lib/musepack/sv8/StreamVersion8.d.ts +0 -40
- package/lib/ogg/Ogg.d.ts +0 -72
- package/lib/ogg/OggParser.d.ts +0 -23
- package/lib/ogg/opus/Opus.d.ts +0 -48
- package/lib/ogg/opus/OpusParser.d.ts +0 -25
- package/lib/ogg/speex/Speex.d.ts +0 -36
- package/lib/ogg/speex/SpeexParser.d.ts +0 -22
- package/lib/ogg/theora/Theora.d.ts +0 -20
- package/lib/ogg/theora/TheoraParser.d.ts +0 -28
- package/lib/ogg/vorbis/Vorbis.d.ts +0 -69
- package/lib/ogg/vorbis/VorbisDecoder.d.ts +0 -12
- package/lib/ogg/vorbis/VorbisParser.d.ts +0 -36
- package/lib/ogg/vorbis/VorbisTagMapper.d.ts +0 -7
- package/lib/riff/RiffChunk.d.ts +0 -16
- package/lib/riff/RiffInfoTagMap.d.ts +0 -10
- package/lib/type.d.ts +0 -592
- package/lib/wav/BwfChunk.d.ts +0 -17
- package/lib/wav/WaveChunk.d.ts +0 -64
- package/lib/wav/WaveParser.d.ts +0 -24
- package/lib/wavpack/WavPackParser.d.ts +0 -14
- package/lib/wavpack/WavPackToken.d.ts +0 -64
package/lib/index.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const RandomFileReader_1 = require("./common/RandomFileReader");
|
|
9
|
-
const debug = (0, debug_1.default)("music-metadata:parser");
|
|
10
|
-
var core_1 = require("./core");
|
|
11
|
-
Object.defineProperty(exports, "parseFromTokenizer", { enumerable: true, get: function () { return core_1.parseFromTokenizer; } });
|
|
12
|
-
Object.defineProperty(exports, "parseBuffer", { enumerable: true, get: function () { return core_1.parseBuffer; } });
|
|
13
|
-
Object.defineProperty(exports, "selectCover", { enumerable: true, get: function () { return core_1.selectCover; } });
|
|
1
|
+
import * as strtok3 from 'strtok3';
|
|
2
|
+
import initDebug from 'debug';
|
|
3
|
+
import { parseFromTokenizer, scanAppendingHeaders } from './core.js';
|
|
4
|
+
import { ParserFactory } from './ParserFactory.js';
|
|
5
|
+
import { RandomFileReader } from './common/RandomFileReader.js';
|
|
6
|
+
export { parseFromTokenizer, parseBuffer, selectCover, orderTags, ratingToStars } from './core.js';
|
|
7
|
+
const debug = initDebug('music-metadata:parser');
|
|
14
8
|
/**
|
|
15
9
|
* Parse audio from Node Stream.Readable
|
|
16
10
|
* @param stream - Stream to read the audio track from
|
|
@@ -18,57 +12,33 @@ Object.defineProperty(exports, "selectCover", { enumerable: true, get: function
|
|
|
18
12
|
* @param options - Parsing options
|
|
19
13
|
* @returns Metadata
|
|
20
14
|
*/
|
|
21
|
-
async function parseStream(stream, fileInfo, options = {}) {
|
|
15
|
+
export async function parseStream(stream, fileInfo, options = {}) {
|
|
22
16
|
const tokenizer = await strtok3.fromStream(stream, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo);
|
|
23
|
-
return
|
|
17
|
+
return parseFromTokenizer(tokenizer, options);
|
|
24
18
|
}
|
|
25
|
-
exports.parseStream = parseStream;
|
|
26
19
|
/**
|
|
27
20
|
* Parse audio from Node file
|
|
28
21
|
* @param filePath - Media file to read meta-data from
|
|
29
22
|
* @param options - Parsing options
|
|
30
23
|
* @returns Metadata
|
|
31
24
|
*/
|
|
32
|
-
async function parseFile(filePath, options = {}) {
|
|
25
|
+
export async function parseFile(filePath, options = {}) {
|
|
33
26
|
debug(`parseFile: ${filePath}`);
|
|
34
27
|
const fileTokenizer = await strtok3.fromFile(filePath);
|
|
35
|
-
const fileReader = await
|
|
28
|
+
const fileReader = await RandomFileReader.init(filePath, fileTokenizer.fileInfo.size);
|
|
36
29
|
try {
|
|
37
|
-
await
|
|
30
|
+
await scanAppendingHeaders(fileReader, options);
|
|
38
31
|
}
|
|
39
32
|
finally {
|
|
40
33
|
await fileReader.close();
|
|
41
34
|
}
|
|
42
35
|
try {
|
|
43
|
-
const parserName =
|
|
36
|
+
const parserName = ParserFactory.getParserIdForExtension(filePath);
|
|
44
37
|
if (!parserName)
|
|
45
38
|
debug(' Parser could not be determined by file extension');
|
|
46
|
-
return await
|
|
39
|
+
return await ParserFactory.parse(fileTokenizer, parserName, options);
|
|
47
40
|
}
|
|
48
41
|
finally {
|
|
49
42
|
await fileTokenizer.close();
|
|
50
43
|
}
|
|
51
44
|
}
|
|
52
|
-
exports.parseFile = parseFile;
|
|
53
|
-
/**
|
|
54
|
-
* Create a dictionary ordered by their tag id (key)
|
|
55
|
-
* @param nativeTags - List of tags
|
|
56
|
-
* @returns Tags indexed by id
|
|
57
|
-
*/
|
|
58
|
-
exports.orderTags = Core.orderTags;
|
|
59
|
-
/**
|
|
60
|
-
* Convert rating to 1-5 star rating
|
|
61
|
-
* @param rating - Normalized rating [0..1] (common.rating[n].rating)
|
|
62
|
-
* @returns Number of stars: 1, 2, 3, 4 or 5 stars
|
|
63
|
-
*/
|
|
64
|
-
exports.ratingToStars = Core.ratingToStars;
|
|
65
|
-
/**
|
|
66
|
-
* Define default module exports
|
|
67
|
-
*/
|
|
68
|
-
exports.default = {
|
|
69
|
-
parseStream,
|
|
70
|
-
parseFile,
|
|
71
|
-
parseFromTokenizer: Core.parseFromTokenizer,
|
|
72
|
-
parseBuffer: Core.parseBuffer,
|
|
73
|
-
selectCover: Core.selectCover
|
|
74
|
-
};
|
package/lib/lyrics3/Lyrics3.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.getLyricsHeaderLength = exports.endTag2 = void 0;
|
|
4
|
-
exports.endTag2 = 'LYRICS200';
|
|
5
|
-
async function getLyricsHeaderLength(reader) {
|
|
1
|
+
export const endTag2 = 'LYRICS200';
|
|
2
|
+
export async function getLyricsHeaderLength(reader) {
|
|
6
3
|
if (reader.fileSize >= 143) {
|
|
7
4
|
const buf = Buffer.alloc(15);
|
|
8
5
|
await reader.randomRead(buf, 0, buf.length, reader.fileSize - 143);
|
|
9
6
|
const txt = buf.toString('binary');
|
|
10
7
|
const tag = txt.substr(6);
|
|
11
|
-
if (tag ===
|
|
8
|
+
if (tag === endTag2) {
|
|
12
9
|
return parseInt(txt.substr(0, 6), 10) + 15;
|
|
13
10
|
}
|
|
14
11
|
}
|
|
15
12
|
return 0;
|
|
16
13
|
}
|
|
17
|
-
exports.getLyricsHeaderLength = getLyricsHeaderLength;
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.elements = void 0;
|
|
4
|
-
const types_1 = require("./types");
|
|
1
|
+
import { DataType } from './types.js';
|
|
5
2
|
/**
|
|
6
3
|
* Elements of document type description
|
|
7
4
|
* Derived from https://github.com/tungol/EBML/blob/master/doctypes/matroska.dtd
|
|
8
5
|
* Extended with:
|
|
9
6
|
* - https://www.matroska.org/technical/specs/index.html
|
|
10
7
|
*/
|
|
11
|
-
|
|
8
|
+
export const elements = {
|
|
12
9
|
0x1a45dfa3: {
|
|
13
10
|
name: 'ebml',
|
|
14
11
|
container: {
|
|
15
|
-
0x4286: { name: 'ebmlVersion', value:
|
|
16
|
-
0x42f7: { name: 'ebmlReadVersion', value:
|
|
17
|
-
0x42f2: { name: 'ebmlMaxIDWidth', value:
|
|
18
|
-
0x42f3: { name: 'ebmlMaxSizeWidth', value:
|
|
19
|
-
0x4282: { name: 'docType', value:
|
|
20
|
-
0x4287: { name: 'docTypeVersion', value:
|
|
21
|
-
0x4285: { name: 'docTypeReadVersion', value:
|
|
12
|
+
0x4286: { name: 'ebmlVersion', value: DataType.uint },
|
|
13
|
+
0x42f7: { name: 'ebmlReadVersion', value: DataType.uint },
|
|
14
|
+
0x42f2: { name: 'ebmlMaxIDWidth', value: DataType.uint },
|
|
15
|
+
0x42f3: { name: 'ebmlMaxSizeWidth', value: DataType.uint },
|
|
16
|
+
0x4282: { name: 'docType', value: DataType.string },
|
|
17
|
+
0x4287: { name: 'docTypeVersion', value: DataType.uint },
|
|
18
|
+
0x4285: { name: 'docTypeReadVersion', value: DataType.uint } // 5.1.7
|
|
22
19
|
}
|
|
23
20
|
},
|
|
24
21
|
// Matroska segments
|
|
@@ -32,8 +29,8 @@ exports.elements = {
|
|
|
32
29
|
0x4dbb: {
|
|
33
30
|
name: 'seek',
|
|
34
31
|
container: {
|
|
35
|
-
0x53ab: { name: 'seekId', value:
|
|
36
|
-
0x53ac: { name: 'seekPosition', value:
|
|
32
|
+
0x53ab: { name: 'seekId', value: DataType.binary },
|
|
33
|
+
0x53ac: { name: 'seekPosition', value: DataType.uint }
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
}
|
|
@@ -42,18 +39,18 @@ exports.elements = {
|
|
|
42
39
|
0x1549a966: {
|
|
43
40
|
name: 'info',
|
|
44
41
|
container: {
|
|
45
|
-
0x73a4: { name: 'uid', value:
|
|
46
|
-
0x7384: { name: 'filename', value:
|
|
47
|
-
0x3cb923: { name: 'prevUID', value:
|
|
48
|
-
0x3c83ab: { name: 'prevFilename', value:
|
|
49
|
-
0x3eb923: { name: 'nextUID', value:
|
|
50
|
-
0x3e83bb: { name: 'nextFilename', value:
|
|
51
|
-
0x2ad7b1: { name: 'timecodeScale', value:
|
|
52
|
-
0x4489: { name: 'duration', value:
|
|
53
|
-
0x4461: { name: 'dateUTC', value:
|
|
54
|
-
0x7ba9: { name: 'title', value:
|
|
55
|
-
0x4d80: { name: 'muxingApp', value:
|
|
56
|
-
0x5741: { name: 'writingApp', value:
|
|
42
|
+
0x73a4: { name: 'uid', value: DataType.uid },
|
|
43
|
+
0x7384: { name: 'filename', value: DataType.string },
|
|
44
|
+
0x3cb923: { name: 'prevUID', value: DataType.uid },
|
|
45
|
+
0x3c83ab: { name: 'prevFilename', value: DataType.string },
|
|
46
|
+
0x3eb923: { name: 'nextUID', value: DataType.uid },
|
|
47
|
+
0x3e83bb: { name: 'nextFilename', value: DataType.string },
|
|
48
|
+
0x2ad7b1: { name: 'timecodeScale', value: DataType.uint },
|
|
49
|
+
0x4489: { name: 'duration', value: DataType.float },
|
|
50
|
+
0x4461: { name: 'dateUTC', value: DataType.uint },
|
|
51
|
+
0x7ba9: { name: 'title', value: DataType.string },
|
|
52
|
+
0x4d80: { name: 'muxingApp', value: DataType.string },
|
|
53
|
+
0x5741: { name: 'writingApp', value: DataType.string }
|
|
57
54
|
}
|
|
58
55
|
},
|
|
59
56
|
// Cluster
|
|
@@ -61,10 +58,10 @@ exports.elements = {
|
|
|
61
58
|
name: 'cluster',
|
|
62
59
|
multiple: true,
|
|
63
60
|
container: {
|
|
64
|
-
0xe7: { name: 'timecode', value:
|
|
65
|
-
0xa3: { name: 'unknown', value:
|
|
66
|
-
0xa7: { name: 'position', value:
|
|
67
|
-
0xab: { name: 'prevSize', value:
|
|
61
|
+
0xe7: { name: 'timecode', value: DataType.uid },
|
|
62
|
+
0xa3: { name: 'unknown', value: DataType.binary },
|
|
63
|
+
0xa7: { name: 'position', value: DataType.uid },
|
|
64
|
+
0xab: { name: 'prevSize', value: DataType.uid }
|
|
68
65
|
}
|
|
69
66
|
},
|
|
70
67
|
// Track
|
|
@@ -75,52 +72,52 @@ exports.elements = {
|
|
|
75
72
|
name: 'entries',
|
|
76
73
|
multiple: true,
|
|
77
74
|
container: {
|
|
78
|
-
0xd7: { name: 'trackNumber', value:
|
|
79
|
-
0x73c5: { name: 'uid', value:
|
|
80
|
-
0x83: { name: 'trackType', value:
|
|
81
|
-
0xb9: { name: 'flagEnabled', value:
|
|
82
|
-
0x88: { name: 'flagDefault', value:
|
|
83
|
-
0x55aa: { name: 'flagForced', value:
|
|
84
|
-
0x9c: { name: 'flagLacing', value:
|
|
85
|
-
0x6de7: { name: 'minCache', value:
|
|
86
|
-
0x6de8: { name: 'maxCache', value:
|
|
87
|
-
0x23e383: { name: 'defaultDuration', value:
|
|
88
|
-
0x23314f: { name: 'timecodeScale', value:
|
|
89
|
-
0x536e: { name: 'name', value:
|
|
90
|
-
0x22b59c: { name: 'language', value:
|
|
91
|
-
0x86: { name: 'codecID', value:
|
|
92
|
-
0x63a2: { name: 'codecPrivate', value:
|
|
93
|
-
0x258688: { name: 'codecName', value:
|
|
94
|
-
0x3a9697: { name: 'codecSettings', value:
|
|
95
|
-
0x3b4040: { name: 'codecInfoUrl', value:
|
|
96
|
-
0x26b240: { name: 'codecDownloadUrl', value:
|
|
97
|
-
0xaa: { name: 'codecDecodeAll', value:
|
|
98
|
-
0x6fab: { name: 'trackOverlay', value:
|
|
75
|
+
0xd7: { name: 'trackNumber', value: DataType.uint },
|
|
76
|
+
0x73c5: { name: 'uid', value: DataType.uid },
|
|
77
|
+
0x83: { name: 'trackType', value: DataType.uint },
|
|
78
|
+
0xb9: { name: 'flagEnabled', value: DataType.bool },
|
|
79
|
+
0x88: { name: 'flagDefault', value: DataType.bool },
|
|
80
|
+
0x55aa: { name: 'flagForced', value: DataType.bool },
|
|
81
|
+
0x9c: { name: 'flagLacing', value: DataType.bool },
|
|
82
|
+
0x6de7: { name: 'minCache', value: DataType.uint },
|
|
83
|
+
0x6de8: { name: 'maxCache', value: DataType.uint },
|
|
84
|
+
0x23e383: { name: 'defaultDuration', value: DataType.uint },
|
|
85
|
+
0x23314f: { name: 'timecodeScale', value: DataType.float },
|
|
86
|
+
0x536e: { name: 'name', value: DataType.string },
|
|
87
|
+
0x22b59c: { name: 'language', value: DataType.string },
|
|
88
|
+
0x86: { name: 'codecID', value: DataType.string },
|
|
89
|
+
0x63a2: { name: 'codecPrivate', value: DataType.binary },
|
|
90
|
+
0x258688: { name: 'codecName', value: DataType.string },
|
|
91
|
+
0x3a9697: { name: 'codecSettings', value: DataType.string },
|
|
92
|
+
0x3b4040: { name: 'codecInfoUrl', value: DataType.string },
|
|
93
|
+
0x26b240: { name: 'codecDownloadUrl', value: DataType.string },
|
|
94
|
+
0xaa: { name: 'codecDecodeAll', value: DataType.bool },
|
|
95
|
+
0x6fab: { name: 'trackOverlay', value: DataType.uint },
|
|
99
96
|
// Video
|
|
100
97
|
0xe0: {
|
|
101
98
|
name: 'video',
|
|
102
99
|
container: {
|
|
103
|
-
0x9a: { name: 'flagInterlaced', value:
|
|
104
|
-
0x53b8: { name: 'stereoMode', value:
|
|
105
|
-
0xb0: { name: 'pixelWidth', value:
|
|
106
|
-
0xba: { name: 'pixelHeight', value:
|
|
107
|
-
0x54b0: { name: 'displayWidth', value:
|
|
108
|
-
0x54ba: { name: 'displayHeight', value:
|
|
109
|
-
0x54b3: { name: 'aspectRatioType', value:
|
|
110
|
-
0x2eb524: { name: 'colourSpace', value:
|
|
111
|
-
0x2fb523: { name: 'gammaValue', value:
|
|
100
|
+
0x9a: { name: 'flagInterlaced', value: DataType.bool },
|
|
101
|
+
0x53b8: { name: 'stereoMode', value: DataType.uint },
|
|
102
|
+
0xb0: { name: 'pixelWidth', value: DataType.uint },
|
|
103
|
+
0xba: { name: 'pixelHeight', value: DataType.uint },
|
|
104
|
+
0x54b0: { name: 'displayWidth', value: DataType.uint },
|
|
105
|
+
0x54ba: { name: 'displayHeight', value: DataType.uint },
|
|
106
|
+
0x54b3: { name: 'aspectRatioType', value: DataType.uint },
|
|
107
|
+
0x2eb524: { name: 'colourSpace', value: DataType.uint },
|
|
108
|
+
0x2fb523: { name: 'gammaValue', value: DataType.float }
|
|
112
109
|
}
|
|
113
110
|
},
|
|
114
111
|
// Audio
|
|
115
112
|
0xe1: {
|
|
116
113
|
name: 'audio',
|
|
117
114
|
container: {
|
|
118
|
-
0xb5: { name: 'samplingFrequency', value:
|
|
119
|
-
0x78b5: { name: 'outputSamplingFrequency', value:
|
|
120
|
-
0x9f: { name: 'channels', value:
|
|
121
|
-
0x94: { name: 'channels', value:
|
|
122
|
-
0x7d7b: { name: 'channelPositions', value:
|
|
123
|
-
0x6264: { name: 'bitDepth', value:
|
|
115
|
+
0xb5: { name: 'samplingFrequency', value: DataType.float },
|
|
116
|
+
0x78b5: { name: 'outputSamplingFrequency', value: DataType.float },
|
|
117
|
+
0x9f: { name: 'channels', value: DataType.uint },
|
|
118
|
+
0x94: { name: 'channels', value: DataType.uint },
|
|
119
|
+
0x7d7b: { name: 'channelPositions', value: DataType.binary },
|
|
120
|
+
0x6264: { name: 'bitDepth', value: DataType.uint }
|
|
124
121
|
}
|
|
125
122
|
},
|
|
126
123
|
// Content Encoding
|
|
@@ -130,28 +127,28 @@ exports.elements = {
|
|
|
130
127
|
0x6240: {
|
|
131
128
|
name: 'contentEncoding',
|
|
132
129
|
container: {
|
|
133
|
-
0x5031: { name: 'order', value:
|
|
134
|
-
0x5032: { name: 'scope', value:
|
|
135
|
-
0x5033: { name: 'type', value:
|
|
130
|
+
0x5031: { name: 'order', value: DataType.uint },
|
|
131
|
+
0x5032: { name: 'scope', value: DataType.bool },
|
|
132
|
+
0x5033: { name: 'type', value: DataType.uint },
|
|
136
133
|
0x5034: {
|
|
137
134
|
name: 'contentEncoding',
|
|
138
135
|
container: {
|
|
139
|
-
0x4254: { name: 'contentCompAlgo', value:
|
|
140
|
-
0x4255: { name: 'contentCompSettings', value:
|
|
136
|
+
0x4254: { name: 'contentCompAlgo', value: DataType.uint },
|
|
137
|
+
0x4255: { name: 'contentCompSettings', value: DataType.binary }
|
|
141
138
|
}
|
|
142
139
|
},
|
|
143
140
|
0x5035: {
|
|
144
141
|
name: 'contentEncoding',
|
|
145
142
|
container: {
|
|
146
|
-
0x47e1: { name: 'contentEncAlgo', value:
|
|
147
|
-
0x47e2: { name: 'contentEncKeyID', value:
|
|
148
|
-
0x47e3: { name: 'contentSignature ', value:
|
|
149
|
-
0x47e4: { name: 'ContentSigKeyID ', value:
|
|
150
|
-
0x47e5: { name: 'contentSigAlgo ', value:
|
|
151
|
-
0x47e6: { name: 'contentSigHashAlgo ', value:
|
|
143
|
+
0x47e1: { name: 'contentEncAlgo', value: DataType.uint },
|
|
144
|
+
0x47e2: { name: 'contentEncKeyID', value: DataType.binary },
|
|
145
|
+
0x47e3: { name: 'contentSignature ', value: DataType.binary },
|
|
146
|
+
0x47e4: { name: 'ContentSigKeyID ', value: DataType.binary },
|
|
147
|
+
0x47e5: { name: 'contentSigAlgo ', value: DataType.uint },
|
|
148
|
+
0x47e6: { name: 'contentSigHashAlgo ', value: DataType.uint }
|
|
152
149
|
}
|
|
153
150
|
},
|
|
154
|
-
0x6264: { name: 'bitDepth', value:
|
|
151
|
+
0x6264: { name: 'bitDepth', value: DataType.uint }
|
|
155
152
|
}
|
|
156
153
|
}
|
|
157
154
|
}
|
|
@@ -167,23 +164,23 @@ exports.elements = {
|
|
|
167
164
|
0xbb: {
|
|
168
165
|
name: 'cuePoint',
|
|
169
166
|
container: {
|
|
170
|
-
0xb3: { name: 'cueTime', value:
|
|
167
|
+
0xb3: { name: 'cueTime', value: DataType.uid },
|
|
171
168
|
0xb7: {
|
|
172
169
|
name: 'positions',
|
|
173
170
|
container: {
|
|
174
|
-
0xf7: { name: 'track', value:
|
|
175
|
-
0xf1: { name: 'clusterPosition', value:
|
|
176
|
-
0x5378: { name: 'blockNumber', value:
|
|
177
|
-
0xea: { name: 'codecState', value:
|
|
171
|
+
0xf7: { name: 'track', value: DataType.uint },
|
|
172
|
+
0xf1: { name: 'clusterPosition', value: DataType.uint },
|
|
173
|
+
0x5378: { name: 'blockNumber', value: DataType.uint },
|
|
174
|
+
0xea: { name: 'codecState', value: DataType.uint },
|
|
178
175
|
0xdb: {
|
|
179
176
|
name: 'reference', container: {
|
|
180
|
-
0x96: { name: 'time', value:
|
|
181
|
-
0x97: { name: 'cluster', value:
|
|
182
|
-
0x535f: { name: 'number', value:
|
|
183
|
-
0xeb: { name: 'codecState', value:
|
|
177
|
+
0x96: { name: 'time', value: DataType.uint },
|
|
178
|
+
0x97: { name: 'cluster', value: DataType.uint },
|
|
179
|
+
0x535f: { name: 'number', value: DataType.uint },
|
|
180
|
+
0xeb: { name: 'codecState', value: DataType.uint }
|
|
184
181
|
}
|
|
185
182
|
},
|
|
186
|
-
0xf0: { name: 'relativePosition', value:
|
|
183
|
+
0xf0: { name: 'relativePosition', value: DataType.uint } // extended
|
|
187
184
|
}
|
|
188
185
|
}
|
|
189
186
|
}
|
|
@@ -198,11 +195,11 @@ exports.elements = {
|
|
|
198
195
|
name: 'attachedFiles',
|
|
199
196
|
multiple: true,
|
|
200
197
|
container: {
|
|
201
|
-
0x467e: { name: 'description', value:
|
|
202
|
-
0x466e: { name: 'name', value:
|
|
203
|
-
0x4660: { name: 'mimeType', value:
|
|
204
|
-
0x465c: { name: 'data', value:
|
|
205
|
-
0x46ae: { name: 'uid', value:
|
|
198
|
+
0x467e: { name: 'description', value: DataType.string },
|
|
199
|
+
0x466e: { name: 'name', value: DataType.string },
|
|
200
|
+
0x4660: { name: 'mimeType', value: DataType.string },
|
|
201
|
+
0x465c: { name: 'data', value: DataType.binary },
|
|
202
|
+
0x46ae: { name: 'uid', value: DataType.uid }
|
|
206
203
|
}
|
|
207
204
|
}
|
|
208
205
|
}
|
|
@@ -217,18 +214,18 @@ exports.elements = {
|
|
|
217
214
|
0xb6: {
|
|
218
215
|
name: 'chapterAtom',
|
|
219
216
|
container: {
|
|
220
|
-
0x73c4: { name: 'uid', value:
|
|
221
|
-
0x91: { name: 'timeStart', value:
|
|
222
|
-
0x92: { name: 'timeEnd', value:
|
|
223
|
-
0x98: { name: 'hidden', value:
|
|
224
|
-
0x4598: { name: 'enabled', value:
|
|
217
|
+
0x73c4: { name: 'uid', value: DataType.uid },
|
|
218
|
+
0x91: { name: 'timeStart', value: DataType.uint },
|
|
219
|
+
0x92: { name: 'timeEnd', value: DataType.uid },
|
|
220
|
+
0x98: { name: 'hidden', value: DataType.bool },
|
|
221
|
+
0x4598: { name: 'enabled', value: DataType.uid },
|
|
225
222
|
0x8f: { name: 'track', container: {
|
|
226
|
-
0x89: { name: 'trackNumber', value:
|
|
223
|
+
0x89: { name: 'trackNumber', value: DataType.uid },
|
|
227
224
|
0x80: {
|
|
228
225
|
name: 'display', container: {
|
|
229
|
-
0x85: { name: 'string', value:
|
|
230
|
-
0x437c: { name: 'language ', value:
|
|
231
|
-
0x437e: { name: 'country ', value:
|
|
226
|
+
0x85: { name: 'string', value: DataType.string },
|
|
227
|
+
0x437c: { name: 'language ', value: DataType.string },
|
|
228
|
+
0x437e: { name: 'country ', value: DataType.string }
|
|
232
229
|
}
|
|
233
230
|
}
|
|
234
231
|
}
|
|
@@ -250,24 +247,24 @@ exports.elements = {
|
|
|
250
247
|
0x63c0: {
|
|
251
248
|
name: 'target',
|
|
252
249
|
container: {
|
|
253
|
-
0x63c5: { name: 'tagTrackUID', value:
|
|
254
|
-
0x63c4: { name: 'tagChapterUID', value:
|
|
255
|
-
0x63c6: { name: 'tagAttachmentUID', value:
|
|
256
|
-
0x63ca: { name: 'targetType', value:
|
|
257
|
-
0x68ca: { name: 'targetTypeValue', value:
|
|
258
|
-
0x63c9: { name: 'tagEditionUID', value:
|
|
250
|
+
0x63c5: { name: 'tagTrackUID', value: DataType.uid },
|
|
251
|
+
0x63c4: { name: 'tagChapterUID', value: DataType.uint },
|
|
252
|
+
0x63c6: { name: 'tagAttachmentUID', value: DataType.uid },
|
|
253
|
+
0x63ca: { name: 'targetType', value: DataType.string },
|
|
254
|
+
0x68ca: { name: 'targetTypeValue', value: DataType.uint },
|
|
255
|
+
0x63c9: { name: 'tagEditionUID', value: DataType.uid } // extended
|
|
259
256
|
}
|
|
260
257
|
},
|
|
261
258
|
0x67c8: {
|
|
262
259
|
name: 'simpleTags',
|
|
263
260
|
multiple: true,
|
|
264
261
|
container: {
|
|
265
|
-
0x45a3: { name: 'name', value:
|
|
266
|
-
0x4487: { name: 'string', value:
|
|
267
|
-
0x4485: { name: 'binary', value:
|
|
268
|
-
0x447a: { name: 'language', value:
|
|
269
|
-
0x447b: { name: 'languageIETF', value:
|
|
270
|
-
0x4484: { name: 'default', value:
|
|
262
|
+
0x45a3: { name: 'name', value: DataType.string },
|
|
263
|
+
0x4487: { name: 'string', value: DataType.string },
|
|
264
|
+
0x4485: { name: 'binary', value: DataType.binary },
|
|
265
|
+
0x447a: { name: 'language', value: DataType.string },
|
|
266
|
+
0x447b: { name: 'languageIETF', value: DataType.string },
|
|
267
|
+
0x4484: { name: 'default', value: DataType.bool } // extended
|
|
271
268
|
}
|
|
272
269
|
}
|
|
273
270
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const types_1 = require("./types");
|
|
8
|
-
const matroskaDtd = require("./MatroskaDtd");
|
|
9
|
-
const debug = (0, debug_1.default)('music-metadata:parser:matroska');
|
|
1
|
+
import { Float32_BE, Float64_BE, StringType, UINT8 } from 'token-types';
|
|
2
|
+
import initDebug from 'debug';
|
|
3
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
4
|
+
import * as matroskaDtd from './MatroskaDtd.js';
|
|
5
|
+
import { DataType, TargetType, TrackType } from './types.js';
|
|
6
|
+
const debug = initDebug('music-metadata:parser:matroska');
|
|
10
7
|
/**
|
|
11
8
|
* Extensible Binary Meta Language (EBML) parser
|
|
12
9
|
* https://en.wikipedia.org/wiki/Extensible_Binary_Meta_Language
|
|
@@ -14,19 +11,19 @@ const debug = (0, debug_1.default)('music-metadata:parser:matroska');
|
|
|
14
11
|
*
|
|
15
12
|
* WEBM VP8 AUDIO FILE
|
|
16
13
|
*/
|
|
17
|
-
class MatroskaParser extends
|
|
14
|
+
export class MatroskaParser extends BasicParser {
|
|
18
15
|
constructor() {
|
|
19
16
|
super();
|
|
20
17
|
this.padding = 0;
|
|
21
18
|
this.parserMap = new Map();
|
|
22
19
|
this.ebmlMaxIDLength = 4;
|
|
23
20
|
this.ebmlMaxSizeLength = 8;
|
|
24
|
-
this.parserMap.set(
|
|
25
|
-
this.parserMap.set(
|
|
26
|
-
this.parserMap.set(
|
|
27
|
-
this.parserMap.set(
|
|
28
|
-
this.parserMap.set(
|
|
29
|
-
this.parserMap.set(
|
|
21
|
+
this.parserMap.set(DataType.uint, e => this.readUint(e));
|
|
22
|
+
this.parserMap.set(DataType.string, e => this.readString(e));
|
|
23
|
+
this.parserMap.set(DataType.binary, e => this.readBuffer(e));
|
|
24
|
+
this.parserMap.set(DataType.uid, async (e) => await this.readUint(e) === 1);
|
|
25
|
+
this.parserMap.set(DataType.bool, e => this.readFlag(e));
|
|
26
|
+
this.parserMap.set(DataType.float, e => this.readFloat(e));
|
|
30
27
|
}
|
|
31
28
|
/**
|
|
32
29
|
* Initialize parser with output (metadata), input (tokenizer) & parsing options (options).
|
|
@@ -68,7 +65,7 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
68
65
|
});
|
|
69
66
|
const audioTrack = audioTracks.entries
|
|
70
67
|
.filter(entry => {
|
|
71
|
-
return entry.trackType ===
|
|
68
|
+
return entry.trackType === TrackType.audio.valueOf();
|
|
72
69
|
})
|
|
73
70
|
.reduce((acc, cur) => {
|
|
74
71
|
if (!acc) {
|
|
@@ -90,7 +87,7 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
90
87
|
if (matroska.segment.tags) {
|
|
91
88
|
matroska.segment.tags.tag.forEach(tag => {
|
|
92
89
|
const target = tag.target;
|
|
93
|
-
const targetType = (target === null || target === void 0 ? void 0 : target.targetTypeValue) ?
|
|
90
|
+
const targetType = (target === null || target === void 0 ? void 0 : target.targetTypeValue) ? TargetType[target.targetTypeValue] : ((target === null || target === void 0 ? void 0 : target.targetType) ? target.targetType : 'track');
|
|
94
91
|
tag.simpleTags.forEach(simpleTag => {
|
|
95
92
|
const value = simpleTag.string ? simpleTag.string : simpleTag.binary;
|
|
96
93
|
this.addTag(`${targetType}:${simpleTag.name}`, value);
|
|
@@ -162,7 +159,7 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
162
159
|
return tree;
|
|
163
160
|
}
|
|
164
161
|
async readVintData(maxLength) {
|
|
165
|
-
const msb = await this.tokenizer.peekNumber(
|
|
162
|
+
const msb = await this.tokenizer.peekNumber(UINT8);
|
|
166
163
|
let mask = 0x80;
|
|
167
164
|
let oc = 1;
|
|
168
165
|
// Calculate VINT_WIDTH
|
|
@@ -202,11 +199,11 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
202
199
|
case 0:
|
|
203
200
|
return 0.0;
|
|
204
201
|
case 4:
|
|
205
|
-
return this.tokenizer.readNumber(
|
|
202
|
+
return this.tokenizer.readNumber(Float32_BE);
|
|
206
203
|
case 8:
|
|
207
|
-
return this.tokenizer.readNumber(
|
|
204
|
+
return this.tokenizer.readNumber(Float64_BE);
|
|
208
205
|
case 10:
|
|
209
|
-
return this.tokenizer.readNumber(
|
|
206
|
+
return this.tokenizer.readNumber(Float64_BE);
|
|
210
207
|
default:
|
|
211
208
|
throw new Error(`Invalid IEEE-754 float length: ${e.len}`);
|
|
212
209
|
}
|
|
@@ -220,7 +217,7 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
220
217
|
return buf.readUIntBE(e.len - nrLen, nrLen);
|
|
221
218
|
}
|
|
222
219
|
async readString(e) {
|
|
223
|
-
const rawString = await this.tokenizer.readToken(new
|
|
220
|
+
const rawString = await this.tokenizer.readToken(new StringType(e.len, 'utf-8'));
|
|
224
221
|
return rawString.replace(/\00.*$/g, '');
|
|
225
222
|
}
|
|
226
223
|
async readBuffer(e) {
|
|
@@ -232,4 +229,3 @@ class MatroskaParser extends BasicParser_1.BasicParser {
|
|
|
232
229
|
this.metadata.addTag('matroska', tagId, value);
|
|
233
230
|
}
|
|
234
231
|
}
|
|
235
|
-
exports.MatroskaParser = MatroskaParser;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MatroskaTagMapper = void 0;
|
|
4
|
-
const CaseInsensitiveTagMap_1 = require("../common/CaseInsensitiveTagMap");
|
|
1
|
+
import { CaseInsensitiveTagMap } from '../common/CaseInsensitiveTagMap.js';
|
|
5
2
|
/**
|
|
6
3
|
* EBML Tag map
|
|
7
4
|
*/
|
|
@@ -27,10 +24,9 @@ const ebmlTagMap = {
|
|
|
27
24
|
'edition:TOTAL_PARTS': 'totaldiscs',
|
|
28
25
|
picture: 'picture'
|
|
29
26
|
};
|
|
30
|
-
class MatroskaTagMapper extends
|
|
27
|
+
export class MatroskaTagMapper extends CaseInsensitiveTagMap {
|
|
31
28
|
constructor() {
|
|
32
29
|
super(['matroska'], ebmlTagMap);
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
|
-
exports.MatroskaTagMapper = MatroskaTagMapper;
|
|
36
32
|
//# sourceMappingURL=MatroskaTagMapper.js.map
|
package/lib/matroska/types.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TrackType = exports.TargetType = exports.DataType = void 0;
|
|
4
|
-
var DataType;
|
|
1
|
+
export var DataType;
|
|
5
2
|
(function (DataType) {
|
|
6
3
|
DataType[DataType["string"] = 0] = "string";
|
|
7
4
|
DataType[DataType["uint"] = 1] = "uint";
|
|
@@ -9,8 +6,8 @@ var DataType;
|
|
|
9
6
|
DataType[DataType["bool"] = 3] = "bool";
|
|
10
7
|
DataType[DataType["binary"] = 4] = "binary";
|
|
11
8
|
DataType[DataType["float"] = 5] = "float";
|
|
12
|
-
})(DataType =
|
|
13
|
-
var TargetType;
|
|
9
|
+
})(DataType = DataType || (DataType = {}));
|
|
10
|
+
export var TargetType;
|
|
14
11
|
(function (TargetType) {
|
|
15
12
|
TargetType[TargetType["shot"] = 10] = "shot";
|
|
16
13
|
TargetType[TargetType["scene"] = 20] = "scene";
|
|
@@ -19,8 +16,8 @@ var TargetType;
|
|
|
19
16
|
TargetType[TargetType["album"] = 50] = "album";
|
|
20
17
|
TargetType[TargetType["edition"] = 60] = "edition";
|
|
21
18
|
TargetType[TargetType["collection"] = 70] = "collection";
|
|
22
|
-
})(TargetType =
|
|
23
|
-
var TrackType;
|
|
19
|
+
})(TargetType = TargetType || (TargetType = {}));
|
|
20
|
+
export var TrackType;
|
|
24
21
|
(function (TrackType) {
|
|
25
22
|
TrackType[TrackType["video"] = 1] = "video";
|
|
26
23
|
TrackType[TrackType["audio"] = 2] = "audio";
|
|
@@ -29,5 +26,5 @@ var TrackType;
|
|
|
29
26
|
TrackType[TrackType["subtitle"] = 17] = "subtitle";
|
|
30
27
|
TrackType[TrackType["button"] = 18] = "button";
|
|
31
28
|
TrackType[TrackType["control"] = 32] = "control";
|
|
32
|
-
})(TrackType =
|
|
29
|
+
})(TrackType = TrackType || (TrackType = {}));
|
|
33
30
|
//# sourceMappingURL=types.js.map
|
package/lib/mp4/Atom.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const AtomToken = require("./AtomToken");
|
|
6
|
-
const debug = (0, debug_1.default)('music-metadata:parser:MP4:Atom');
|
|
7
|
-
class Atom {
|
|
1
|
+
import initDebug from 'debug';
|
|
2
|
+
import * as AtomToken from './AtomToken.js';
|
|
3
|
+
const debug = initDebug('music-metadata:parser:MP4:Atom');
|
|
4
|
+
export class Atom {
|
|
8
5
|
constructor(header, extended, parent) {
|
|
9
6
|
this.header = header;
|
|
10
7
|
this.extended = extended;
|
|
@@ -67,4 +64,3 @@ class Atom {
|
|
|
67
64
|
}
|
|
68
65
|
}
|
|
69
66
|
}
|
|
70
|
-
exports.Atom = Atom;
|