diff --git a/package-lock.json b/package-lock.json
index da7992bfa..a58d03c4b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -131,7 +131,7 @@
},
"engines": {
"node": "^18",
- "npm": "8.*"
+ "npm": "9.*"
}
},
"node_modules/@adobe/css-tools": {
diff --git a/src/components/Breadcrumbs/BreadcrumbContainer.js b/src/components/Breadcrumbs/BreadcrumbContainer.js
index e304337a9..68e67936e 100644
--- a/src/components/Breadcrumbs/BreadcrumbContainer.js
+++ b/src/components/Breadcrumbs/BreadcrumbContainer.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import { reportAnalytics } from '../../utils/report-analytics';
import { theme } from '../../theme/docsTheme';
+import { getFullBreadcrumbPath } from '../../utils/get-complete-breadcrumb-data';
import IndividualBreadcrumb from './IndividualBreadcrumb';
import CollapsedBreadcrumbs from './CollapsedBreadcrumbs';
@@ -67,7 +68,7 @@ const BreadcrumbContainer = ({ breadcrumbs }) => {
setIsExcessivelyTruncated={collapseBreadcrumbs}
onClick={() =>
reportAnalytics('BreadcrumbClick', {
- breadcrumbClicked: crumb.url,
+ breadcrumbClicked: getFullBreadcrumbPath(crumb.path, true),
})
}
>
@@ -81,7 +82,7 @@ const BreadcrumbContainer = ({ breadcrumbs }) => {
const crumbObjectShape = {
title: PropTypes.string.isRequired,
- url: PropTypes.string.isRequired,
+ path: PropTypes.string.isRequired,
};
BreadcrumbContainer.propTypes = {
diff --git a/src/components/Breadcrumbs/CollapsedBreadcrumbs.js b/src/components/Breadcrumbs/CollapsedBreadcrumbs.js
index 509337031..7217a28ff 100644
--- a/src/components/Breadcrumbs/CollapsedBreadcrumbs.js
+++ b/src/components/Breadcrumbs/CollapsedBreadcrumbs.js
@@ -2,10 +2,27 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Menu, MenuItem } from '@leafygreen-ui/menu';
import IconButton from '@leafygreen-ui/icon-button';
+import { withPrefix } from 'gatsby';
+import { useLocation } from '@gatsbyjs/reach-router';
import Icon from '@leafygreen-ui/icon';
import { formatText } from '../../utils/format-text';
+import { isGatsbyPreview } from '../../utils/is-gatsby-preview';
+import { getGatsbyPreviewLink } from '../../utils/get-gatsby-preview-link';
const CollapsedBreadcrumbs = ({ crumbs }) => {
+ const location = useLocation();
+
+ const menuItems = crumbs.map((crumb, index) => {
+ let to = withPrefix(crumb.path);
+ if (isGatsbyPreview()) to = getGatsbyPreviewLink(to, location);
+
+ return (
+
+ );
+ });
+
return (
);
@@ -29,7 +42,7 @@ const CollapsedBreadcrumbs = ({ crumbs }) => {
const crumbObjectShape = {
title: PropTypes.string.isRequired,
- url: PropTypes.string.isRequired,
+ path: PropTypes.string.isRequired,
};
CollapsedBreadcrumbs.propTypes = {
diff --git a/src/components/Breadcrumbs/IndividualBreadcrumb.js b/src/components/Breadcrumbs/IndividualBreadcrumb.js
index 9a741b396..b1e272545 100644
--- a/src/components/Breadcrumbs/IndividualBreadcrumb.js
+++ b/src/components/Breadcrumbs/IndividualBreadcrumb.js
@@ -9,6 +9,7 @@ import { theme } from '../../theme/docsTheme';
const linkStyling = LeafyCss`
font-size: ${theme.fontSize.small};
vertical-align: middle;
+ line-height: unset;
:hover,
:focus {
@@ -82,7 +83,7 @@ const IndividualBreadcrumb = ({ crumb, setIsExcessivelyTruncated, onClick }) =>
let result = (
21 ? ellipsisStyling : '')} ref={measuredRef}>
-
+
{formatText(crumb.title)}
@@ -109,7 +110,7 @@ const IndividualBreadcrumb = ({ crumb, setIsExcessivelyTruncated, onClick }) =>
const crumbObjectShape = {
title: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.arrayOf(PropTypes.object)]),
- url: PropTypes.string.isRequired,
+ path: PropTypes.string.isRequired,
};
IndividualBreadcrumb.propTypes = {
diff --git a/src/components/Link.js b/src/components/Link.js
index 7d64a24c7..0ddab664b 100644
--- a/src/components/Link.js
+++ b/src/components/Link.js
@@ -10,6 +10,7 @@ import { isRelativeUrl } from '../utils/is-relative-url';
import { joinClassNames } from '../utils/join-class-names';
import { isGatsbyPreview } from '../utils/is-gatsby-preview';
import { validateHTMAttributes } from '../utils/validate-element-attributes';
+import { getGatsbyPreviewLink } from '../utils/get-gatsby-preview-link';
/*
* Note: This component is not suitable for internal page navigation:
@@ -86,19 +87,7 @@ const Link = ({
// Ensure trailing slash
to = to.replace(/\/?(\?|#|$)/, '/$1');
- if (isGatsbyPreview()) {
- // If we're in preview mode, we build the pages of each project and branch of the site within
- // its own namespace so each author can preview their own pages e.g.
- // /project1/branch1/doc-path
- // /project2/branch2/doc-path
- //
- // So to navigate with the namespaced site, we add to each link the current project and branch
- // the user is browsing in.
- const projectAndBranchPrefix = `/` + location.pathname.split(`/`).slice(1, 3).join(`/`);
- if (!to.startsWith(projectAndBranchPrefix)) {
- to = projectAndBranchPrefix + to;
- }
- }
+ if (isGatsbyPreview()) to = getGatsbyPreviewLink(to, location);
return (
- breadcrumbs.map(({ url, title }, index) => ({
- '@type': 'ListItem',
- position: index + 1,
- name: title,
- item: assertTrailingSlash(url),
- }));
+ breadcrumbs.map(({ path, title }, index) => {
+ path = getFullBreadcrumbPath(path, true);
+
+ return {
+ '@type': 'ListItem',
+ position: index + 1,
+ name: title,
+ item: path,
+ };
+ });
const BreadcrumbSchema = ({ slug }) => {
const { parentPaths, title: siteTitle } = useSnootyMetadata();
diff --git a/src/utils/get-complete-breadcrumb-data.js b/src/utils/get-complete-breadcrumb-data.js
index 8b107fb1e..7b5131ba9 100644
--- a/src/utils/get-complete-breadcrumb-data.js
+++ b/src/utils/get-complete-breadcrumb-data.js
@@ -1,7 +1,9 @@
+import { withPrefix } from 'gatsby';
import { baseUrl } from './base-url';
import { assertTrailingSlash } from './assert-trailing-slash';
import { removeLeadingSlash } from './remove-leading-slash';
import { assertLeadingSlash } from './assert-leading-slash';
+import { isRelativeUrl } from './is-relative-url';
const nodesToString = (titleNodes) => {
if (typeof titleNodes === 'string') {
@@ -23,15 +25,25 @@ const nodesToString = (titleNodes) => {
.join('');
};
+export const getFullBreadcrumbPath = (path, needsPrefix) => {
+ if (needsPrefix) {
+ path = withPrefix(path);
+ }
+ if (isRelativeUrl(path)) {
+ path = baseUrl() + removeLeadingSlash(path);
+ }
+ return assertTrailingSlash(path);
+};
+
export const getCompleteBreadcrumbData = ({ siteTitle, slug, queriedCrumbs, parentPaths }) => {
//get intermediate breadcrumbs
const intermediateCrumbs = (queriedCrumbs?.breadcrumbs ?? []).map((crumb) => {
- return { ...crumb, url: assertTrailingSlash(baseUrl() + removeLeadingSlash(crumb.url)) };
+ return { ...crumb, path: getFullBreadcrumbPath(crumb.path, false) };
});
const homeCrumb = {
title: 'Docs Home',
- url: baseUrl(),
+ path: baseUrl(),
};
// If site is the property homepage, leave the propertyCrumb blank
@@ -39,7 +51,7 @@ export const getCompleteBreadcrumbData = ({ siteTitle, slug, queriedCrumbs, pare
if (slug !== '/') {
propertyCrumb = {
title: nodesToString(siteTitle),
- url: '/',
+ path: '/',
};
}
@@ -49,7 +61,7 @@ export const getCompleteBreadcrumbData = ({ siteTitle, slug, queriedCrumbs, pare
return {
...crumb,
title: nodesToString(crumb.title),
- url: assertLeadingSlash(crumb.path),
+ path: assertLeadingSlash(crumb.path),
};
});
diff --git a/src/utils/get-gatsby-preview-link.js b/src/utils/get-gatsby-preview-link.js
new file mode 100644
index 000000000..e1e2f8bdf
--- /dev/null
+++ b/src/utils/get-gatsby-preview-link.js
@@ -0,0 +1,18 @@
+/**
+ * If we're in preview mode, we build the pages of each project and branch of the site within
+ * its own namespace so each author can preview their own pages e.g.
+ * /project1/branch1/doc-path
+ * /project2/branch2/doc-path
+ *
+ * So to navigate with the namespaced site, we add to each link the current project and branch
+ * the user is browsing in.
+ */
+const getGatsbyPreviewLink = (to, location) => {
+ const projectAndBranchPrefix = `/` + location.pathname.split(`/`).slice(1, 3).join(`/`);
+ if (!to.startsWith(projectAndBranchPrefix)) {
+ to = projectAndBranchPrefix + to;
+ }
+ return to;
+};
+
+module.exports = { getGatsbyPreviewLink };
diff --git a/tests/unit/BreadcrumbContainer.test.js b/tests/unit/BreadcrumbContainer.test.js
index c0b53972f..f9a746656 100644
--- a/tests/unit/BreadcrumbContainer.test.js
+++ b/tests/unit/BreadcrumbContainer.test.js
@@ -13,30 +13,30 @@ jest.mock(`../../src/utils/use-snooty-metadata`, () => jest.fn());
const mockIntermediateCrumbs = {
title: 'MongoDB Atlas',
- url: 'https://www.mongodb.com/docs/atlas/',
+ path: 'https://www.mongodb.com/docs/atlas/',
};
const mockPropertyCrumb = {
title: 'MongoDB Atlas Device SDKs',
- url: 'https://www.mongodb.com/docs/atlas/device-sdks/',
+ path: 'https://www.mongodb.com/docs/atlas/device-sdks/',
};
describe('BreadcrumbContainer', () => {
//home breadcrumb
const mockHomeCrumb = {
title: 'Docs Home',
- url: 'https://www.mongodb.com/docs/',
+ path: 'https://www.mongodb.com/docs/',
};
const mockParents = mockData;
it('renders a driver site correctly with intermediate breadcrumb and with project parents', () => {
const breadcrumbs = [
- { title: 'Docs Home', url: 'https://www.mongodb.com/docs/' },
- { title: 'Languages', url: 'https://www.mongodb.com/docs/languages' },
- { title: 'C#/.NET', url: 'https://www.mongodb.com/docs/languages/csharp/' },
- { title: 'C#/.NET Driver', url: 'https://www.mongodb.com/docs/languages/csharp/csharp-driver/' },
- { title: 'Usage Examples', url: 'https://www.mongodb.com/docs/languages/csharp/csharp-driver/usage-examples/' },
+ { title: 'Docs Home', path: 'https://www.mongodb.com/docs/' },
+ { title: 'Languages', path: 'https://www.mongodb.com/docs/languages' },
+ { title: 'C#/.NET', path: 'https://www.mongodb.com/docs/languages/csharp/' },
+ { title: 'C#/.NET Driver', path: 'https://www.mongodb.com/docs/languages/csharp/csharp-driver/' },
+ { title: 'Usage Examples', path: 'https://www.mongodb.com/docs/languages/csharp/csharp-driver/usage-examples/' },
];
const tree = mountBreadcrumbContainer(breadcrumbs);
diff --git a/tests/unit/Breadcrumbs.test.js b/tests/unit/Breadcrumbs.test.js
index 68cb2ee23..dc8357909 100644
--- a/tests/unit/Breadcrumbs.test.js
+++ b/tests/unit/Breadcrumbs.test.js
@@ -18,7 +18,7 @@ beforeAll(() => {
const mockIntermediateCrumbs = [
{
title: 'MongoDB Atlas',
- url: '/atlas',
+ path: '/atlas',
},
];
const useStaticQuery = jest.spyOn(Gatsby, 'useStaticQuery');
diff --git a/tests/unit/__snapshots__/BreadcrumbContainer.test.js.snap b/tests/unit/__snapshots__/BreadcrumbContainer.test.js.snap
index 193e86dca..35c866232 100644
--- a/tests/unit/__snapshots__/BreadcrumbContainer.test.js.snap
+++ b/tests/unit/__snapshots__/BreadcrumbContainer.test.js.snap
@@ -62,6 +62,7 @@ exports[`BreadcrumbContainer renders a driver site correctly with intermediate b
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-3:hover,
@@ -252,6 +253,7 @@ exports[`BreadcrumbContainer renders correctly as a docs homepage 1`] = `
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-3:hover,
@@ -308,6 +310,54 @@ exports[`BreadcrumbContainer renders correctly as a docs homepage 1`] = `
}
}
+.emotion-11 {
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ cursor: pointer;
+ position: relative;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ text-decoration-color: transparent;
+ line-height: 13px;
+ color: #016BF8;
+}
+
+.emotion-11>code {
+ color: #016BF8;
+}
+
+.emotion-11:focus,
+.emotion-11:hover {
+ text-decoration-line: underline;
+ -webkit-transition: text-decoration 150ms ease-in-out;
+ transition: text-decoration 150ms ease-in-out;
+ text-underline-offset: 4px;
+ text-decoration-thickness: 2px;
+}
+
+.emotion-11:focus {
+ text-decoration-color: #016BF8;
+ outline: none;
+}
+
+.emotion-11:hover {
+ text-decoration-color: #E8EDEB;
+}
+
+.emotion-12 {
+ font-size: 13px;
+ vertical-align: middle;
+ line-height: unset;
+}
+
+.emotion-12:hover,
+.emotion-12:focus {
+ -webkit-text-decoration: underline;
+ text-decoration: underline;
+}
+
-
- Application Services - C++ SDK
-
+ Application Services - C++ SDK
@@ -442,6 +488,7 @@ exports[`BreadcrumbContainer renders correctly with intermediate breadcrumb, no
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-3:hover,
@@ -616,6 +663,7 @@ exports[`BreadcrumbContainer renders correctly with no intermediate breadcrumbs,
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-3:hover,
@@ -672,6 +720,54 @@ exports[`BreadcrumbContainer renders correctly with no intermediate breadcrumbs,
}
}
+.emotion-11 {
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ cursor: pointer;
+ position: relative;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ text-decoration-color: transparent;
+ line-height: 13px;
+ color: #016BF8;
+}
+
+.emotion-11>code {
+ color: #016BF8;
+}
+
+.emotion-11:focus,
+.emotion-11:hover {
+ text-decoration-line: underline;
+ -webkit-transition: text-decoration 150ms ease-in-out;
+ transition: text-decoration 150ms ease-in-out;
+ text-underline-offset: 4px;
+ text-decoration-thickness: 2px;
+}
+
+.emotion-11:focus {
+ text-decoration-color: #016BF8;
+ outline: none;
+}
+
+.emotion-11:hover {
+ text-decoration-color: #E8EDEB;
+}
+
+.emotion-12 {
+ font-size: 13px;
+ vertical-align: middle;
+ line-height: unset;
+}
+
+.emotion-12:hover,
+.emotion-12:focus {
+ -webkit-text-decoration: underline;
+ text-decoration: underline;
+}
+
-
- Application Services - C++ SDK
-
+ Application Services - C++ SDK
diff --git a/tests/unit/__snapshots__/Breadcrumbs.test.js.snap b/tests/unit/__snapshots__/Breadcrumbs.test.js.snap
index 37d958154..74b6114c5 100644
--- a/tests/unit/__snapshots__/Breadcrumbs.test.js.snap
+++ b/tests/unit/__snapshots__/Breadcrumbs.test.js.snap
@@ -70,6 +70,7 @@ exports[`renders correctly as a homepage 1`] = `
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-4:hover,
@@ -218,6 +219,7 @@ exports[`renders correctly with siteTitle 1`] = `
display: inline;
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-4:hover,
@@ -293,6 +295,7 @@ exports[`renders correctly with siteTitle 1`] = `
.emotion-13 {
font-size: 13px;
vertical-align: middle;
+ line-height: unset;
}
.emotion-13:hover,