Node.anitomy.js
node.anitomy.js is a Node.js binding for Anitomy a C++ library for parsing anime video filenames.
Install / Use
/learn @Xtansia/Node.anitomy.jsREADME
node.anitomy.js

node.anitomy.js is a Node.js binding for
Anitomy a C++ library for parsing anime
video filenames.
Installing
You can install node.anitomy.js as a dependency of your project using NPM like so, provided you have met the dependencies listed below.
> npm install --save anitomyjs
Dependencies
- Node.JS >= 4.0.0
- CMake >= 3.2
- A C++14 compatible compiler
- GCC >= 5
- Clang >= 3.4 (According to the Clang CXX status page)
- Visual Studio 2017 OR Build Tools for Visual Studio 2017
Example Usage
const anitomy = require('anitomyjs');
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
Would output:
Toradora! #01 by TaigaSubs
API
parse(filenames[, options], callback)
Parses the filenames asynchronously.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called passing the resulting elements as the first parameter.- If
filenameswas an array, then the passed value will be an array of AnitomyElements, with the same ordering asfilenames. - If
filenameswas a string, then the passed value will be an AnitomyElements.
- If
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
anitomy.parse(filename, function (elems) {
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});
Would output:
Toradora! #01 by TaigaSubs
parseSync(filenames[, options])
Parses the filenames synchronously.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.- Returns:
- If
filenameswas an array, then the returned value will be an array of AnitomyElements, with the same ordering asfilenames. - If
filenameswas a string, then the returned value will be an AnitomyElements.
- If
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
Would output:
Toradora! #01 by TaigaSubs
parseEach(filenames[, options], callback)
Parses each of the individual filenames asynchronously, as opposed to parse which parses them all in bulk. As it is asynchronous there is no ordering ensured.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called when each filename is parsed, passing the filename and the resulting AnitomyElements as the first and second parameters respectively.
const filenames = [
'[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv',
'[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv',
'[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv',
'[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv'
];
anitomy.parseEach(filenames, function (filename, elems) {
console.log(filename + '\n\t=> ' + elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});
Would output (though not necessarily in this order):
[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv
=> Princess Lover! #01 by ANBU
[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv
=> Canaan #01 by ANBU-Menclave
[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv
=> Haiyoru! Nyaru-Ani #undefined by ANBU-umai
[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv
=> Toradora! #01 by TaigaSubs
parseEachSync(filenames[, options], callback)
Same as parseEach but synchronous, i.e.
calls callback for each parsed filename, then returns. callback is ensured to
be called in the same order as filenames.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called when each filename is parsed, passing the filename and the resulting AnitomyElements as the first and second parameters respectively.
const filenames = [
'[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv',
'[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv',
'[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv',
'[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv'
];
anitomy.parseEachSync(filenames, function (filename, elems) {
console.log(filename + '\n\t=> ' + elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});
console.log('parseEachSync completed');
Would output:
[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv
=> Toradora! #01 by TaigaSubs
[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv
=> Princess Lover! #01 by ANBU
[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv
=> Canaan #01 by ANBU-Menclave
[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv
=> Haiyoru! Nyaru-Ani #undefined by ANBU-umai
parseEachSync completed
Parse Options
Options are given in the form of an object, with any or all of the following properties set, if unset they default to these values (Anitomy's defaults):
{
allowedDelimiters: ' _.&+,|',
ignoredStrings: [],
parseEpisodeNumber: true,
parseEpisodeTitle: true,
parseFileExtension: true,
parseReleaseGroup: true
}
AnitomyElements
This object represents the parsed elements of the filename. With a property for each ElementCategory that it has a value for, the properties are immutable. In cases where there are multiple elements in a category the property's value will be an array.
AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTitle: 'Tiger and Dragon',
FileChecksum: '1234ABCD',
FileExtension: 'mkv',
FileName: '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD]',
ReleaseGroup: 'TaigaSubs',
ReleaseVersion: '2',
VideoResolution: '1280x720',
VideoTerm: 'H.264' }
AnitomyElements#empty([category])
Returns true if the AnitomyElements has no category-value pairs.
categoryis optional, if provided must be a string representing an ElementCategory, return value will then be true if the AnitomyElements has no values for that category.
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTitle: 'Tiger and Dragon',
FileChecksum: '1234ABCD',
FileExtension: 'mkv',
FileName: '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD]',
ReleaseGroup: 'TaigaSubs',
ReleaseVersion: '2',
VideoResolution: '1280x720',
VideoTerm: 'H.264' } */
const isEmpty = elems.empty();
// -> false
const hasNoVolumeNumber = elems.empty('VolumeNumber');
// -> true
AnitomyElements#count(category)
Returns the number of values associated with the category in this AnitomyElements.
categorymust be a string representing an ElementCategory.
const filename = 'Detective Conan - 316-317 [DCTP][2411959B].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Detective Conan',
EpisodeNumber: [ '316', '317' ],
FileChecksum: '2411959B',
FileExtension: 'mkv',
FileName: 'Detective Conan - 316-317 [DCTP][2411959B]',
ReleaseGroup: 'DCTP' } */
const numOfEpNumbers = elems.count('EpisodeNumber');
// -> 2
AnitomyElements#size()
Returns the number of category-value pairs this AnitomyElements has.
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTit
Related Skills
docs-writer
99.5k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
340.5kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
ddd
Guía de Principios DDD para el Proyecto > 📚 Documento Complementario : Este documento define los principios y reglas de DDD. Para ver templates de código, ejemplos detallados y guías paso
arscontexta
2.9kClaude Code plugin that generates individualized knowledge systems from conversation. You describe how you think and work, have a conversation and get a complete second brain as markdown files you own.
