diff --git a/.editorconfig b/.editorconfig index 0443b45..014787d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,9 +8,11 @@ indent_style = tab insert_final_newline = true trim_trailing_whitespace = true +# Markdown files should not trim trailing whitespace [*.md] trim_trailing_whitespace = false +# JSON and YAML files should use 2 spaces for indentation [*.{json,yaml,yml}] indent_size = 2 indent_style = space diff --git a/.prettierignore b/.prettierignore index 1b76017..982a338 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,13 @@ -/.codacy-coverage/ -/coverage/ -/dist/ -/types/ +# Ignore coverage directories +.codacy-coverage/ +coverage/ +# Ignore build output +dist/ + +# Ignore type definitions +types/ + +# Ignore package files package.json package-lock.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..d9360d2 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "useTabs": true, + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 80 +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ab42e63 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "master" + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e11736..dfdf582 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,19 +4,19 @@ First of all, thanks for taking the time to contribute to metadata-filter! ## Submitting issues -- Ensure the bug was not already reported by searching on GitHub under issues. -- If you're unable to find an open issue addressing the problem, open a new one. +- Ensure the bug was not already reported by searching on GitHub under issues. +- If you're unable to find an open issue addressing the problem, open a new one. Be sure to include a title and clear description, as much relevant information as possible. If you don't know how to report bugs effectively, please use [this article][report-bugs] as a guideline. ## Submitting pull requests -- Fork the metadata-filter [git repository][repository]. -- Create a pull request against the [**master**][repository-master] branch. -- Ensure the PR description **clearly** describes the problem and solution. +- Fork the metadata-filter [git repository][repository]. +- Create a pull request against the [**master**][repository-master] branch. +- Ensure the PR description **clearly** describes the problem and solution. Include the relevant issue number(s) if applicable. -- Ensure CI tests pass. +- Ensure CI tests pass. It's worth reading [how to write][commit-messages] good commit messages. diff --git a/README.md b/README.md index fde0ec5..ba10944 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ object: ```html ``` @@ -54,9 +54,9 @@ combined fields ("Artist - Song", "Artist - Album"), as in the third example bel console.log(MetadataFilter.removeRemastered('Jane Doe (Remastered)')); // Jane Doe console.log(MetadataFilter.removeVersion('Get Lucky (Album Version)')); // Get Lucky console.log( - MetadataFilter.youtube( - 'Car Bomb - Scattered Sprites (Official Music Video)' - ) + MetadataFilter.youtube( + 'Car Bomb - Scattered Sprites (Official Music Video)' + ) ); // Car Bomb - Scattered Sprites ``` @@ -73,16 +73,16 @@ fields. ```javascript const filterSet = { - track: [ - MetadataFilter.removeRemastered, - MetadataFilter.fixTrackSuffix, - MetadataFilter.removeLive, - ], - album: [ - MetadataFilter.removeRemastered, - MetadataFilter.fixTrackSuffix, - MetadataFilter.removeLive, - ], + track: [ + MetadataFilter.removeRemastered, + MetadataFilter.fixTrackSuffix, + MetadataFilter.removeLive, + ], + album: [ + MetadataFilter.removeRemastered, + MetadataFilter.fixTrackSuffix, + MetadataFilter.removeLive, + ], }; ``` @@ -117,7 +117,7 @@ filter.extend(MetadataFilter.createAmazonFilter()); // This would also work: filter.extend(MetadataFilter.createFilter(filterSet)); console.log( - filter.filterField('track', 'Seasons in the Abyss (Album Version)') + filter.filterField('track', 'Seasons in the Abyss (Album Version)') ); // Seasons in the Abyss ``` @@ -134,7 +134,7 @@ Since these methods return a `MetadataFilter` instance, you can chain method cal ```javascript const filter = MetadataFilter.createFilter({ track: filterTrack }).append({ - artist: filterArtist, + artist: filterArtist, }); ``` @@ -162,7 +162,7 @@ const filter = MetadataFilter.createFilter({ track: filterTrack }).append({ ## See also -- [music-metadata-filter] - Python implementation of this module +- [music-metadata-filter] - Python implementation of this module ## License diff --git a/src/filters.ts b/src/filters.ts index 337643a..8adf77f 100644 --- a/src/filters.ts +++ b/src/filters.ts @@ -1,17 +1,17 @@ import { MetadataFilter } from './filter'; import { - albumArtistFromArtist, - decodeHtmlEntities, - fixTrackSuffix, - normalizeFeature, - removeCleanExplicit, - removeFeature, - removeLive, - removeParody, - removeReissue, - removeRemastered, - removeVersion, - youtube, + albumArtistFromArtist, + decodeHtmlEntities, + fixTrackSuffix, + normalizeFeature, + removeCleanExplicit, + removeFeature, + removeLive, + removeParody, + removeReissue, + removeRemastered, + removeVersion, + youtube, } from './functions'; /** @@ -20,7 +20,7 @@ import { * @return Filter object */ export function createYouTubeFilter(): MetadataFilter { - return new MetadataFilter({ track: youtube }); + return new MetadataFilter({ track: youtube }); } /** @@ -29,10 +29,10 @@ export function createYouTubeFilter(): MetadataFilter { * @return Filter object */ export function createRemasteredFilter(): MetadataFilter { - return new MetadataFilter({ - track: removeRemastered, - album: removeRemastered, - }); + return new MetadataFilter({ + track: removeRemastered, + album: removeRemastered, + }); } /** @@ -41,16 +41,16 @@ export function createRemasteredFilter(): MetadataFilter { * @return Filter object */ export function createSpotifyFilter(): MetadataFilter { - return new MetadataFilter({ - track: [removeRemastered, removeParody, fixTrackSuffix, removeLive], - album: [ - removeRemastered, - fixTrackSuffix, - removeLive, - removeReissue, - removeVersion, - ], - }); + return new MetadataFilter({ + track: [removeRemastered, removeParody, fixTrackSuffix, removeLive], + album: [ + removeRemastered, + fixTrackSuffix, + removeLive, + removeReissue, + removeVersion, + ], + }); } /** @@ -59,26 +59,26 @@ export function createSpotifyFilter(): MetadataFilter { * @return Filter object */ export function createAmazonFilter(): MetadataFilter { - return new MetadataFilter({ - artist: [normalizeFeature], - track: [ - removeCleanExplicit, - removeFeature, - removeRemastered, - fixTrackSuffix, - removeVersion, - removeLive, - ], - album: [ - decodeHtmlEntities, - removeCleanExplicit, - removeRemastered, - fixTrackSuffix, - removeVersion, - removeLive, - ], - albumArtist: [normalizeFeature, albumArtistFromArtist], - }); + return new MetadataFilter({ + artist: [normalizeFeature], + track: [ + removeCleanExplicit, + removeFeature, + removeRemastered, + fixTrackSuffix, + removeVersion, + removeLive, + ], + album: [ + decodeHtmlEntities, + removeCleanExplicit, + removeRemastered, + fixTrackSuffix, + removeVersion, + removeLive, + ], + albumArtist: [normalizeFeature, albumArtistFromArtist], + }); } /** @@ -87,8 +87,8 @@ export function createAmazonFilter(): MetadataFilter { * @return Filter object */ export function createTidalFilter(): MetadataFilter { - return new MetadataFilter({ - track: [removeRemastered, fixTrackSuffix, removeVersion, removeLive], - album: [removeRemastered, fixTrackSuffix, removeVersion, removeLive], - }); + return new MetadataFilter({ + track: [removeRemastered, fixTrackSuffix, removeVersion, removeLive], + album: [removeRemastered, fixTrackSuffix, removeVersion, removeLive], + }); } diff --git a/src/functions.ts b/src/functions.ts index 818144c..0865545 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -1,25 +1,25 @@ import { - CLEAN_EXPLICIT_FILTER_RULES, - FEATURE_FILTER_RULES, - LIVE_FILTER_RULES, - NORMALIZE_FEATURE_FILTER_RULES, - PARODY_FILTER_RULES, - REISSUE_FILTER_RULES, - REMASTERED_FILTER_RULES, - SUFFIX_FILTER_RULES, - TRIM_SYMBOLS_FILTER_RULES, - VERSION_FILTER_RULES, - YOUTUBE_TRACK_FILTER_RULES, - VARIOUS_ARTISTS_FILTER_RULES, - FilterRule, - ADDITIONAL_ARTISTS_FILTER_RULES, + CLEAN_EXPLICIT_FILTER_RULES, + FEATURE_FILTER_RULES, + LIVE_FILTER_RULES, + NORMALIZE_FEATURE_FILTER_RULES, + PARODY_FILTER_RULES, + REISSUE_FILTER_RULES, + REMASTERED_FILTER_RULES, + SUFFIX_FILTER_RULES, + TRIM_SYMBOLS_FILTER_RULES, + VERSION_FILTER_RULES, + YOUTUBE_TRACK_FILTER_RULES, + VARIOUS_ARTISTS_FILTER_RULES, + FilterRule, + ADDITIONAL_ARTISTS_FILTER_RULES, } from './rules'; const escapeHtmlEntityMap: Record = { - '&': /&/g, - '<': /</g, - '>': />/g, - '"': /"/g, + '&': /&/g, + '<': /</g, + '>': />/g, + '"': /"/g, }; /** @@ -30,10 +30,10 @@ const escapeHtmlEntityMap: Record = { * @return Transformed string */ export function albumArtistFromArtist(text: string): string { - if (text.includes(' feat. ')) { - return text.split(' feat. ')[0]; - } - return text; + if (text.includes(' feat. ')) { + return text.split(' feat. ')[0]; + } + return text; } /** @@ -44,22 +44,22 @@ export function albumArtistFromArtist(text: string): string { * @return Decoded string */ export function decodeHtmlEntities(text: string): string { - let filteredText = text; + let filteredText = text; - for (const target in escapeHtmlEntityMap) { - const source = escapeHtmlEntityMap[target]; - filteredText = filteredText.replace(source, target); - } + for (const target in escapeHtmlEntityMap) { + const source = escapeHtmlEntityMap[target]; + filteredText = filteredText.replace(source, target); + } - filteredText = filteredText.replace(/&#x([a-fA-f0-9]+);/g, (_, hex) => { - const dec = parseInt(hex, 16); - return String.fromCharCode(dec); - }); - filteredText = filteredText.replace(/&#(\d+);/g, (_, dec) => { - return String.fromCharCode(dec); - }); + filteredText = filteredText.replace(/&#x([a-fA-f0-9]+);/g, (_, hex) => { + const dec = parseInt(hex, 16); + return String.fromCharCode(dec); + }); + filteredText = filteredText.replace(/&#(\d+);/g, (_, dec) => { + return String.fromCharCode(dec); + }); - return filteredText; + return filteredText; } /** @@ -71,25 +71,25 @@ export function decodeHtmlEntities(text: string): string { * @return Filtered string */ export function filterWithFilterRules( - text: string, - filterRules: FilterRule[] + text: string, + filterRules: FilterRule[] ): string { - return filterRules.reduce((text, filterRule) => { - const { source, target } = filterRule; + return filterRules.reduce((text, filterRule) => { + const { source, target } = filterRule; - return text.replace(source, target); - }, text); + return text.replace(source, target); + }, text); } /** - * Replace "Title - X Remix" suffix with "Title (X Remix) and similar". + * Replace "Title - X Remix" suffix with "Title (X Remix)" and similar. * * @param text String to be filtered * * @return Filtered string */ export function fixTrackSuffix(text: string): string { - return filterWithFilterRules(text, SUFFIX_FILTER_RULES); + return filterWithFilterRules(text, SUFFIX_FILTER_RULES); } /** @@ -100,7 +100,7 @@ export function fixTrackSuffix(text: string): string { * @return Filtered string */ export function fixVariousArtists(text: string): string { - return filterWithFilterRules(text, VARIOUS_ARTISTS_FILTER_RULES); + return filterWithFilterRules(text, VARIOUS_ARTISTS_FILTER_RULES); } /** @@ -111,7 +111,7 @@ export function fixVariousArtists(text: string): string { * @return Transformed string */ export function normalizeFeature(text: string): string { - return filterWithFilterRules(text, NORMALIZE_FEATURE_FILTER_RULES); + return filterWithFilterRules(text, NORMALIZE_FEATURE_FILTER_RULES); } /** @@ -122,7 +122,7 @@ export function normalizeFeature(text: string): string { * @return Filtered string */ export function removeCleanExplicit(text: string): string { - return filterWithFilterRules(text, CLEAN_EXPLICIT_FILTER_RULES); + return filterWithFilterRules(text, CLEAN_EXPLICIT_FILTER_RULES); } /** @@ -133,7 +133,7 @@ export function removeCleanExplicit(text: string): string { * @return Filtered string */ export function removeFeature(text: string): string { - return filterWithFilterRules(text, FEATURE_FILTER_RULES); + return filterWithFilterRules(text, FEATURE_FILTER_RULES); } /** @@ -144,7 +144,7 @@ export function removeFeature(text: string): string { * @return Filtered string */ export function removeAdditionalArtists(text: string): string { - return filterWithFilterRules(text, ADDITIONAL_ARTISTS_FILTER_RULES); + return filterWithFilterRules(text, ADDITIONAL_ARTISTS_FILTER_RULES); } /** @@ -155,21 +155,29 @@ export function removeAdditionalArtists(text: string): string { * @return Filtered string */ export function removeLive(text: string): string { - return filterWithFilterRules(text, LIVE_FILTER_RULES); + return filterWithFilterRules(text, LIVE_FILTER_RULES); } /** * Remove "(Parody of "X" by Y)"-like strings from the text. + * * @param text String to be filtered * * @return Filtered string */ export function removeParody(text: string): string { - return filterWithFilterRules(text, PARODY_FILTER_RULES); + return filterWithFilterRules(text, PARODY_FILTER_RULES); } +/** + * Remove "Re-issue"-like strings from the text. + * + * @param text String to be filtered + * + * @return Filtered string + */ export function removeReissue(text: string): string { - return filterWithFilterRules(text, REISSUE_FILTER_RULES); + return filterWithFilterRules(text, REISSUE_FILTER_RULES); } /** @@ -180,18 +188,18 @@ export function removeReissue(text: string): string { * @return Filtered string */ export function removeRemastered(text: string): string { - return filterWithFilterRules(text, REMASTERED_FILTER_RULES); + return filterWithFilterRules(text, REMASTERED_FILTER_RULES); } /** - * Remove "(Single|Album|Mono version}"-like strings from the text. + * Remove "(Single|Album|Mono version)"-like strings from the text. * * @param text String to be filtered * * @return Filtered string */ export function removeVersion(text: string): string { - return filterWithFilterRules(text, VERSION_FILTER_RULES); + return filterWithFilterRules(text, VERSION_FILTER_RULES); } /** @@ -202,7 +210,7 @@ export function removeVersion(text: string): string { * @return Filtered string */ export function removeZeroWidth(text: string): string { - return text.replace(/[\u200B-\u200D\uFEFF]/g, ''); + return text.replace(/[\u200B-\u200D\uFEFF]/g, ''); } /** @@ -213,7 +221,7 @@ export function removeZeroWidth(text: string): string { * @return Filtered string */ export function replaceNbsp(text: string): string { - return text.replace(/\u00a0/g, '\u0020'); + return text.replace(/\u00a0/g, '\u0020'); } /** @@ -224,10 +232,10 @@ export function replaceNbsp(text: string): string { * @return Filtered string */ export function youtube(text: string): string { - return filterWithFilterRules(text, [ - ...YOUTUBE_TRACK_FILTER_RULES, - ...TRIM_SYMBOLS_FILTER_RULES, - ]); + return filterWithFilterRules(text, [ + ...YOUTUBE_TRACK_FILTER_RULES, + ...TRIM_SYMBOLS_FILTER_RULES, + ]); } /** @@ -238,5 +246,5 @@ export function youtube(text: string): string { * @return Filtered string */ export function replaceSmartQuotes(text: string): string { - return text.replace(/[\u2018\u2019]/g, "'").replace(/[\u201c\u201d]/g, '"'); + return text.replace(/[\u2018\u2019]/g, "'").replace(/[\u201c\u201d]/g, '"'); } diff --git a/src/rules.ts b/src/rules.ts index 0a52d5c..1eeebe7 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -7,94 +7,94 @@ * function. */ export interface FilterRule { - /** - * String or pattern to replace. - */ - source: RegExp | string; - - /** - * Replacement string. - */ - target: string; + /** + * String or pattern to replace. + */ + source: RegExp | string; + + /** + * Replacement string. + */ + target: string; } export const CLEAN_EXPLICIT_FILTER_RULES: FilterRule[] = [ - // (Explicit) or [Explicit] - { source: /\s[([]Explicit[)\]]/i, target: '' }, - // (Clean) or [Clean] - { source: /\s[([]Clean[)\]]/i, target: '' }, + // (Explicit) or [Explicit] + { source: /\s[([]Explicit[)\]]/i, target: '' }, + // (Clean) or [Clean] + { source: /\s[([]Clean[)\]]/i, target: '' }, ]; export const FEATURE_FILTER_RULES: FilterRule[] = [ - // [Feat. Artist] or (Feat. Artist) - { source: /\s[([]feat. .+[)\]]/i, target: '' }, - { source: /\s(feat. .+)/i, target: '' }, + // [Feat. Artist] or (Feat. Artist) + { source: /\s[([]feat. .+[)\]]/i, target: '' }, + { source: /\s(feat. .+)/i, target: '' }, ]; export const LIVE_FILTER_RULES: FilterRule[] = [ - // Track - Live - // Track - Live at - { source: /\s-\sLive(\s.+)?$/, target: '' }, - // Track (Live) - { source: /\s[([]Live[)\]]$/, target: '' }, + // Track - Live + // Track - Live at + { source: /\s-\sLive(\s.+)?$/, target: '' }, + // Track (Live) + { source: /\s[([]Live[)\]]$/, target: '' }, ]; -export const NORMALIZE_FEATURE_FILTER_RULES = [ - // [Feat. Artist] or (Feat. Artist) -> Feat. Artist - { source: /\s[([](feat. .+)[)\]]/i, target: ' $1' }, +export const NORMALIZE_FEATURE_FILTER_RULES: FilterRule[] = [ + // [Feat. Artist] or (Feat. Artist) -> Feat. Artist + { source: /\s[([](feat. .+)[)\]]/i, target: ' $1' }, ]; export const PARODY_FILTER_RULES: FilterRule[] = [ - // Party In the CIA (Parody of "Party In The U.S.A." by Miley Cyrus) - { source: /\s\(Parody of ".*" by .*\)$/, target: '' }, - // White & Nerdy (Parody of "Ridin'" by Chamillionaire feat. Krayzie Bone) - { source: /\s\(Parody of ".*" by .* feat\. .*\)$/, target: '' }, - // The Saga Begins (Lyrical Adaption of "American Pie") - { source: /\s\(Lyrical Adaption of ".*"\)$/, target: '' }, + // Party In the CIA (Parody of "Party In The U.S.A." by Miley Cyrus) + { source: /\s\(Parody of ".*" by .*\)$/, target: '' }, + // White & Nerdy (Parody of "Ridin'" by Chamillionaire feat. Krayzie Bone) + { source: /\s\(Parody of ".*" by .* feat\. .*\)$/, target: '' }, + // The Saga Begins (Lyrical Adaption of "American Pie") + { source: /\s\(Lyrical Adaption of ".*"\)$/, target: '' }, ]; export const REISSUE_FILTER_RULES: FilterRule[] = [ - // Album Title Re-issue - { source: /\sRe-?issue$/i, target: '' }, - // Album Title [Whatever Re-issue Whatever] - { source: /\s\[.*?Re-?issue.*?\]/i, target: '' }, - // Album Title (Whatever Re-issue Whatever) - { source: /\s\(.*?Re-?issue.*?\)/i, target: '' }, + // Album Title Re-issue + { source: /\sRe-?issue$/i, target: '' }, + // Album Title [Whatever Re-issue Whatever] + { source: /\s\[.*?Re-?issue.*?\]/i, target: '' }, + // Album Title (Whatever Re-issue Whatever) + { source: /\s\(.*?Re-?issue.*?\)/i, target: '' }, ]; /** * Filter rules to remove "Remastered..."-like strings from a text. */ export const REMASTERED_FILTER_RULES: FilterRule[] = [ - // Ticket To Ride - Live / Remastered - { source: /Live\s\/\sRemastered/, target: 'Live' }, - // Mothership (Remastered) - // Let It Be (Remastered 2009) - // How The West Was Won [Remastered] - // Ride the Lightning (Deluxe Remaster) - // ...And Justice For All (Remastered Deluxe Box Set) - { source: /\s[([].*Re-?[Mm]aster(ed)?.*[)\]]$/, target: '' }, - // Outside The Wall - 2011 - Remaster - // China Grove - 2006 Remaster - // Easy Living - 2003 Remastered - // Learning To Fly - 2001 Digital Remaster - // Red Right Hand - 2011 Remastered Version - { source: /\s-\s\d{4}(\s-)?\s.*Re-?[Mm]aster(ed)?.*$/, target: '' }, - // Here Comes The Sun - Remastered - // 1979 - Remastered 2012 - // 1979 - Remastered Version - { source: /\s-\sRe-?[Mm]aster(ed)?.*$/, target: '' }, - // Wish You Were Here [Remastered] (Remastered Version) - { source: /\s\[Remastered\]\s\(Remastered\sVersion\)$/, target: '' }, + // Ticket To Ride - Live / Remastered + { source: /Live\s\/\sRemastered/, target: 'Live' }, + // Mothership (Remastered) + // Let It Be (Remastered 2009) + // How The West Was Won [Remastered] + // Ride the Lightning (Deluxe Remaster) + // ...And Justice For All (Remastered Deluxe Box Set) + { source: /\s[([].*Re-?[Mm]aster(ed)?.*[)\]]$/, target: '' }, + // Outside The Wall - 2011 - Remaster + // China Grove - 2006 Remaster + // Easy Living - 2003 Remastered + // Learning To Fly - 2001 Digital Remaster + // Red Right Hand - 2011 Remastered Version + { source: /\s-\s\d{4}(\s-)?\s.*Re-?[Mm]aster(ed)?.*$/, target: '' }, + // Here Comes The Sun - Remastered + // 1979 - Remastered 2012 + // 1979 - Remastered Version + { source: /\s-\sRe-?[Mm]aster(ed)?.*$/, target: '' }, + // Wish You Were Here [Remastered] (Remastered Version) + { source: /\s\[Remastered\]\s\(Remastered\sVersion\)$/, target: '' }, ]; export const SUFFIX_FILTER_RULES: FilterRule[] = [ - // "- X Remix" -> "(X Remix)" and similar - { - source: /-\s(.+?)\s((Re)?mix|edit|dub|mix|vip|version)$/i, - target: '($1 $2)', - }, - { source: /-\s(Remix|VIP|Instrumental)$/i, target: '($1)' }, + // "- X Remix" -> "(X Remix)" and similar + { + source: /-\s(.+?)\s((Re)?mix|edit|dub|mix|vip|version)$/i, + target: '($1 $2)', + }, + { source: /-\s(Remix|VIP|Instrumental)$/i, target: '($1)' }, ]; /** @@ -102,14 +102,14 @@ export const SUFFIX_FILTER_RULES: FilterRule[] = [ * `YOUTUBE_TRACK_FILTER_RULES` filter rules. */ export const TRIM_SYMBOLS_FILTER_RULES: FilterRule[] = [ - // Leftovers after e.g. (official video) - { source: /\(+\s*\)+/, target: '' }, - // trim starting white chars and dash - { source: /^[/,:;~\s"-]+/, target: '' }, - // trim trailing white chars and dash - { source: /[/,:;~\s"-]+$/, target: '' }, - // remove multiple spaces - { source: /\u0020{1,}/, target: ' ' }, + // Leftovers after e.g. (official video) + { source: /\(+\s*\)+/, target: '' }, + // trim starting white chars and dash + { source: /^[/,:;~\s"-]+/, target: '' }, + // trim trailing white chars and dash + { source: /[/,:;~\s"-]+$/, target: '' }, + // remove multiple spaces + { source: /\u0020{1,}/, target: ' ' }, ]; /** @@ -118,7 +118,7 @@ export const TRIM_SYMBOLS_FILTER_RULES: FilterRule[] = [ * rejected. */ export const VARIOUS_ARTISTS_FILTER_RULES: FilterRule[] = [ - { source: /(Various Artists).+/, target: '$1' }, + { source: /(Various Artists).+/, target: '$1' }, ]; /** @@ -126,110 +126,190 @@ export const VARIOUS_ARTISTS_FILTER_RULES: FilterRule[] = [ * from a text. */ export const VERSION_FILTER_RULES: FilterRule[] = [ - // Love Will Come To You (Album Version) - { source: /\s[([]Album Version[)\]]$/, target: '' }, - // I Melt With You (Rerecorded) - // When I Need You [Re-Recorded] - { source: /\s[([]Re-?recorded[)\]]$/, target: '' }, - // Your Cheatin' Heart (Single Version) - { source: /\s[([]Single Version[)\]]$/, target: '' }, - // All Over Now (Edit) - { source: /\s[([]Edit[)\]]$/, target: '' }, - // (I Can't Get No) Satisfaction - Mono Version - { source: /\s-\sMono Version$/, target: '' }, - // Ruby Tuesday - Stereo Version - { source: /\s-\sStereo Version$/, target: '' }, - // Pure McCartney (Deluxe Edition) - { source: /\s\(Deluxe Edition\)$/, target: '' }, - // Ace of Spades (Expanded Edition) - // Overkill (Expanded Bonus Track Edition) - // On Parole (Expanded and Remastered) - { source: /\s[([]Expanded.*[)\]]$/, target: '' }, - // Sound of White Noise - Expanded Edition - { source: /\s-\sExpanded Edition$/, target: '' }, - // 6 Foot 7 Foot (Explicit Version) - { source: /\s[([]Explicit Version[)\]]/i, target: '' }, - // No Remorse (Bonus Track Edition) - { source: /\s[([]Bonus Track Edition[)\]]/i, target: '' }, - // Peace Sells...But Who's Buying (25th Anniversary) - // Persistence of Time (30th Anniversary Remaster) - { source: /\s[([]\d+th\sAnniversary.*[)\]]/i, target: '' }, - // 6 Foot 7 Foot - Original - { source: /\s-\sOriginal$/i, target: '' }, - // California Love - Original Version - // Personal Jesus - Original Single Version - // Prince of the Moment - Original 7" Version - // YMCA - Original Version 1978 - { source: /\s-\sOriginal.*Version(\s\d{4})?$/i, target: '' }, + // Love Will Come To You (Album Version) + { source: /\s[([]Album Version[)\]]$/, target: '' }, + // I Melt With You (Rerecorded) + // When I Need You [Re-Recorded] + { source: /\s[([]Re-?recorded[)\]]$/, target: '' }, + // Your Cheatin' Heart (Single Version) + { source: /\s[([]Single Version[)\]]$/, target: '' }, + // All Over Now (Edit) + { source: /\s[([]Edit[)\]]$/, target: '' }, + // (I Can't Get No) Satisfaction - Mono Version + { source: /\s-\sMono Version$/, target: '' }, + // Ruby Tuesday - Stereo Version + { source: /\s-\sStereo Version$/, target: '' }, + // Pure McCartney (Deluxe Edition) + { source: /\s\(Deluxe Edition\)$/, target: '' }, + // Ace of Spades (Expanded Edition) + // Overkill (Expanded Bonus Track Edition) + // On Parole (Expanded and Remastered) + { source: /\s[([]Expanded.*[)\]]$/, target: '' }, + // Sound of White Noise - Expanded Edition + { source: /\s-\sExpanded Edition$/, target: '' }, + // 6 Foot 7 Foot (Explicit Version) + { source: /\s[([]Explicit Version[)\]]/i, target: '' }, + // No Remorse (Bonus Track Edition) + { source: /\s[([]Bonus Track Edition[)\]]/i, target: '' }, + // Peace Sells...But Who's Buying (25th Anniversary) + // Persistence of Time (30th Anniversary Remaster) + { source: /\s[([]\d+th\sAnniversary.*[)\]]/i, target: '' }, + // 6 Foot 7 Foot - Original + { source: /\s-\sOriginal$/i, target: '' }, + // California Love - Original Version + // Personal Jesus - Original Single Version + // Prince of the Moment - Original 7" Version + // YMCA - Original Version 1978 + { source: /\s-\sOriginal.*Version(\s\d{4})?$/i, target: '' }, ]; /** * Filter rules to remove YouTube suffixes and prefixes from a text. */ export const YOUTUBE_TRACK_FILTER_RULES: FilterRule[] = [ - // Trim whitespaces - { source: /^\s+|\s+$/g, target: '' }, - // **NEW** - { source: /\*+\s?\S+\s?\*+$/, target: '' }, - // [Whatever] - { source: /\[[^\]]+\]/, target: '' }, - // 【Whatever】 - { source: /【[^\]]+】/, target: '' }, - // (Whatever) - { source: /([^\]]+)/, target: '' }, - // (Whatever Version) - { source: /\([^)]*version\)$/i, target: '' }, - // Video extensions - { source: /\.(avi|wmv|mpg|mpeg|flv)$/i, target: '' }, - // (Lyrics Video) - { source: /\(.*lyrics?\s*(video)?\)/i, target: '' }, - // ((Official)? (Track)? Stream) - { source: /\((of+icial\s*)?(track\s*)?stream\)/i, target: '' }, - // ((Official)? (Music|HD)? Video|Audio) - { source: /\((of+icial\s*)?((music|hd)\s*)?(video|audio)\)/i, target: '' }, - // - (Official)? (Music)? Video|Audio - { source: /-\s(of+icial\s*)?(music\s*)?(video|audio)$/i, target: '' }, - // ((Whatever)? Album Track) - { source: /\(.*Album\sTrack\)/i, target: '' }, - // (Official) - { source: /\(\s*of+icial\s*\)/i, target: '' }, - // (1999) - { source: /\(\s*[0-9]{4}\s*\)/i, target: '' }, - // (HD) / (HQ) - { source: /\(\s*(HD|HQ)\s*\)$/, target: '' }, - // HD / HQ - { source: /(HD|HQ)\s?$/, target: '' }, - // Video Clip Officiel / Video Clip Official - { source: /(vid[\u00E9e]o)?\s?clip\sof+ici[ae]l/i, target: '' }, - // Offizielles - { source: /of+iziel+es\s*video/i, target: '' }, - // Video Clip - { source: /vid[\u00E9e]o\s?clip/i, target: '' }, - // Clip - { source: /\sclip/i, target: '' }, - // Full Album - { source: /full\s*album/i, target: '' }, - // (Live) - { source: /\(live.*?\)$/i, target: '' }, - // | Something - { source: /\|.*$/i, target: '' }, - // Artist - The new "Track title" featuring someone - { source: /^(|.*\s)"(.{5,})"(\s.*|)$/, target: '$2' }, - // 'Track title' - { source: /^(|.*\s)'(.{5,})'(\s.*|)$/, target: '$2' }, - // (*01/01/1999*) - { source: /\(.*[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}.*\)/i, target: '' }, - // Sub Español - { source: /sub\s*español/i, target: '' }, - // (Letra) - { source: /\s\(Letra\)/i, target: '' }, - // (En vivo) - { source: /\s\(En\svivo\)/i, target: '' }, - // Sub Español - { source: /sub\s*español/i, target: '' }, + // Trim whitespaces + { source: /^\s+|\s+$/g, target: '' }, + // **NEW** + { source: /\*+\s?\S+\s?\*+$/, target: '' }, + // [Whatever] + { source: /\[[^\]]+\]/, target: '' }, + // 【Whatever】 + { source: /【[^\]]+】/, target: '' }, + // (Whatever) + { source: /([^\]]+)/, target: '' }, + // (Whatever Version) + { source: /\([^)]*version\)$/i, target: '' }, + // Video extensions + { source: /\.(avi|wmv|mpg|mpeg|flv)$/i, target: '' }, + // (Lyrics Video) + { source: /\(.*lyrics?\s*(video)?\)/i, target: '' }, + // ((Official)? (Track)? Stream) + { source: /\((of+icial\s*)?(track\s*)?stream\)/i, target: '' }, + // ((Official)? (Music|HD)? Video|Audio) + { source: /\((of+icial\s*)?((music|hd)\s*)?(video|audio)\)/i, target: '' }, + // - (Official)? (Music)? Video|Audio + { source: /-\s(of+icial\s*)?(music\s*)?(video|audio)$/i, target: '' }, + // ((Whatever)? Album Track) + { source: /\(.*Album\sTrack\)/i, target: '' }, + // (Official) + { source: /\(\s*of+icial\s*\)/i, target: '' }, + // (1999) + { source: /\(\s*[0-9]{4}\s*\)/i, target: '' }, + // (HD) / (HQ) + { source: /\(\s*(HD|HQ)\s*\)$/, target: '' }, + // HD / HQ + { source: /(HD|HQ)\s?$/, target: '' }, + // Video Clip Officiel / Video Clip Official + { source: /(vid[\u00E9e]o)?\s?clip\sof+ici[ae]l/i, target: '' }, + // Offizielles + { source: /of+iziel+es\s*video/i, target: '' }, + // Video Clip + { source: /vid[\u00E9e]o\s?clip/i, target: '' }, + // Clip + { source: /\sclip/i, target: '' }, + // Full Album + { source: /full\s*album/i, target: '' }, + // (Live) + { source: /\(live.*?\)$/i, target: '' }, + // | Something + { source: /\|.*$/i, target: '' }, + // Artist - The new "Track title" featuring someone + { source: /^(|.*\s)"(.{5,})"(\s.*|)$/, target: '$2' }, + // 'Track title' + { source: /^(|.*\s)'(.{5,})'(\s.*|)$/, target: '$2' }, + // (*01/01/1999*) + { source: /\(.*[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}.*\)/i, target: '' }, + // Sub Español + { source: /sub\s*español/i, target: '' }, + // (Letra) + { source: /\s\(Letra\)/i, target: '' }, + // (En vivo) + { source: /\s\(En\svivo\)/i, target: '' }, + // Sub Español + { source: /sub\s*español/i, target: '' }, ]; export const ADDITIONAL_ARTISTS_FILTER_RULES: FilterRule[] = [ - { source: /\s(& .+)/i, target: '' }, - { source: /\s(x .+)/i, target: '' }, + { source: /\s(& .+)/i, target: '' }, + { source: /\s(x .+)/i, target: '' }, +]; + +/** + * Filter rules to remove "Acoustic" and similar strings from a text. + */ +export const ACOUSTIC_FILTER_RULES: FilterRule[] = [ + // Track - Acoustic + { source: /\s-\sAcoustic$/, target: '' }, + // Track (Acoustic) + { source: /\s[([]Acoustic[)\]]$/, target: '' }, +]; + +/** + * Filter rules to remove "Demo" and similar strings from a text. + */ +export const DEMO_FILTER_RULES: FilterRule[] = [ + // Track - Demo + { source: /\s-\sDemo$/, target: '' }, + // Track (Demo) + { source: /\s[([]Demo[)\]]$/, target: '' }, +]; + +/** + * Filter rules to remove "Instrumental" and similar strings from a text. + */ +export const INSTRUMENTAL_FILTER_RULES: FilterRule[] = [ + // Track - Instrumental + { source: /\s-\sInstrumental$/, target: '' }, + // Track (Instrumental) + { source: /\s[([]Instrumental[)\]]$/, target: '' }, +]; + +/** + * Filter rules to remove "Radio Edit" and similar strings from a text. + */ +export const RADIO_EDIT_FILTER_RULES: FilterRule[] = [ + // Track - Radio Edit + { source: /\s-\sRadio Edit$/, target: '' }, + // Track (Radio Edit) + { source: /\s[([]Radio Edit[)\]]$/, target: '' }, +]; + +/** + * Filter rules to remove "Deluxe Edition" and similar strings from a text. + */ +export const DELUXE_EDITION_FILTER_RULES: FilterRule[] = [ + // Track (Deluxe Edition) + { source: /\s[([]Deluxe Edition[)\]]$/, target: '' }, + // Track - Deluxe Edition + { source: /\s-\sDeluxe Edition$/, target: '' }, +]; + +/** + * Filter rules to remove "Extended Version" and similar strings from a text. + */ +export const EXTENDED_VERSION_FILTER_RULES: FilterRule[] = [ + // Track (Extended Version) + { source: /\s[([]Extended Version[)\]]$/, target: '' }, + // Track - Extended Version + { source: /\s-\sExtended Version$/, target: '' }, +]; + +/** + * Filter rules to remove "Remix" and similar strings from a text. + */ +export const REMIX_FILTER_RULES: FilterRule[] = [ + // Track (Remix) + { source: /\s[([]Remix[)\]]$/, target: '' }, + // Track - Remix + { source: /\s-\sRemix$/, target: '' }, +]; + +/** + * Filter rules to remove "Cover" and similar strings from a text. + */ +export const COVER_FILTER_RULES: FilterRule[] = [ + // Track (Cover) + { source: /\s[([]Cover[)\]]$/, target: '' }, + // Track - Cover + { source: /\s-\sCover$/, target: '' }, ];