@myst-theme/site 0.1.38 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -7
- package/src/components/FooterLinksBlock.tsx +3 -3
- package/src/components/Navigation/TableOfContents.tsx +13 -8
- package/src/components/Navigation/TopNav.tsx +9 -2
- package/src/loaders/utils.ts +4 -3
- package/src/pages/Error404.tsx +8 -0
- package/src/pages/Root.tsx +37 -31
- package/src/pages/index.ts +2 -2
- package/src/seo/sitemap.ts +4 -3
- package/src/types.ts +3 -0
- package/src/pages/ErrorSiteNotFound.tsx +0 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myst-theme/site",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"main": "./src/index.ts",
|
|
5
5
|
"types": "./src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -16,16 +16,16 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@headlessui/react": "^1.7.13",
|
|
18
18
|
"@heroicons/react": "^2.0.14",
|
|
19
|
-
"@myst-theme/diagrams": "^0.1
|
|
20
|
-
"@myst-theme/frontmatter": "^0.1
|
|
21
|
-
"@myst-theme/jupyter": "^0.1
|
|
22
|
-
"@myst-theme/providers": "^0.1
|
|
19
|
+
"@myst-theme/diagrams": "^0.2.1",
|
|
20
|
+
"@myst-theme/frontmatter": "^0.2.1",
|
|
21
|
+
"@myst-theme/jupyter": "^0.2.1",
|
|
22
|
+
"@myst-theme/providers": "^0.2.1",
|
|
23
23
|
"classnames": "^2.3.2",
|
|
24
24
|
"lodash.throttle": "^4.1.1",
|
|
25
25
|
"myst-common": "^0.0.16",
|
|
26
26
|
"myst-config": "^0.0.14",
|
|
27
|
-
"myst-demo": "^0.1
|
|
28
|
-
"myst-to-react": "^0.1
|
|
27
|
+
"myst-demo": "^0.2.1",
|
|
28
|
+
"myst-to-react": "^0.2.1",
|
|
29
29
|
"nbtx": "^0.2.3",
|
|
30
30
|
"node-cache": "^5.1.2",
|
|
31
31
|
"node-fetch": "^2.6.7",
|
|
@@ -2,16 +2,16 @@ import classNames from 'classnames';
|
|
|
2
2
|
import ArrowLeftIcon from '@heroicons/react/24/outline/ArrowLeftIcon';
|
|
3
3
|
import ArrowRightIcon from '@heroicons/react/24/outline/ArrowRightIcon';
|
|
4
4
|
import type { FooterLinks, NavigationLink } from '../types';
|
|
5
|
-
import { useLinkProvider,
|
|
5
|
+
import { useLinkProvider, useBaseurl, withBaseurl } from '@myst-theme/providers';
|
|
6
6
|
|
|
7
7
|
const FooterLink = ({ title, url, group, right }: NavigationLink & { right?: boolean }) => {
|
|
8
|
-
const
|
|
8
|
+
const baseurl = useBaseurl();
|
|
9
9
|
const Link = useLinkProvider();
|
|
10
10
|
return (
|
|
11
11
|
<Link
|
|
12
12
|
prefetch="intent"
|
|
13
13
|
className="group flex-1 p-4 block border font-normal hover:border-blue-600 dark:hover:border-blue-400 no-underline hover:text-blue-600 dark:hover:text-blue-400 text-gray-600 dark:text-gray-100 border-gray-200 dark:border-gray-500 rounded shadow-sm hover:shadow-lg dark:shadow-neutral-700"
|
|
14
|
-
to={
|
|
14
|
+
to={withBaseurl(url, baseurl)}
|
|
15
15
|
>
|
|
16
16
|
<div className="flex align-middle h-full">
|
|
17
17
|
{right && (
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import {
|
|
3
|
+
import { useLocation, useNavigation } from '@remix-run/react';
|
|
4
4
|
import type { SiteManifest } from 'myst-config';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useNavLinkProvider,
|
|
7
|
+
useNavOpen,
|
|
8
|
+
useSiteManifest,
|
|
9
|
+
useBaseurl,
|
|
10
|
+
withBaseurl,
|
|
11
|
+
} from '@myst-theme/providers';
|
|
6
12
|
import { getProjectHeadings } from '../../loaders';
|
|
7
13
|
import type { Heading } from '../../types';
|
|
8
14
|
|
|
@@ -26,8 +32,9 @@ const HeadingLink = ({
|
|
|
26
32
|
children: React.ReactNode;
|
|
27
33
|
}) => {
|
|
28
34
|
const { pathname } = useLocation();
|
|
35
|
+
const NavLink = useNavLinkProvider();
|
|
29
36
|
const exact = pathname === path;
|
|
30
|
-
const
|
|
37
|
+
const baseurl = useBaseurl();
|
|
31
38
|
const [, setOpen] = useNavOpen();
|
|
32
39
|
return (
|
|
33
40
|
<NavLink
|
|
@@ -44,7 +51,7 @@ const HeadingLink = ({
|
|
|
44
51
|
!isActive,
|
|
45
52
|
})
|
|
46
53
|
}
|
|
47
|
-
to={
|
|
54
|
+
to={withBaseurl(path, baseurl)}
|
|
48
55
|
suppressHydrationWarning // The pathname is not defined on the server always.
|
|
49
56
|
onClick={() => {
|
|
50
57
|
// Close the nav panel if it is open
|
|
@@ -141,10 +148,8 @@ export const TableOfContents = ({
|
|
|
141
148
|
const footerRef = useRef<HTMLDivElement>(null);
|
|
142
149
|
const [open] = useNavOpen();
|
|
143
150
|
const config = useSiteManifest();
|
|
144
|
-
const { folder, project } = useParams();
|
|
145
|
-
const resolvedProjectSlug = projectSlug || (folder ?? project);
|
|
146
151
|
if (!config) return null;
|
|
147
|
-
const headings = getProjectHeadings(config,
|
|
152
|
+
const headings = getProjectHeadings(config, projectSlug, {
|
|
148
153
|
addGroups: false,
|
|
149
154
|
});
|
|
150
155
|
useEffect(() => {
|
|
@@ -183,7 +188,7 @@ export const TableOfContents = ({
|
|
|
183
188
|
aria-label="Table of Contents"
|
|
184
189
|
className="flex-grow overflow-y-auto transition-opacity mt-6 pb-3 ml-3 xl:ml-0 mr-3"
|
|
185
190
|
>
|
|
186
|
-
<Headings folder={
|
|
191
|
+
<Headings folder={projectSlug} headings={headings} sections={config?.projects} />
|
|
187
192
|
</nav>
|
|
188
193
|
{footer && (
|
|
189
194
|
<div
|
|
@@ -7,7 +7,13 @@ import MenuIcon from '@heroicons/react/24/solid/Bars3Icon';
|
|
|
7
7
|
import ChevronDownIcon from '@heroicons/react/24/solid/ChevronDownIcon';
|
|
8
8
|
import type { SiteManifest, SiteNavItem } from 'myst-config';
|
|
9
9
|
import { ThemeButton } from './ThemeButton';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
useBaseurl,
|
|
12
|
+
useLinkProvider,
|
|
13
|
+
useNavOpen,
|
|
14
|
+
useSiteManifest,
|
|
15
|
+
withBaseurl,
|
|
16
|
+
} from '@myst-theme/providers';
|
|
11
17
|
import { LoadingBar } from './Loading';
|
|
12
18
|
|
|
13
19
|
export const DEFAULT_NAV_HEIGHT = 60;
|
|
@@ -178,11 +184,12 @@ function ActionMenu({ actions }: { actions?: SiteManifest['actions'] }) {
|
|
|
178
184
|
|
|
179
185
|
function HomeLink({ logo, logoText, name }: { logo?: string; logoText?: string; name?: string }) {
|
|
180
186
|
const Link = useLinkProvider();
|
|
187
|
+
const baseurl = useBaseurl();
|
|
181
188
|
const nothingSet = !logo && !logoText;
|
|
182
189
|
return (
|
|
183
190
|
<Link
|
|
184
191
|
className="flex items-center dark:text-white w-fit ml-3 md:ml-5 xl:ml-7"
|
|
185
|
-
to=
|
|
192
|
+
to={withBaseurl('/', baseurl)}
|
|
186
193
|
prefetch="intent"
|
|
187
194
|
>
|
|
188
195
|
{logo && (
|
package/src/loaders/utils.ts
CHANGED
|
@@ -16,7 +16,8 @@ export function getProject(
|
|
|
16
16
|
config?: SiteManifest,
|
|
17
17
|
projectSlug?: string,
|
|
18
18
|
): ManifestProject | undefined {
|
|
19
|
-
if (!
|
|
19
|
+
if (!config) return undefined;
|
|
20
|
+
if (!projectSlug) return config.projects?.[0];
|
|
20
21
|
const project = config.projects?.find((p) => p.slug === projectSlug);
|
|
21
22
|
return project;
|
|
22
23
|
}
|
|
@@ -32,12 +33,12 @@ export function getProjectHeadings(
|
|
|
32
33
|
{
|
|
33
34
|
title: project.title,
|
|
34
35
|
slug: project.index,
|
|
35
|
-
path: `/${project.slug}
|
|
36
|
+
path: project.slug ? `/${project.slug}` : '/',
|
|
36
37
|
level: 'index',
|
|
37
38
|
},
|
|
38
39
|
...project.pages.map((p) => {
|
|
39
40
|
if (!('slug' in p)) return p;
|
|
40
|
-
return { ...p, path: `/${project.slug}/${p.slug}` };
|
|
41
|
+
return { ...p, path: projectSlug ? `/${project.slug}/${p.slug}` : `/${p.slug}` };
|
|
41
42
|
}),
|
|
42
43
|
];
|
|
43
44
|
if (opts.addGroups) {
|
package/src/pages/Root.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SiteManifest } from 'myst-config';
|
|
2
2
|
import type { SiteLoader } from '../types';
|
|
3
|
-
import { SiteProvider, Theme, ThemeProvider } from '@myst-theme/providers';
|
|
3
|
+
import { BaseUrlProvider, SiteProvider, Theme, ThemeProvider } from '@myst-theme/providers';
|
|
4
4
|
import {
|
|
5
5
|
Links,
|
|
6
6
|
LiveReload,
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
Outlet,
|
|
9
9
|
Scripts,
|
|
10
10
|
ScrollRestoration,
|
|
11
|
-
useCatch,
|
|
12
11
|
useLoaderData,
|
|
13
|
-
Link
|
|
12
|
+
Link,
|
|
13
|
+
NavLink,
|
|
14
14
|
} from '@remix-run/react';
|
|
15
15
|
import { ContentReload, renderers } from '../components';
|
|
16
16
|
import { Analytics } from '../seo';
|
|
17
|
-
import {
|
|
17
|
+
import { Error404 } from './Error404';
|
|
18
18
|
import classNames from 'classnames';
|
|
19
19
|
import { ThebeCoreProvider } from 'thebe-react';
|
|
20
20
|
import { ConfiguredThebeServerProvider } from '@myst-theme/jupyter';
|
|
@@ -26,6 +26,8 @@ export function Document({
|
|
|
26
26
|
config,
|
|
27
27
|
title,
|
|
28
28
|
scrollTopClass = 'scroll-p-20',
|
|
29
|
+
staticBuild,
|
|
30
|
+
baseurl,
|
|
29
31
|
}: {
|
|
30
32
|
children: React.ReactNode;
|
|
31
33
|
scripts?: React.ReactNode;
|
|
@@ -33,7 +35,18 @@ export function Document({
|
|
|
33
35
|
config?: SiteManifest;
|
|
34
36
|
title?: string;
|
|
35
37
|
scrollTopClass?: string;
|
|
38
|
+
staticBuild?: boolean;
|
|
39
|
+
baseurl?: string;
|
|
36
40
|
}) {
|
|
41
|
+
const links = staticBuild
|
|
42
|
+
? {
|
|
43
|
+
Link: (props: any) => <Link {...{ ...props, reloadDocument: true }} />,
|
|
44
|
+
NavLink: (props: any) => <NavLink {...{ ...props, reloadDocument: true }} />,
|
|
45
|
+
}
|
|
46
|
+
: {
|
|
47
|
+
Link: Link as any,
|
|
48
|
+
NavLink: NavLink as any,
|
|
49
|
+
};
|
|
37
50
|
return (
|
|
38
51
|
<html lang="en" className={classNames(theme, scrollTopClass)}>
|
|
39
52
|
<head>
|
|
@@ -48,16 +61,18 @@ export function Document({
|
|
|
48
61
|
/>
|
|
49
62
|
</head>
|
|
50
63
|
<body className="m-0 transition-colors duration-500 bg-white dark:bg-stone-900">
|
|
51
|
-
<ThemeProvider theme={theme} renderers={renderers}
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
<ThemeProvider theme={theme} renderers={renderers} {...links}>
|
|
65
|
+
<BaseUrlProvider baseurl={baseurl}>
|
|
66
|
+
<ThebeCoreProvider>
|
|
67
|
+
<SiteProvider config={config}>
|
|
68
|
+
<ConfiguredThebeServerProvider>{children}</ConfiguredThebeServerProvider>
|
|
69
|
+
</SiteProvider>
|
|
70
|
+
</ThebeCoreProvider>
|
|
71
|
+
</BaseUrlProvider>
|
|
57
72
|
</ThemeProvider>
|
|
58
73
|
<ScrollRestoration />
|
|
59
74
|
<Scripts />
|
|
60
|
-
<LiveReload />
|
|
75
|
+
{!staticBuild && <LiveReload />}
|
|
61
76
|
{scripts}
|
|
62
77
|
</body>
|
|
63
78
|
</html>
|
|
@@ -74,37 +89,28 @@ export function App() {
|
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
export function AppWithReload() {
|
|
77
|
-
const { theme, config, CONTENT_CDN_PORT } = useLoaderData<SiteLoader>();
|
|
92
|
+
const { theme, config, CONTENT_CDN_PORT, MODE, BASE_URL } = useLoaderData<SiteLoader>();
|
|
78
93
|
return (
|
|
79
|
-
<Document
|
|
94
|
+
<Document
|
|
95
|
+
theme={theme}
|
|
96
|
+
config={config}
|
|
97
|
+
scripts={MODE === 'static' ? undefined : <ContentReload port={CONTENT_CDN_PORT} />}
|
|
98
|
+
staticBuild={MODE === 'static'}
|
|
99
|
+
baseurl={BASE_URL}
|
|
100
|
+
>
|
|
80
101
|
<Outlet />
|
|
81
102
|
</Document>
|
|
82
103
|
);
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
export function AppCatchBoundary() {
|
|
86
|
-
const caught = useCatch();
|
|
87
107
|
return (
|
|
88
|
-
<Document theme={Theme.light}
|
|
89
|
-
<article className="
|
|
108
|
+
<Document theme={Theme.light}>
|
|
109
|
+
<article className="article">
|
|
90
110
|
<main className="article-grid article-subgrid-gap col-screen">
|
|
91
|
-
<
|
|
111
|
+
<Error404 />
|
|
92
112
|
</main>
|
|
93
113
|
</article>
|
|
94
114
|
</Document>
|
|
95
115
|
);
|
|
96
116
|
}
|
|
97
|
-
|
|
98
|
-
export function AppDebugErrorBoundary({ error }: { error: { message: string; stack: string } }) {
|
|
99
|
-
return (
|
|
100
|
-
<Document theme={Theme.light} title="Error">
|
|
101
|
-
<div className="mt-16">
|
|
102
|
-
<main className="article-grid article-subgrid-gap col-screen">
|
|
103
|
-
<h1>An Error Occurred</h1>
|
|
104
|
-
<code>{error.message}</code>
|
|
105
|
-
<pre>{error.stack}</pre>
|
|
106
|
-
</main>
|
|
107
|
-
</div>
|
|
108
|
-
</Document>
|
|
109
|
-
);
|
|
110
|
-
}
|
package/src/pages/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ErrorProjectNotFound } from './ErrorProjectNotFound';
|
|
2
2
|
export { ErrorDocumentNotFound } from './ErrorDocumentNotFound';
|
|
3
|
-
export {
|
|
3
|
+
export { Error404 } from './Error404';
|
|
4
4
|
export { ArticlePage, ArticlePageCatchBoundary, ProjectPageCatchBoundary } from './Article';
|
|
5
|
-
export { App, AppWithReload, Document, AppCatchBoundary
|
|
5
|
+
export { App, AppWithReload, Document, AppCatchBoundary } from './Root';
|
package/src/seo/sitemap.ts
CHANGED
|
@@ -145,14 +145,15 @@ export function getSiteSlugs(
|
|
|
145
145
|
const slugs =
|
|
146
146
|
site.projects
|
|
147
147
|
?.map((project) => {
|
|
148
|
+
const projectSlug = project.slug ? `/${project.slug}` : '';
|
|
148
149
|
const pages = project.pages
|
|
149
150
|
.filter((page): page is ManifestProjectItem => 'slug' in page)
|
|
150
|
-
.map((page) => `${baseurl}
|
|
151
|
+
.map((page) => `${baseurl}${projectSlug}/${page.slug}`);
|
|
151
152
|
if (opts?.excludeIndex) return [...pages];
|
|
152
153
|
return [
|
|
153
154
|
opts?.explicitIndex
|
|
154
|
-
? `${baseurl}
|
|
155
|
-
: `${baseurl}
|
|
155
|
+
? `${baseurl}${projectSlug}/${project.index}`
|
|
156
|
+
: `${baseurl}${projectSlug}`,
|
|
156
157
|
...pages,
|
|
157
158
|
];
|
|
158
159
|
})
|
package/src/types.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type SiteLoader = {
|
|
|
17
17
|
theme: Theme;
|
|
18
18
|
config?: SiteManifest;
|
|
19
19
|
CONTENT_CDN_PORT?: string | number;
|
|
20
|
+
MODE?: 'app' | 'static';
|
|
21
|
+
BASE_URL?: string;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export type NavigationLink = {
|
|
@@ -38,6 +40,7 @@ export type PageLoader = {
|
|
|
38
40
|
sha256: string;
|
|
39
41
|
slug: string;
|
|
40
42
|
domain: string; // This is written in at render time in the site
|
|
43
|
+
project: string; // This is written in at render time in the site
|
|
41
44
|
frontmatter: PageFrontmatter;
|
|
42
45
|
mdast: Root;
|
|
43
46
|
references: References;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function ErrorSiteNotFound() {
|
|
2
|
-
return (
|
|
3
|
-
<>
|
|
4
|
-
<h1>No Site Found</h1>
|
|
5
|
-
<p>No website is available at this url, please double check the url.</p>
|
|
6
|
-
<h3>What's next?</h3>
|
|
7
|
-
<p>
|
|
8
|
-
If you are expecting to see <span className="font-semibold">your website</span> here and you
|
|
9
|
-
think that something has gone wrong, please send an email to{' '}
|
|
10
|
-
<a
|
|
11
|
-
href={`mailto:support@curvenote.com?subject=Website%20Unavailable&body=${encodeURIComponent(
|
|
12
|
-
`My website is not available. 😥`,
|
|
13
|
-
)}`}
|
|
14
|
-
>
|
|
15
|
-
support@curvenote.com
|
|
16
|
-
</a>
|
|
17
|
-
, or let us know on our <a href="https://slack.curvenote.dev">community slack</a>, and
|
|
18
|
-
we'll help out.
|
|
19
|
-
</p>
|
|
20
|
-
<p>
|
|
21
|
-
Or create a new temporary website from Markdown and Jupyter Notebooks using{' '}
|
|
22
|
-
<a href="https://try.curvenote.com">try.curvenote.com</a>.
|
|
23
|
-
</p>
|
|
24
|
-
<p>
|
|
25
|
-
Or find out more about Curvenote's scientific writing, collaboration and publishing
|
|
26
|
-
tools at <a href="https://curvenote.com">curvenote.com</a>.
|
|
27
|
-
</p>
|
|
28
|
-
</>
|
|
29
|
-
);
|
|
30
|
-
}
|