Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🗂 Support url slugs with multiple path segments #489

Merged
merged 8 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/early-plums-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@myst-theme/common': patch
'@myst-theme/article': patch
'@myst-theme/site': patch
'@myst-theme/book': patch
---

Support url slugs with multiple path segments
88 changes: 44 additions & 44 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
"build": "npm-run-all -l clean -p build:esm"
},
"dependencies": {
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-spec-ext": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-spec-ext": "^1.7.3",
"nbtx": "^0.2.3",
"unist-util-select": "^4.0.3"
}
Expand Down
4 changes: 3 additions & 1 deletion packages/common/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { SiteManifest } from 'myst-config';
import { selectAll } from 'unist-util-select';
import type { Image as ImageSpec, Link as LinkSpec } from 'myst-spec';
import type { FooterLinks, Heading, NavigationLink, PageLoader } from './types.js';
import { slugToUrl } from 'myst-common';

type Image = ImageSpec & { urlOptimized?: string };
type Link = LinkSpec & { static?: boolean };
Expand Down Expand Up @@ -40,9 +41,10 @@ export function getProjectHeadings(
},
...project.pages.map((p) => {
if (!('slug' in p)) return p;
const slug = slugToUrl(p.slug);
return {
...p,
path: projectSlug && project.slug ? `/${project.slug}/${p.slug}` : `/${p.slug}`,
path: projectSlug && project.slug ? `/${project.slug}/${slug}` : `/${slug}`,
};
}),
];
Expand Down
8 changes: 4 additions & 4 deletions packages/jupyter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
"buffer": "^6.0.3",
"classnames": "^2.5.1",
"jupyterlab-plotly": "^5.24.0",
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-frontmatter": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-frontmatter": "^1.7.3",
"myst-spec": "^0.0.5",
"myst-spec-ext": "^1.7.2",
"myst-spec-ext": "^1.7.3",
"myst-to-react": "^0.13.2",
"nanoid": "^4.0.2",
"nbtx": "^0.2.3",
Expand Down
8 changes: 4 additions & 4 deletions packages/myst-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@
"@heroicons/react": "^2.0.18",
"classnames": "^2.3.2",
"js-yaml": "^4.1.0",
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-directives": "^1.5.7",
"myst-ext-card": "^1.0.9",
"myst-ext-exercise": "^1.0.8",
"myst-ext-grid": "^1.0.8",
"myst-ext-proof": "^1.0.11",
"myst-ext-tabs": "^1.0.8",
"myst-frontmatter": "^1.7.2",
"myst-frontmatter": "^1.7.3",
"myst-parser": "^1.5.7",
"myst-spec": "^0.0.5",
"myst-to-docx": "^1.0.12",
"myst-to-html": "^1.5.7",
"myst-to-jats": "^1.0.30",
"myst-to-react": "^0.13.2",
"myst-to-tex": "^1.0.38",
"myst-to-typst": "^0.0.24",
"myst-to-typst": "^0.0.25",
"myst-transforms": "^1.3.26",
"unified": "^10.1.2",
"unist-util-remove": "^4.0.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/myst-to-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"@radix-ui/react-hover-card": "^1.0.6",
"buffer": "^6.0.3",
"classnames": "^2.3.2",
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-spec": "^0.0.5",
"nanoid": "^4.0.2",
"react-syntax-highlighter": "15.5.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/providers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-frontmatter": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-frontmatter": "^1.7.3",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
Expand Down
6 changes: 3 additions & 3 deletions packages/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
"@radix-ui/react-visually-hidden": "^1.1.0",
"classnames": "^2.3.2",
"lodash.throttle": "^4.1.1",
"myst-common": "^1.7.2",
"myst-config": "^1.7.2",
"myst-common": "^1.7.3",
"myst-config": "^1.7.3",
"myst-demo": "^0.13.2",
"myst-spec-ext": "^1.7.2",
"myst-spec-ext": "^1.7.3",
"myst-to-react": "^0.13.2",
"nbtx": "^0.2.3",
"node-cache": "^5.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/site/src/components/Navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const ConfigurablePrimaryNavigation = ({

