« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/reformat-urls.js89
-rw-r--r--src/validators.js40
2 files changed, 112 insertions, 17 deletions
diff --git a/src/reformat-urls.js b/src/reformat-urls.js
index a42d7a4a..69b15de5 100644
--- a/src/reformat-urls.js
+++ b/src/reformat-urls.js
@@ -25,11 +25,82 @@ function https(namespace, domain) {
   ];
 }
 
+function trimQueryParameter(namespace, domain, parameter) {
+  return [
+    `${namespace}: trim ?${parameter} query parameter`,
+
+    re('gmi', [
+      '^(',
+        '- https://',
+        '(?:' + domain + ')',
+        '\/.*',
+      ')',
+
+      '[&?]' + parameter + '=',
+      '[^\n&?]+',
+    ]),
+
+    '$1',
+  ];
+}
+
+function trimTrailingSlash(namespace, domain) {
+  return [
+    `${namespace}: trim trailing slash`,
+
+    re('gmi', [
+      '^(',
+        '- https://',
+        '(?:' + domain + ')',
+        '\/.*',
+      ')',
+
+      '/',
+      '(?=[#?]|$)',
+    ]),
+
+    '$1',
+  ];
+}
+
 
 // Rules are evaluated top to bottom, in order,
 // so each rule can build off previous ones.
 const findreplace = [];
 
+// General
+
+findreplace.push([
+  `general: add slash to stand in for empty path`,
+  re('gmi', ['^(- [a-z]*://[^\n?#/]+)(?=[?#]|$)']),
+  '$1/',
+]);
+
+// Apple Music
+
+findreplace.push([
+  `apple music: trim country code`,
+  /^(- https:\/\/music.apple.com\/)[a-z][a-z]\//gmi,
+  '$1',
+]);
+
+// SoundCloud
+
+findreplace.push(trimTrailingSlash('soundcloud', 'soundcloud.com'));
+
+// Spotify
+
+findreplace.push(trimQueryParameter('spotify', 'open\.spotify\.com', 'si'));
+findreplace.push(trimQueryParameter('spotify', 'open\.spotify\.com', 'nd'));
+
+// Tumblr
+
+findreplace.push([
+  `tumblr: tumblr.com -> www.tumblr.com`,
+  /^- https:\/\/tumblr\.com\//gmi,
+  '- https://www.tumblr.com/',
+]);
+
 // Twitter
 
 const twitterDomains =
@@ -63,23 +134,7 @@ const youtubeDomains =
 
 findreplace.push(https('youtube', youtubeDomains));
 
-findreplace.push([
-  `youtube: trim ?si search parameter`,
-
-  re('gmi', [
-    '^(',
-      '- https://',
-      '(?:' + youtubeDomains + ')',
-      '\/.*',
-    ')',
-
-    '[&?]si=',
-    '[a-z0-9_-]+',
-    '$',
-  ]),
-
-  '$1',
-]);
+findreplace.push(trimQueryParameter('youtube', youtubeDomains, 'si'));
 
 findreplace.push([
   `youtube: youtu.be -> www.youtube.com/watch?v=___`,
diff --git a/src/validators.js b/src/validators.js
index 19d74991..7dcd7b8c 100644
--- a/src/validators.js
+++ b/src/validators.js
@@ -743,6 +743,9 @@ export function isCuratedURL(string) {
       `not ${colors.red(url.hostname)}`);
 
   switch (url.hostname) {
+    case 'tumblr.com':
+      throw useHostname('www.tumblr.com');
+
     case 'www.twitter.com':
     case 'x.com':
       throw useHostname('twitter.com');
@@ -768,12 +771,49 @@ export function isCuratedURL(string) {
     }
   };
 
+  const dropTrailingSlash = () => {
+    if (url.pathname.length >= 3 && url.pathname.endsWith('/')) {
+      throw new Error(
+        `Remove slash at end: ` +
+        url.pathname.slice(0, -1) +
+        colors.bright(colors.red('/')));
+    }
+  };
+
   switch (url.hostname) {
+    case 'soundcloud.com':
+      dropTrailingSlash();
+      break;
+
+    case 'open.spotify.com':
+      dropSearchParam('si', `tracking parameter`);
+      dropSearchParam('nd', `unnecessary parameter`);
+      break;
+
     case 'www.youtube.com':
       dropSearchParam('si', `tracking parameter`);
       break;
   }
 
+  if (url.hostname === 'music.apple.com') {
+    const countryMatch =
+      url.pathname.match(/^\/[a-z][a-z]\//);
+
+    if (countryMatch) {
+      throw new Error(`Remove country code ${colors.red(countryMatch[0])}`);
+    }
+  }
+
+  if (url.pathname === '/' && string === url.origin + url.hash + url.search) {
+    if (url.hash) {
+      throw new Error(`Add slash before "#" hash`);
+    } else if (url.search) {
+      throw new Error(`Add slash before "?" query`);
+    } else {
+      throw new Error(`Add slash at end`);
+    }
+  }
+
   return true;
 }