Repository: ROpdebee/mb-userscripts
Pull request #781 (2024-07-26 17:10:19)

fix: remove extraneous spacing in JSX-transpiled HTML
Update nativejsx to trim extraneous whitespace. An example of the bug can be seen in the recent caa_dims changelog notifications, where there's a space before the period after the anchor. Normal JSX allegedly removes such whitespace, so we should too.


Patch:
diff --git a/package-lock.json b/package-lock.json
index 22404248..7649ffe2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11452,8 +11452,9 @@
     },
     "node_modules/nativejsx": {
       "version": "4.3.0",
-      "resolved": "git+ssh://git@github.com/ROpdebee/nativejsx.git#f2bed01d621bb158134e13ed3abb9be9e265cd00",
+      "resolved": "git+ssh://git@github.com/ROpdebee/nativejsx.git#dc9d4694ff92c78f76b153e44af69948b035a5a4",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "acorn": "^8.3.0",
         "acorn-jsx": "^5.3.1",
diff --git a/src/mb_enhanced_cover_art_uploads/docs/supported_providers.md b/src/mb_enhanced_cover_art_uploads/docs/supported_providers.md
index 7f47f366..1c738229 100644
--- a/src/mb_enhanced_cover_art_uploads/docs/supported_providers.md
+++ b/src/mb_enhanced_cover_art_uploads/docs/supported_providers.md
@@ -29,7 +29,7 @@ The following table describes the types of links supported by MB: Upload to CAA
 | Qobuz | ✔️ | ✔️ | Goodies are grabbed whenever possible. Back covers might not be supported at this time, if you have a release with a back cover, please let me know. Maximised to original source image. |
 | RateYourMusic | ✔️ | ✔️ | Requires being logged in to RYM. |
 | Rockipedia | ✔️ | ❌ |
-| Soundcloud | ✔️ | ✔️ | Grabs custom track images. |
+| SoundCloud | ✔️ | ✔️ | Grabs custom track images. |
 | Spotify | ✔️ | ✔️ |
 | Tidal | ✔️ | ✔️ | listen.tidal.com/store.tidal.com are converted to tidal.com prior to fetching |
 | Traxsource | ✔️ | ✔️ | Limited to 600x600. |
diff --git a/src/mb_enhanced_cover_art_uploads/providers/base.ts b/src/mb_enhanced_cover_art_uploads/providers/base.ts
index fde8ad7f..9da9b78b 100644
--- a/src/mb_enhanced_cover_art_uploads/providers/base.ts
+++ b/src/mb_enhanced_cover_art_uploads/providers/base.ts
@@ -163,7 +163,7 @@ export abstract class ProviderWithTrackImages extends CoverArtProvider {
     // Providers that provide track images which need to be deduplicated. The
     // base class supports deduping by URL and thumbnail content.
     //
-    // Some providers, like Soundcloud and sometimes Bandcamp, use unique URLs
+    // Some providers, like SoundCloud and sometimes Bandcamp, use unique URLs
     // for each track image, so deduplicating based on URL won't work. They may
     // also not return any headers that uniquely identify the image (like a
     // Digest or an ETag), so we need to load the image and compare its data
diff --git a/src/mb_enhanced_cover_art_uploads/providers/index.ts b/src/mb_enhanced_cover_art_uploads/providers/index.ts
index 9609a182..4cd5d2ea 100644
--- a/src/mb_enhanced_cover_art_uploads/providers/index.ts
+++ b/src/mb_enhanced_cover_art_uploads/providers/index.ts
@@ -25,7 +25,7 @@ import { NetEaseProvider } from './netease';
 import { QobuzProvider } from './qobuz';
 import { RateYourMusicProvider } from './rateyourmusic';
 import { RockipediaProvider } from './rockipedia';
-import { SoundcloudProvider } from './soundcloud';
+import { SoundCloudProvider } from './soundcloud';
 import { SpotifyProvider } from './spotify';
 import { TidalProvider } from './tidal';
 import { TraxsourceProvider } from './traxsource';
@@ -68,7 +68,7 @@ addProvider(new QobuzProvider());
 addProvider(new RateYourMusicProvider());
 addProvider(new RockipediaProvider());
 addProvider(new SevenDigitalProvider());
-addProvider(new SoundcloudProvider());
+addProvider(new SoundCloudProvider());
 addProvider(new SpotifyProvider());
 addProvider(new TidalProvider());
 addProvider(new TraxsourceProvider());
diff --git a/src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts b/src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts
index 72abdb98..ab1def5c 100644
--- a/src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts
+++ b/src/mb_enhanced_cover_art_uploads/providers/soundcloud.ts
@@ -51,11 +51,11 @@ const SC_CLIENT_ID_REGEX = /client_id\s*:\s*"([a-zA-Z\d]{32})"/;
 const SC_CLIENT_ID_CACHE_KEY = 'ROpdebee_ECAU_SC_ID';
 const SC_HOMEPAGE = 'https://soundcloud.com/';
 
-export class SoundcloudProvider extends ProviderWithTrackImages {
+export class SoundCloudProvider extends ProviderWithTrackImages {
     public readonly supportedDomains = ['soundcloud.com'];
     public readonly favicon = 'https://a-v2.sndcdn.com/assets/images/sc-icons/favicon-2cadd14bdb.ico';
-    public readonly name = 'Soundcloud';
-    // Soundcloud's URL scheme is a bit complicated, so instead of creating overly
+    public readonly name = 'SoundCloud';
+    // SoundCloud's URL scheme is a bit complicated, so instead of creating overly
     // complex regular expressions, we'll match URLs programmatically. However,
     // we still need to define this field, even though it'll never be used.
     protected readonly urlRegex = [];
@@ -88,7 +88,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
             }
         }
 
-        throw new Error('Could not extract Soundcloud Client ID');
+        throw new Error('Could not extract SoundCloud Client ID');
     }
 
     private static async getClientID(): Promise<string> {
@@ -106,7 +106,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
         const oldId = await this.getClientID();
         const newId = await this.loadClientID();
 
-        assert(oldId !== newId, 'Attempted to refresh Soundcloud Client ID but retrieved the same one.');
+        assert(oldId !== newId, 'Attempted to refresh SoundCloud Client ID but retrieved the same one.');
         localStorage.setItem(SC_CLIENT_ID_CACHE_KEY, newId);
     }
 
@@ -120,10 +120,10 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
             .split('/');
 
         return (pathParts.length > 0
-            && !SoundcloudProvider.badArtistIDs.has(artistId)
+            && !SoundCloudProvider.badArtistIDs.has(artistId)
             // artist/likes, artist/track/recommended, artist/sets, ...
             // but not artist/sets/setname!
-            && !SoundcloudProvider.badSubpaths.has(urlBasename(url)));
+            && !SoundCloudProvider.badSubpaths.has(urlBasename(url)));
     }
 
     public override extractId(url: URL): string | undefined {
@@ -141,7 +141,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
         const metadata = this.extractMetadataFromJS(pageContent)
             ?.find((data) => ['sound', 'playlist'].includes(data.hydratable));
         if (!metadata) {
-            throw new Error('Could not extract metadata from Soundcloud page. The release may have been removed.');
+            throw new Error('Could not extract metadata from SoundCloud page. The release may have been removed.');
         }
 
         if (metadata.hydratable === 'sound') {
@@ -175,7 +175,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
             covers.push(...backdrops.map((backdropUrl) => ({
                 url: new URL(backdropUrl),
                 types: [ArtworkTypeIDs.Other],
-                comment: 'Soundcloud backdrop',
+                comment: 'SoundCloud backdrop',
             })));
         }
 
@@ -195,7 +195,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
         // Don't bother extracting track covers if they won't be used anyway
         if (onlyFront) return covers;
 
-        // Soundcloud page only contains data for the first 5 tracks at first,
+        // SoundCloud page only contains data for the first 5 tracks at first,
         // we need to load the rest of the tracks.
         const tracks = await this.lazyLoadTracks(metadata.data.tracks);
 
@@ -215,7 +215,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
                 trackImages.push(...visuals.map((visualUrl) => ({
                     url: visualUrl,
                     trackNumber: (trackNumber + 1).toString(),
-                    customCommentPrefix: ['Soundcloud backdrop for track', 'Soundcloud backdrop for tracks'] as [string, string],
+                    customCommentPrefix: ['SoundCloud backdrop for track', 'SoundCloud backdrop for tracks'] as [string, string],
                 })));
 
                 return trackImages;
@@ -235,7 +235,7 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
         try {
             trackData = await this.getTrackData(lazyTrackIDs);
         } catch (error) {
-            LOGGER.error('Failed to load Soundcloud track data, some track images may be missed', error);
+            LOGGER.error('Failed to load SoundCloud track data, some track images may be missed', error);
             // We'll still return the tracks that we couldn't load, otherwise
             // the track indices will be wrong.
             return tracks;
@@ -260,8 +260,8 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
     }
 
     private async getTrackData(lazyTrackIDs: number[], firstTry = true): Promise<SCHydrationTrack[]> {
-        LOGGER.info('Loading Soundcloud track data');
-        const clientId = await SoundcloudProvider.getClientID();
+        LOGGER.info('Loading SoundCloud track data');
+        const clientId = await SoundCloudProvider.getClientID();
 
         // TODO: Does this work still work if we pass a large list of IDs?
         const parameters = new URLSearchParams({
@@ -278,11 +278,11 @@ export class SoundcloudProvider extends ProviderWithTrackImages {
             }
 
             LOGGER.debug('Attempting to refresh client ID');
-            await SoundcloudProvider.refreshClientID();
+            await SoundCloudProvider.refreshClientID();
             return this.getTrackData(lazyTrackIDs, firstTry = false);
         }
 
-        return safeParseJSON<LoadedAPITrack[]>(trackDataResponse.text, 'Failed to parse Soundcloud API response');
+        return safeParseJSON<LoadedAPITrack[]>(trackDataResponse.text, 'Failed to parse SoundCloud API response');
     }
 
     private extractVisuals(track: SCHydrationTrack): string[] {


Test patch:
diff --git a/tests/unit/mb_enhanced_cover_art_uploads/providers/soundcloud.test.ts b/tests/unit/mb_enhanced_cover_art_uploads/providers/soundcloud.test.ts
index 538f62b7..d5b71818 100644
--- a/tests/unit/mb_enhanced_cover_art_uploads/providers/soundcloud.test.ts
+++ b/tests/unit/mb_enhanced_cover_art_uploads/providers/soundcloud.test.ts
@@ -1,6 +1,6 @@
 import { LOGGER } from '@lib/logging/logger';
 import { ArtworkTypeIDs } from '@lib/MB/cover-art';
-import { SoundcloudProvider } from '@src/mb_enhanced_cover_art_uploads/providers/soundcloud';
+import { SoundCloudProvider } from '@src/mb_enhanced_cover_art_uploads/providers/soundcloud';
 import { setupPolly } from '@test-utils/pollyjs';
 import { itBehavesLike } from '@test-utils/shared-behaviour';
 
@@ -16,7 +16,7 @@ afterEach(() => {
 });
 
 describe('soundcloud provider', () => {
-    const provider = new SoundcloudProvider();
+    const provider = new SoundCloudProvider();
     const pollyContext = setupPolly();
 
     describe('url matching', () => {
@@ -113,7 +113,7 @@ describe('soundcloud provider', () => {
                 index: 3,
                 urlPart: '9b0d4395-cc72-4aa9-84e1-17b807264e2f',
                 types: [ArtworkTypeIDs.Track],
-                comment: 'Soundcloud backdrop for tracks 2, 4, 6, 8, 10, 18, 20',
+                comment: 'SoundCloud backdrop for tracks 2, 4, 6, 8, 10, 18, 20',
             }],
         }];
 
@@ -168,7 +168,7 @@ describe('soundcloud provider', () => {
             const covers = await provider.findImages(new URL('https://soundcloud.com/soundcloud/sets/i-am-other-vol-2'));
 
             expect(covers).toBeArrayOfSize(6);
-            expect(mockLoggerError).toHaveBeenCalledWith('Failed to load Soundcloud track data, some track images may be missed', expect.any(Error));
+            expect(mockLoggerError).toHaveBeenCalledWith('Failed to load SoundCloud track data, some track images may be missed', expect.any(Error));
         });
 
         it('attempts to refresh client ID', async () => {