From ef4fb0a5277ee99bd0f1747b77e733ef7f02460d Mon Sep 17 00:00:00 2001
From: flu0r1ne <flu0r1ne@flu0r1ne.net>
Date: Wed, 6 Sep 2023 19:53:23 -0500
Subject: Make BreadCrumbs domain agnostic

---
 components/BreadCrumbs/breadcrumbs.module.scss | 15 +++++++
 components/BreadCrumbs/index.tsx               | 56 ++++++++++++++++++++++++
 components/Breadcrumbs/breadcrumbs.module.scss | 15 -------
 components/Breadcrumbs/index.tsx               | 56 ------------------------
 components/PathCrumbs/index.tsx                | 60 ++++++++++++++++++++++++++
 5 files changed, 131 insertions(+), 71 deletions(-)
 create mode 100644 components/BreadCrumbs/breadcrumbs.module.scss
 create mode 100644 components/BreadCrumbs/index.tsx
 delete mode 100644 components/Breadcrumbs/breadcrumbs.module.scss
 delete mode 100644 components/Breadcrumbs/index.tsx
 create mode 100644 components/PathCrumbs/index.tsx

(limited to 'components')

diff --git a/components/BreadCrumbs/breadcrumbs.module.scss b/components/BreadCrumbs/breadcrumbs.module.scss
new file mode 100644
index 0000000..6facea4
--- /dev/null
+++ b/components/BreadCrumbs/breadcrumbs.module.scss
@@ -0,0 +1,15 @@
+.crumb {
+    font-size: 1.10rem;
+}
+
+.divider {
+    font-size: 1.0rem;
+}
+
+.crumb {
+    align-content: center;
+}
+
+.divider {
+    margin: 0 0.3rem;
+}
diff --git a/components/BreadCrumbs/index.tsx b/components/BreadCrumbs/index.tsx
new file mode 100644
index 0000000..693a9d0
--- /dev/null
+++ b/components/BreadCrumbs/index.tsx
@@ -0,0 +1,56 @@
+import React, { Children, FC } from "react";
+import Link from "next/link";
+import styles from './breadcrumbs.module.scss';
+import clsx from 'clsx';
+
+export type BreadCrumbsProps = {
+    className?: string;
+    style?: object;
+    children: React.ReactNode;
+};
+
+const BreadCrumbs : FC<BreadCrumbsProps> = ({children, className, ...props}) => (
+    <span className={clsx(styles.breadcrumbs, className)} {...props}>
+        {Children.map(children, (child, index) => {
+            return (
+                <>
+                    {
+                        index !== 0 ? (
+                            <span className={styles.divider}>/</span>
+                        ) : undefined
+                    }
+                    {child}
+                </>
+            );
+        })}
+    </span>
+);
+
+export type CrumbProps = {
+  children: React.ReactNode;
+};
+
+const Crumb : FC<CrumbProps> = ({children, ...props}) => (
+    <span className={styles.crumb} {...props}>
+        {children}
+    </span>
+);
+
+export type LinkCrumbProps = {
+    href: string;
+    children: React.ReactNode;
+}
+
+const LinkCrumb : FC<LinkCrumbProps> = ({children, href, ...props}) => (
+    <Crumb>
+        <Link href={href}>
+            {children}
+        </Link>
+    </Crumb>
+);
+
+export {
+    Crumb,
+    BreadCrumbs,
+    LinkCrumb
+};
diff --git a/components/Breadcrumbs/breadcrumbs.module.scss b/components/Breadcrumbs/breadcrumbs.module.scss
deleted file mode 100644
index 6facea4..0000000
--- a/components/Breadcrumbs/breadcrumbs.module.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-.crumb {
-    font-size: 1.10rem;
-}
-
-.divider {
-    font-size: 1.0rem;
-}
-
-.crumb {
-    align-content: center;
-}
-
-.divider {
-    margin: 0 0.3rem;
-}
diff --git a/components/Breadcrumbs/index.tsx b/components/Breadcrumbs/index.tsx
deleted file mode 100644
index d773b33..0000000
--- a/components/Breadcrumbs/index.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import React, { Children, FC } from "react";
-import Link from "next/link";
-import styles from './breadcrumbs.module.scss';
-import clsx from 'clsx';
-
-export type BreadcrumbsProps = {
-    className?: string;
-    style?: object;
-    children: React.ReactNode;
-};
-
-const Breadcrumbs : FC<BreadcrumbsProps> = ({children, className, ...props}) => (
-    <span className={clsx(styles.breadcrumbs, className)} {...props}>
-        {Children.map(children, (child, index) => {
-            return (
-                <>
-                    {
-                        index !== 0 ? (
-                            <span className={styles.divider}>/</span>
-                        ) : undefined
-                    }
-                    {child}
-                </>
-            );
-        })}
-    </span>
-);
-
-export type CrumbProps = {
-  children: React.ReactNode;
-};
-
-const Crumb : FC<CrumbProps> = ({children, ...props}) => (
-    <span className={styles.crumb} {...props}>
-        {children}
-    </span>
-);
-
-export type LinkCrumbProps = {
-    href: string;
-    children: React.ReactNode;
-}
-
-const LinkCrumb : FC<LinkCrumbProps> = ({children, href, ...props}) => (
-    <Crumb>
-        <Link href={href}>
-            {children}
-        </Link>
-    </Crumb>
-);
-
-export {
-    Crumb,
-    Breadcrumbs,
-    LinkCrumb
-};
diff --git a/components/PathCrumbs/index.tsx b/components/PathCrumbs/index.tsx
new file mode 100644
index 0000000..1c87344
--- /dev/null
+++ b/components/PathCrumbs/index.tsx
@@ -0,0 +1,60 @@
+import React, { FC } from 'react';
+
+import assert from '../../utils/assert';
+import { DISPLAY_DOMAIN } from '../../utils/env';
+
+const urlPathComponents = (path : string): string[] => {
+  assert(path.length > 0, "empty path");
+
+  let canonicalizedPath = path[path.length - 1] === '/' ?
+    path.substr(0, path.length - 1) : path;
+
+  if(canonicalizedPath.length === 0) {
+    return [];
+  } else {
+    canonicalizedPath = canonicalizedPath[0] == '/' ?
+      path.substr(1, path.length - 1) : path;
+  }
+
+  return canonicalizedPath.split('/')
+}
+
+const urlPathComponentsToFullPath = (urlPathComponents : string[]): string[] => {
+  const fullPaths = new Array<string>(urlPathComponents.length + 1);
+
+  fullPaths[0] = '';
+
+  for(let i = 0; i < urlPathComponents.length; i++) {
+    fullPaths[i + 1] = fullPaths[i] + '/' + urlPathComponents[i];
+  }
+
+  fullPaths[0] = '/';
+
+  return fullPaths;
+};
+
+export type PathCrumbsProps = {
+  path: string
+};
+
+import { BreadCrumbs , LinkCrumb } from '../../components/BreadCrumbs';
+
+const PathCrumbs: FC<PathCrumbsProps> = ({ path }) => {
+
+  const pathComponents = urlPathComponents(path);
+  const fullPaths = urlPathComponentsToFullPath(pathComponents);
+
+  const linksComponents = fullPaths.map((fullPath, i) => (
+    <LinkCrumb href={fullPath} key={fullPath}>
+      { i === 0 ? DISPLAY_DOMAIN : pathComponents[i - 1] }
+    </LinkCrumb>
+  ));
+
+  return (
+    <BreadCrumbs>
+      {linksComponents}
+    </BreadCrumbs>
+  );
+};
+
+export default PathCrumbs;
-- 
cgit v1.2.3