From 81eef212a1e8abaea3780fc0dec9922005c21188 Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Tue, 30 Nov 2021 15:14:00 +0100
Subject: [PATCH] common: add combineURLs() helper

This combines URLs similar to an URL join, but assumes the
base URL is the root path instead of the host.

This is useful for combining API paths with API server entry points.
---
 packages/common/index.js     |  1 +
 packages/common/src/utils.js | 17 +++++++++++++++++
 packages/common/test/unit.js | 15 +++++++++++++++
 3 files changed, 33 insertions(+)
 create mode 100644 packages/common/src/utils.js

diff --git a/packages/common/index.js b/packages/common/index.js
index 1ef16d4c..825ec149 100644
--- a/packages/common/index.js
+++ b/packages/common/index.js
@@ -16,4 +16,5 @@ export {Spinner};
 export {InlineNotification};
 export {Translated};
 export * from './src/logger.js';
+export * from './src/utils.js';
 export {AdapterLitElement};
diff --git a/packages/common/src/utils.js b/packages/common/src/utils.js
new file mode 100644
index 00000000..a3db6d6a
--- /dev/null
+++ b/packages/common/src/utils.js
@@ -0,0 +1,17 @@
+/**
+ * Appends the second relative or absolute URL by treating
+ * the base URL as the root path. Unlike normal URL join which
+ * treats the host as root path.
+ * 
+ * http://example.com/foo + bar -> http://example.com/foo/bar
+ * http://example.com/foo/ + /bar -> http://example.com/foo/bar
+ *
+ * @param {string} baseURL The bas URL
+ * @param {string} addedURL The URL to append ot the baseURL
+ */
+export const combineURLs = (baseURL, addedURL) => {
+    if(!baseURL.endsWith('/')) {
+        baseURL += '/';
+    }
+    return new URL(addedURL.replace(/^\/+/, ''), baseURL).href;
+};
\ No newline at end of file
diff --git a/packages/common/test/unit.js b/packages/common/test/unit.js
index e5379404..c72b6345 100644
--- a/packages/common/test/unit.js
+++ b/packages/common/test/unit.js
@@ -1,6 +1,7 @@
 import {expect, assert} from '@esm-bundle/chai';
 import * as utils from '../utils';
 import * as styles from '../styles';
+import {combineURLs} from '../';
 import '../jsonld.js';
 
 suite('utils', () => {
@@ -44,4 +45,18 @@ suite('utils', () => {
     test('getThemeCSS', () => {
         styles.getThemeCSS();
     });
+
+    test('combineURLs', () => {
+        assert.equal(combineURLs('http://example.org/foo', 'bar'), "http://example.org/foo/bar");
+        assert.equal(combineURLs('http://example.org/foo', '/bar'), "http://example.org/foo/bar");
+        assert.equal(combineURLs('http://example.org/foo/', '/bar/'), "http://example.org/foo/bar/");
+        assert.equal(combineURLs('http://example.org', '/bar'), "http://example.org/bar");
+        assert.equal(combineURLs('http://example.org', 'bar/'), "http://example.org/bar/");
+        assert.equal(combineURLs('http://example.org', ''), "http://example.org/");
+        assert.equal(combineURLs('http://example.org/bla', ''), "http://example.org/bla/");
+        assert.equal(combineURLs('http://example.org/bla/', ''), "http://example.org/bla/");
+        assert.equal(combineURLs('http://example.org', 'http://other.com'), "http://other.com/");
+        assert.equal(combineURLs('http://example.org', 'http://other.com/test'), "http://other.com/test");
+        assert.equal(combineURLs('http://example.org', 'http://other.com/test/'), "http://other.com/test/");
+    });
 });
-- 
GitLab