@myst-theme/site 0.3.7 → 0.4.0
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 +11 -10
- package/src/components/ContentBlocks.tsx +4 -7
- package/src/components/DocumentOutline.tsx +13 -13
- package/src/components/renderers.ts +2 -1
- package/src/loaders/utils.ts +19 -2
- package/src/pages/Article.tsx +22 -8
- package/src/pages/Root.tsx +2 -17
- package/src/pages/index.ts +1 -1
- package/src/types.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myst-theme/site",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"main": "./src/index.ts",
|
|
5
5
|
"types": "./src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -16,20 +16,21 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@headlessui/react": "^1.7.15",
|
|
18
18
|
"@heroicons/react": "^2.0.18",
|
|
19
|
-
"@myst-theme/diagrams": "^0.
|
|
20
|
-
"@myst-theme/frontmatter": "^0.
|
|
21
|
-
"@myst-theme/jupyter": "^0.
|
|
22
|
-
"@myst-theme/providers": "^0.
|
|
19
|
+
"@myst-theme/diagrams": "^0.4.0",
|
|
20
|
+
"@myst-theme/frontmatter": "^0.4.0",
|
|
21
|
+
"@myst-theme/jupyter": "^0.4.0",
|
|
22
|
+
"@myst-theme/providers": "^0.4.0",
|
|
23
23
|
"classnames": "^2.3.2",
|
|
24
24
|
"lodash.throttle": "^4.1.1",
|
|
25
|
-
"myst-common": "^1.0
|
|
26
|
-
"myst-
|
|
27
|
-
"myst-
|
|
28
|
-
"myst-
|
|
25
|
+
"myst-common": "^1.1.0",
|
|
26
|
+
"myst-spec-ext": "^1.1.0",
|
|
27
|
+
"myst-config": "^1.1.0",
|
|
28
|
+
"myst-demo": "^0.4.0",
|
|
29
|
+
"myst-to-react": "^0.4.0",
|
|
29
30
|
"nbtx": "^0.2.3",
|
|
30
31
|
"node-cache": "^5.1.2",
|
|
31
32
|
"node-fetch": "^2.6.11",
|
|
32
|
-
"thebe-react": "^0.
|
|
33
|
+
"thebe-react": "^0.3.0",
|
|
33
34
|
"unist-util-select": "^4.0.1"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { SourceFileKind } from 'myst-
|
|
1
|
+
import { MyST } from 'myst-to-react';
|
|
2
|
+
import { SourceFileKind } from 'myst-spec-ext';
|
|
3
3
|
import type { GenericParent } from 'myst-common';
|
|
4
|
-
import { useNodeRenderers } from '@myst-theme/providers';
|
|
5
4
|
import classNames from 'classnames';
|
|
6
5
|
import {
|
|
7
6
|
NotebookClearCell,
|
|
@@ -31,8 +30,6 @@ function Block({
|
|
|
31
30
|
node: GenericParent;
|
|
32
31
|
className?: string;
|
|
33
32
|
}) {
|
|
34
|
-
const renderers = useNodeRenderers() ?? DEFAULT_RENDERERS;
|
|
35
|
-
const children = useParse(node, renderers);
|
|
36
33
|
const subGrid = 'article-grid article-subgrid-gap col-screen';
|
|
37
34
|
const dataClassName = typeof node.data?.class === 'string' ? node.data?.class : undefined;
|
|
38
35
|
// Hide the subgrid if either the dataClass or the className exists and includes `col-`
|
|
@@ -40,7 +37,7 @@ function Block({
|
|
|
40
37
|
(dataClassName && dataClassName.includes('col-')) || (className && className.includes('col-'));
|
|
41
38
|
return (
|
|
42
39
|
<div
|
|
43
|
-
key={id}
|
|
40
|
+
key={`block-${id}`}
|
|
44
41
|
id={id}
|
|
45
42
|
className={classNames('relative group/block', className, dataClassName, {
|
|
46
43
|
[subGrid]: !noSubGrid,
|
|
@@ -61,7 +58,7 @@ function Block({
|
|
|
61
58
|
</div>
|
|
62
59
|
</>
|
|
63
60
|
)}
|
|
64
|
-
{children}
|
|
61
|
+
<MyST ast={node.children} />
|
|
65
62
|
</div>
|
|
66
63
|
);
|
|
67
64
|
}
|
|
@@ -26,7 +26,7 @@ type Props = {
|
|
|
26
26
|
* scrollIntoView is used to ensure that when a user clicks on an item, it will smoothly scroll.
|
|
27
27
|
*/
|
|
28
28
|
const Headings = ({ headings, activeId, highlight, selector }: Props) => (
|
|
29
|
-
<ul className="text-sm text-slate-400
|
|
29
|
+
<ul className="text-sm leading-6 text-slate-400">
|
|
30
30
|
{headings.map((heading) => (
|
|
31
31
|
<li
|
|
32
32
|
key={heading.id}
|
|
@@ -43,7 +43,7 @@ const Headings = ({ headings, activeId, highlight, selector }: Props) => (
|
|
|
43
43
|
'text-slate-500 dark:text-slate-300': heading.level >= 3 && heading.id !== activeId,
|
|
44
44
|
'text-blue-600 dark:text-white font-bold': heading.id === activeId,
|
|
45
45
|
'pr-2': heading.id !== activeId, // Allows for bold to change length
|
|
46
|
-
'pl-2': heading.level === 2,
|
|
46
|
+
'pl-2': heading.level === 1 || heading.level === 2,
|
|
47
47
|
'pl-4': heading.level === 3,
|
|
48
48
|
'pl-8 text-xs': heading.level === 4,
|
|
49
49
|
'pl-10 text-xs font-light': heading.level === 5,
|
|
@@ -86,11 +86,14 @@ function useHeaders(selector: string) {
|
|
|
86
86
|
|
|
87
87
|
const highlight = useCallback(() => {
|
|
88
88
|
const current = [...onScreen.current];
|
|
89
|
-
const highlighted = current.reduce(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
const highlighted = current.reduce(
|
|
90
|
+
(a, b) => {
|
|
91
|
+
if (a) return a;
|
|
92
|
+
if (b.classList.contains('highlight')) return b.id;
|
|
93
|
+
return null;
|
|
94
|
+
},
|
|
95
|
+
null as string | null,
|
|
96
|
+
);
|
|
94
97
|
const active = [...onScreen.current].sort((a, b) => a.offsetTop - b.offsetTop)[0];
|
|
95
98
|
if (highlighted || active) setActiveId(highlighted || active.id);
|
|
96
99
|
}, []);
|
|
@@ -156,9 +159,6 @@ const useIntersectionObserver = (highlight: () => void, onScreen: Set<HTMLHeadin
|
|
|
156
159
|
return { observer };
|
|
157
160
|
};
|
|
158
161
|
|
|
159
|
-
const DOC_OUTLINE_CLASS =
|
|
160
|
-
'fixed bottom-0 right-[max(0px,calc(50%-45rem))] w-[14rem] lg:w-[18rem] py-10 px-4 lg:px-8 overflow-y-auto hidden lg:block';
|
|
161
|
-
|
|
162
162
|
export function useOutlineHeight<T extends HTMLElement = HTMLElement>() {
|
|
163
163
|
const container = useRef<T>(null);
|
|
164
164
|
const outline = useRef<T>(null);
|
|
@@ -186,7 +186,7 @@ export function useOutlineHeight<T extends HTMLElement = HTMLElement>() {
|
|
|
186
186
|
export const DocumentOutline = ({
|
|
187
187
|
outlineRef,
|
|
188
188
|
top,
|
|
189
|
-
className
|
|
189
|
+
className,
|
|
190
190
|
selector = SELECTOR,
|
|
191
191
|
}: {
|
|
192
192
|
outlineRef?: React.RefObject<HTMLElement>;
|
|
@@ -204,7 +204,7 @@ export const DocumentOutline = ({
|
|
|
204
204
|
ref={outlineRef}
|
|
205
205
|
aria-label="Document Outline"
|
|
206
206
|
className={classNames(
|
|
207
|
-
'not-prose overflow-y-auto
|
|
207
|
+
'not-prose overflow-y-auto',
|
|
208
208
|
'transition-opacity duration-700', // Animation on load
|
|
209
209
|
className,
|
|
210
210
|
)}
|
|
@@ -213,7 +213,7 @@ export const DocumentOutline = ({
|
|
|
213
213
|
maxHeight: `calc(100vh - ${(top ?? 0) + 20}px)`,
|
|
214
214
|
}}
|
|
215
215
|
>
|
|
216
|
-
<div className="mb-4 text-sm uppercase text-slate-900
|
|
216
|
+
<div className="mb-4 text-sm leading-6 uppercase text-slate-900 dark:text-slate-100">
|
|
217
217
|
In this article
|
|
218
218
|
</div>
|
|
219
219
|
<Headings headings={headings} activeId={activeId} highlight={highlight} selector={selector} />
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { NodeRenderer } from '@myst-theme/providers';
|
|
1
2
|
import { DEFAULT_RENDERERS } from 'myst-to-react';
|
|
2
3
|
import { MystDemoRenderer } from 'myst-demo';
|
|
3
4
|
import { MermaidNodeRenderer } from '@myst-theme/diagrams';
|
|
4
5
|
import OUTPUT_RENDERERS from '@myst-theme/jupyter';
|
|
5
6
|
|
|
6
|
-
export const renderers = {
|
|
7
|
+
export const renderers: Record<string, NodeRenderer> = {
|
|
7
8
|
...DEFAULT_RENDERERS,
|
|
8
9
|
myst: MystDemoRenderer,
|
|
9
10
|
mermaid: MermaidNodeRenderer,
|
package/src/loaders/utils.ts
CHANGED
|
@@ -101,6 +101,17 @@ export function updateSiteManifestStaticLinksInplace(
|
|
|
101
101
|
if (data.logo_dark) data.logo_dark = updateUrl(data.logo_dark);
|
|
102
102
|
// Update the thumbnails to point at the CDN
|
|
103
103
|
data.projects?.forEach((project) => {
|
|
104
|
+
if (project.banner) project.banner = updateUrl(project.banner);
|
|
105
|
+
if (project.bannerOptimized) project.bannerOptimized = updateUrl(project.bannerOptimized);
|
|
106
|
+
if (project.thumbnail) project.thumbnail = updateUrl(project.thumbnail);
|
|
107
|
+
if (project.thumbnailOptimized)
|
|
108
|
+
project.thumbnailOptimized = updateUrl(project.thumbnailOptimized);
|
|
109
|
+
if (project?.exports) {
|
|
110
|
+
project.exports = project.exports.map((exp) => {
|
|
111
|
+
if (!exp.url) return exp;
|
|
112
|
+
return { ...exp, url: updateUrl(exp.url) };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
104
115
|
project.pages
|
|
105
116
|
.filter((page): page is ManifestProjectItem => 'slug' in page)
|
|
106
117
|
.forEach((page) => {
|
|
@@ -118,6 +129,12 @@ export function updatePageStaticLinksInplace(data: PageLoader, updateUrl: Update
|
|
|
118
129
|
if (data?.frontmatter?.thumbnailOptimized) {
|
|
119
130
|
data.frontmatter.thumbnailOptimized = updateUrl(data.frontmatter.thumbnailOptimized);
|
|
120
131
|
}
|
|
132
|
+
if (data?.frontmatter?.banner) {
|
|
133
|
+
data.frontmatter.banner = updateUrl(data.frontmatter.banner);
|
|
134
|
+
}
|
|
135
|
+
if (data?.frontmatter?.bannerOptimized) {
|
|
136
|
+
data.frontmatter.bannerOptimized = updateUrl(data.frontmatter.bannerOptimized);
|
|
137
|
+
}
|
|
121
138
|
if (data?.frontmatter?.exports) {
|
|
122
139
|
data.frontmatter.exports = data.frontmatter.exports.map((exp) => {
|
|
123
140
|
if (!exp.url) return exp;
|
|
@@ -142,8 +159,8 @@ export function updatePageStaticLinksInplace(data: PageLoader, updateUrl: Update
|
|
|
142
159
|
outputs.forEach((node) => {
|
|
143
160
|
if (!node.data) return;
|
|
144
161
|
walkOutputs(node.data, (obj) => {
|
|
145
|
-
// The path will be defined from output of myst
|
|
146
|
-
// Here we are re-
|
|
162
|
+
// The path will be defined from output of myst
|
|
163
|
+
// Here we are re-assigning it to the current domain
|
|
147
164
|
if (!obj.path) return;
|
|
148
165
|
obj.path = updateUrl(obj.path);
|
|
149
166
|
});
|
package/src/pages/Article.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { ErrorDocumentNotFound } from './ErrorDocumentNotFound';
|
|
|
5
5
|
import { ErrorProjectNotFound } from './ErrorProjectNotFound';
|
|
6
6
|
import type { PageLoader } from '../types';
|
|
7
7
|
import type { GenericParent } from 'myst-common';
|
|
8
|
-
import { SourceFileKind } from 'myst-
|
|
8
|
+
import { SourceFileKind } from 'myst-spec-ext';
|
|
9
9
|
import {
|
|
10
10
|
useComputeOptions,
|
|
11
11
|
ExecuteScopeProvider,
|
|
@@ -13,16 +13,24 @@ import {
|
|
|
13
13
|
NotebookToolbar,
|
|
14
14
|
ConnectionStatusTray,
|
|
15
15
|
BinderBadge,
|
|
16
|
+
useCanCompute,
|
|
17
|
+
ErrorTray,
|
|
16
18
|
} from '@myst-theme/jupyter';
|
|
17
19
|
import { FrontmatterBlock } from '@myst-theme/frontmatter';
|
|
18
20
|
|
|
19
|
-
export const ArticlePage = React.memo(function ({
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
export const ArticlePage = React.memo(function ({
|
|
22
|
+
article,
|
|
23
|
+
hide_all_footer_links,
|
|
24
|
+
}: {
|
|
25
|
+
article: PageLoader;
|
|
26
|
+
hide_all_footer_links?: boolean;
|
|
27
|
+
}) {
|
|
28
|
+
const canCompute = useCanCompute(article);
|
|
29
|
+
const { binderBadgeUrl } = useComputeOptions();
|
|
22
30
|
const { hide_title_block, hide_footer_links } = (article.frontmatter as any)?.design ?? {};
|
|
23
31
|
|
|
24
32
|
// take binder url from article frontmatter or fallback to project
|
|
25
|
-
const binderUrl = article.frontmatter.binder ??
|
|
33
|
+
const binderUrl = article.frontmatter.binder ?? binderBadgeUrl;
|
|
26
34
|
|
|
27
35
|
return (
|
|
28
36
|
<ReferencesProvider
|
|
@@ -32,7 +40,11 @@ export const ArticlePage = React.memo(function ({ article }: { article: PageLoad
|
|
|
32
40
|
<BusyScopeProvider>
|
|
33
41
|
<ExecuteScopeProvider contents={article}>
|
|
34
42
|
{!hide_title_block && (
|
|
35
|
-
<FrontmatterBlock
|
|
43
|
+
<FrontmatterBlock
|
|
44
|
+
kind={article.kind}
|
|
45
|
+
frontmatter={article.frontmatter}
|
|
46
|
+
className="mb-8"
|
|
47
|
+
/>
|
|
36
48
|
)}
|
|
37
49
|
{binderUrl && !canCompute && (
|
|
38
50
|
<div className="flex justify-end">
|
|
@@ -40,11 +52,13 @@ export const ArticlePage = React.memo(function ({ article }: { article: PageLoad
|
|
|
40
52
|
</div>
|
|
41
53
|
)}
|
|
42
54
|
{canCompute && article.kind === SourceFileKind.Notebook && <NotebookToolbar showLaunch />}
|
|
43
|
-
|
|
55
|
+
<ErrorTray pageSlug={article.slug} />
|
|
44
56
|
<ContentBlocks pageKind={article.kind} mdast={article.mdast as GenericParent} />
|
|
45
57
|
<Bibliography />
|
|
46
58
|
<ConnectionStatusTray />
|
|
47
|
-
{!hide_footer_links &&
|
|
59
|
+
{!hide_footer_links && !hide_all_footer_links && (
|
|
60
|
+
<FooterLinksBlock links={article.footer} />
|
|
61
|
+
)}
|
|
48
62
|
</ExecuteScopeProvider>
|
|
49
63
|
</BusyScopeProvider>
|
|
50
64
|
</ReferencesProvider>
|
package/src/pages/Root.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
Link,
|
|
13
13
|
NavLink,
|
|
14
14
|
} from '@remix-run/react';
|
|
15
|
-
import {
|
|
15
|
+
import { renderers } from '../components';
|
|
16
16
|
import { Analytics } from '../seo';
|
|
17
17
|
import { Error404 } from './Error404';
|
|
18
18
|
import classNames from 'classnames';
|
|
@@ -60,7 +60,7 @@ export function Document({
|
|
|
60
60
|
analytics_plausible={config?.analytics_plausible}
|
|
61
61
|
/>
|
|
62
62
|
</head>
|
|
63
|
-
<body className="m-0
|
|
63
|
+
<body className="m-0 transition-colors duration-500 bg-white dark:bg-stone-900">
|
|
64
64
|
<ThemeProvider theme={theme} renderers={renderers} {...links}>
|
|
65
65
|
<BaseUrlProvider baseurl={baseurl}>
|
|
66
66
|
<ThebeBundleLoaderProvider loadThebeLite publicPath={baseurl}>
|
|
@@ -88,21 +88,6 @@ export function App() {
|
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export function AppWithReload() {
|
|
92
|
-
const { theme, config, CONTENT_CDN_PORT, MODE, BASE_URL } = useLoaderData<SiteLoader>();
|
|
93
|
-
return (
|
|
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
|
-
>
|
|
101
|
-
<Outlet />
|
|
102
|
-
</Document>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
91
|
export function AppCatchBoundary() {
|
|
107
92
|
return (
|
|
108
93
|
<Document theme={Theme.light}>
|
package/src/pages/index.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { ErrorProjectNotFound } from './ErrorProjectNotFound';
|
|
|
2
2
|
export { ErrorDocumentNotFound } from './ErrorDocumentNotFound';
|
|
3
3
|
export { Error404 } from './Error404';
|
|
4
4
|
export { ArticlePage, ArticlePageCatchBoundary, ProjectPageCatchBoundary } from './Article';
|
|
5
|
-
export { App,
|
|
5
|
+
export { App, Document, AppCatchBoundary } from './Root';
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Root } from 'mdast';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Dependency, SourceFileKind } from 'myst-spec-ext';
|
|
3
|
+
import type { References } from 'myst-common';
|
|
3
4
|
import type { SiteManifest } from 'myst-config';
|
|
4
5
|
import type { PageFrontmatter } from 'myst-frontmatter';
|
|
5
6
|
import type { Theme } from '@myst-theme/providers';
|