if (children)
console.warn(
`Including children in Navigation can break keyboard accessbility and is deprecated. Please move children to the page component.`,
`Including children in Navigation can break keyboard accessibility and is deprecated. Please move children to the page component.`,
);

// the logic on the following line looks wrong, this will return `null` or `<></>`
Expand Down
10 changes: 8 additions & 2 deletions packages/site/src/components/Navigation/TableOfContentsItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,16 @@ function nestToc(toc: Heading[]): NestedHeading[] {
return items;
}

function pathnameMatchesHeading(pathname: string, heading: Heading, baseurl?: string) {
const headingPath = withBaseurl(heading.path, baseurl);
if (pathname && headingPath === `${pathname}/index`) return true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few small changes in here that allow index pages to be accessible at the folder-path url.

For example, the file folder1/folder2/index.md is available at /folder1/folder2 (and /folder1/folder2/index redirects back to /folder1/folder2).

return headingPath === pathname;
}

function childrenOpen(headings: NestedHeading[], pathname: string, baseurl?: string): string[] {
return headings
.map((heading) => {
if (withBaseurl(heading.path, baseurl) === pathname) return [heading.id];
if (pathnameMatchesHeading(pathname, heading, baseurl)) return [heading.id];
const open = childrenOpen(heading.children, pathname, baseurl);
if (open.length === 0) return [];
return [heading.id, ...open];
Expand Down Expand Up @@ -110,7 +116,7 @@ const NestedToc = ({ heading }: { heading: NestedHeading }) => {
useEffect(() => {
if (nav.state === 'idle') setOpen(startOpen);
}, [nav.state]);
const exact = pathname === withBaseurl(heading.path, baseurl);
const exact = pathnameMatchesHeading(pathname, heading, baseurl);
if (!heading.children || heading.children.length === 0) {
return (
<LinkItem
Expand Down
3 changes: 2 additions & 1 deletion packages/site/src/seo/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { slugToUrl } from 'myst-common';
import type { SiteManifest } from 'myst-config';

type ManifestProjectItem = Required<SiteManifest>['projects'][0]['pages'][0];
Expand Down Expand Up @@ -148,7 +149,7 @@ export function getSiteSlugs(
const projectSlug = project.slug ? `/${project.slug}` : '';
const pages = project.pages
.filter((page): page is ManifestProjectItem => 'slug' in page)
.map((page) => `${baseurl}${projectSlug}/${page.slug}`);
.map((page) => `${baseurl}${projectSlug}/${slugToUrl(page.slug)}`);
if (opts?.excludeIndex) return [...pages];
return [
opts?.explicitIndex
Expand Down
11 changes: 6 additions & 5 deletions themes/article/app/routes/$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ export const meta: V2_MetaFunction<typeof loader> = ({ data, matches, location }
export const links: LinksFunction = () => [KatexCSS];

export const loader: LoaderFunction = async ({ params, request }) => {
const [first, second] = new URL(request.url).pathname.slice(1).split('/');
const projectName = second ? first : undefined;
const slug = second || first;
const [first, ...rest] = new URL(request.url).pathname.slice(1).split('/');
const config = await getConfig();
const project = getProject(config, projectName ?? slug);
const project = getProject(config, first);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I learned about some strangeness in the article theme while making these changes: the article theme does not work correctly with project slugs. I think it is ok if project slugs just do not work with article theme, but we should make that more clear. For example, here we should not even try to load the project based on the URL; it should always just be the default single project.

However, for this PR, I tried as best as I could to keep parity with the old functionality.

const projectName = project?.slug === first ? first : undefined;
const slugParts = projectName ? rest : [first, ...rest];
const slug = slugParts.length ? slugParts.join('.') : undefined;
const flat = isFlatSite(config);
const page = await getPage(request, {
project: flat ? projectName : projectName ?? slug,
project: flat ? projectName : (projectName ?? slug),
slug: flat ? slug : projectName ? slug : undefined,
redirect: process.env.MODE === 'static' ? false : true,
});
Expand Down
Loading
Loading