« get me outta code hell

upd8, etc: curated url validation, tidying modes, --format-urls - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/validators.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2026-04-12 12:14:23 -0300
committer(quasar) nebula <qznebula@protonmail.com>2026-04-12 12:15:04 -0300
commit0d2481ed8abdb084f5c10984181c2a7355d5208a (patch)
treef039a8ef4def20bb8ac9202bdc85a94dfaec3dbb /src/validators.js
parent5fcd8ce38402c6623b57a5dc846c9786a24644f1 (diff)
upd8, etc: curated url validation, tidying modes, --format-urls
Diffstat (limited to 'src/validators.js')
-rw-r--r--src/validators.js58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/validators.js b/src/validators.js
index 73fcf7bc..19d74991 100644
--- a/src/validators.js
+++ b/src/validators.js
@@ -22,6 +22,14 @@ export function setValidatorCreatorMeta(validator, creator, meta) {
   return validator;
 }
 
+// External configuration
+
+let disabledCuratedURLValidation = false;
+
+export function disableCuratedURLValidation() {
+  disabledCuratedURLValidation = true;
+}
+
 // Basic types (primitives)
 
 export function a(noun) {
@@ -719,6 +727,56 @@ export function isURL(string) {
   return true;
 }
 
+export function isCuratedURL(string) {
+  if (disabledCuratedURLValidation) {
+    return isURL(string);
+  }
+
+  // Do the same basic checks as in isURL.
+  // We'll need access to the URL object.
+  const url = new URL(string);
+  decodeURIComponent(url.pathname);
+
+  const useHostname = hostname =>
+    new Error(
+      `Use ${colors.green(hostname)}, ` +
+      `not ${colors.red(url.hostname)}`);
+
+  switch (url.hostname) {
+    case 'www.twitter.com':
+    case 'x.com':
+      throw useHostname('twitter.com');
+
+    case 'youtu.be':
+    case 'youtube.com':
+      throw useHostname('www.youtube.com');
+  }
+
+  const dropSearchParam = (param, message = null) => {
+    if (url.searchParams.has(param)) {
+      const index =
+        Array.from(url.searchParams)
+          .findIndex(entry => entry[0] === param);
+
+      const prefix = (index === 0 ? '?' : '&');
+
+      const value = url.searchParams.get(param);
+
+      throw new Error(
+        `Remove ${colors.red(`${prefix}${param}=${value}`)}` +
+        (message ? ` (${message})` : ''));
+    }
+  };
+
+  switch (url.hostname) {
+    case 'www.youtube.com':
+      dropSearchParam('si', `tracking parameter`);
+      break;
+  }
+
+  return true;
+}
+
 export function validateReference(type) {
   return (ref) => {
     isStringNonEmpty(ref);