@myst-theme/site 0.0.17

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.
Files changed (37) hide show
  1. package/package.json +53 -0
  2. package/src/components/Bibliography.tsx +51 -0
  3. package/src/components/ContentBlocks.tsx +20 -0
  4. package/src/components/ContentReload.tsx +66 -0
  5. package/src/components/DocumentOutline.tsx +187 -0
  6. package/src/components/ExternalOrInternalLink.tsx +30 -0
  7. package/src/components/FooterLinksBlock.tsx +39 -0
  8. package/src/components/Navigation/Loading.tsx +59 -0
  9. package/src/components/Navigation/Navigation.tsx +31 -0
  10. package/src/components/Navigation/TableOfContents.tsx +155 -0
  11. package/src/components/Navigation/ThemeButton.tsx +25 -0
  12. package/src/components/Navigation/TopNav.tsx +249 -0
  13. package/src/components/Navigation/index.tsx +5 -0
  14. package/src/components/index.ts +8 -0
  15. package/src/components/renderers.ts +7 -0
  16. package/src/hooks/index.ts +23 -0
  17. package/src/index.ts +8 -0
  18. package/src/loaders/cdn.server.ts +145 -0
  19. package/src/loaders/errors.server.ts +20 -0
  20. package/src/loaders/index.ts +5 -0
  21. package/src/loaders/links.ts +8 -0
  22. package/src/loaders/theme.server.ts +47 -0
  23. package/src/loaders/utils.ts +145 -0
  24. package/src/pages/Article.tsx +31 -0
  25. package/src/pages/ErrorDocumentNotFound.tsx +10 -0
  26. package/src/pages/ErrorProjectNotFound.tsx +10 -0
  27. package/src/pages/ErrorSiteNotFound.tsx +30 -0
  28. package/src/pages/Root.tsx +91 -0
  29. package/src/pages/index.ts +5 -0
  30. package/src/seo/analytics.tsx +34 -0
  31. package/src/seo/index.ts +4 -0
  32. package/src/seo/meta.ts +57 -0
  33. package/src/seo/robots.ts +24 -0
  34. package/src/seo/sitemap.ts +216 -0
  35. package/src/store.ts +21 -0
  36. package/src/types.ts +49 -0
  37. package/src/utils.ts +5 -0
@@ -0,0 +1,216 @@
1
+ import type { SiteManifest } from 'myst-config';
2
+
3
+ type ManifestProjectItem = Required<SiteManifest>['projects'][0]['pages'][0];
4
+
5
+ export function sitemapStylesheetIndex() {
6
+ return `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9" version="1.0" exclude-result-prefixes="sitemap">
7
+ <xsl:output method="html" encoding="UTF-8" indent="yes"/>
8
+ <xsl:variable name="has-lastmod" select="count( /sitemap:sitemapindex/sitemap:sitemap/sitemap:lastmod )"/>
9
+ <xsl:template match="/">
10
+ <html lang="en-US" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
11
+ <head>
12
+ <title>XML Sitemap</title>
13
+ <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #444; } #sitemap { max-width: 980px; margin: 0 auto; } #sitemap__table { width: 100%; border: solid 1px #ccc; border-collapse: collapse; } #sitemap__table tr td.loc { /* * URLs should always be LTR. * See https://core.trac.wordpress.org/ticket/16834 * and https://core.trac.wordpress.org/ticket/49949 */ direction: ltr; } #sitemap__table tr th { text-align: left; } #sitemap__table tr td, #sitemap__table tr th { padding: 10px; } #sitemap__table tr:nth-child(odd) td { background-color: #eee; } a:hover { text-decoration: none; } </style>
14
+ </head>
15
+ <body>
16
+ <div id="sitemap">
17
+ <div id="sitemap__header">
18
+ <h1>XML Sitemap</h1>
19
+ <p>This XML Sitemap is generated by Curvenote to make your content more visible for search engines.</p>
20
+ <p>
21
+ <a href="https://www.sitemaps.org/">Learn more about XML sitemaps.</a>
22
+ </p>
23
+ </div>
24
+ <div id="sitemap__content">
25
+ <p class="text">
26
+ Number of URLs in this XML Sitemap:
27
+ <xsl:value-of select="count( sitemap:sitemapindex/sitemap:sitemap )"/>
28
+ .
29
+ </p>
30
+ <table id="sitemap__table">
31
+ <thead>
32
+ <tr>
33
+ <th class="loc">URL</th>
34
+ <xsl:if test="$has-lastmod">
35
+ <th class="lastmod">Last Modified</th>
36
+ </xsl:if>
37
+ </tr>
38
+ </thead>
39
+ <tbody>
40
+ <xsl:for-each select="sitemap:sitemapindex/sitemap:sitemap">
41
+ <tr>
42
+ <td class="loc">
43
+ <a href="{sitemap:loc}">
44
+ <xsl:value-of select="sitemap:loc"/>
45
+ </a>
46
+ </td>
47
+ <xsl:if test="$has-lastmod">
48
+ <td class="lastmod">
49
+ <xsl:value-of select="sitemap:lastmod"/>
50
+ </td>
51
+ </xsl:if>
52
+ </tr>
53
+ </xsl:for-each>
54
+ </tbody>
55
+ </table>
56
+ </div>
57
+ </div>
58
+ </body>
59
+ </html>
60
+ </xsl:template>
61
+ </xsl:stylesheet>`;
62
+ }
63
+
64
+ export function sitemapStylesheet() {
65
+ return `<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9" version="1.0" exclude-result-prefixes="sitemap">
66
+ <xsl:output method="html" encoding="UTF-8" indent="yes"/>
67
+ <xsl:variable name="has-lastmod" select="count( /sitemap:urlset/sitemap:url/sitemap:lastmod )"/>
68
+ <xsl:variable name="has-changefreq" select="count( /sitemap:urlset/sitemap:url/sitemap:changefreq )"/>
69
+ <xsl:variable name="has-priority" select="count( /sitemap:urlset/sitemap:url/sitemap:priority )"/>
70
+ <xsl:template match="/">
71
+ <html lang="en-US" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
72
+ <head>
73
+ <title>XML Sitemap</title>
74
+ <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #444; } #sitemap { max-width: 980px; margin: 0 auto; } #sitemap__table { width: 100%; border: solid 1px #ccc; border-collapse: collapse; } #sitemap__table tr td.loc { /* * URLs should always be LTR. * See https://core.trac.wordpress.org/ticket/16834 * and https://core.trac.wordpress.org/ticket/49949 */ direction: ltr; } #sitemap__table tr th { text-align: left; } #sitemap__table tr td, #sitemap__table tr th { padding: 10px; } #sitemap__table tr:nth-child(odd) td { background-color: #eee; } a:hover { text-decoration: none; } </style>
75
+ </head>
76
+ <body>
77
+ <div id="sitemap">
78
+ <div id="sitemap__header">
79
+ <h1>XML Sitemap</h1>
80
+ <p>This XML Sitemap is generated by Curvenote to make your content more visible for search engines.</p>
81
+ <p>
82
+ <a href="https://www.sitemaps.org/">Learn more about XML sitemaps.</a>
83
+ </p>
84
+ </div>
85
+ <div id="sitemap__content">
86
+ <p class="text">
87
+ Number of URLs in this XML Sitemap:
88
+ <xsl:value-of select="count( sitemap:urlset/sitemap:url )"/>
89
+ </p>
90
+ <table id="sitemap__table">
91
+ <thead>
92
+ <tr>
93
+ <th class="loc">URL</th>
94
+ <xsl:if test="$has-lastmod">
95
+ <th class="lastmod">Last Modified</th>
96
+ </xsl:if>
97
+ <xsl:if test="$has-changefreq">
98
+ <th class="changefreq">Change Frequency</th>
99
+ </xsl:if>
100
+ <xsl:if test="$has-priority">
101
+ <th class="priority">Priority</th>
102
+ </xsl:if>
103
+ </tr>
104
+ </thead>
105
+ <tbody>
106
+ <xsl:for-each select="sitemap:urlset/sitemap:url">
107
+ <tr>
108
+ <td class="loc">
109
+ <a href="{sitemap:loc}">
110
+ <xsl:value-of select="sitemap:loc"/>
111
+ </a>
112
+ </td>
113
+ <xsl:if test="$has-lastmod">
114
+ <td class="lastmod">
115
+ <xsl:value-of select="sitemap:lastmod"/>
116
+ </td>
117
+ </xsl:if>
118
+ <xsl:if test="$has-changefreq">
119
+ <td class="changefreq">
120
+ <xsl:value-of select="sitemap:changefreq"/>
121
+ </td>
122
+ </xsl:if>
123
+ <xsl:if test="$has-priority">
124
+ <td class="priority">
125
+ <xsl:value-of select="sitemap:priority"/>
126
+ </td>
127
+ </xsl:if>
128
+ </tr>
129
+ </xsl:for-each>
130
+ </tbody>
131
+ </table>
132
+ </div>
133
+ </div>
134
+ </body>
135
+ </html>
136
+ </xsl:template>
137
+ </xsl:stylesheet>`;
138
+ }
139
+
140
+ export function getSiteSlugs(
141
+ site: SiteManifest,
142
+ baseurl = '',
143
+ opts?: { excludeIndex?: boolean; explicitIndex?: boolean },
144
+ ): string[] {
145
+ const slugs =
146
+ site.projects
147
+ ?.map((project) => {
148
+ const pages = project.pages
149
+ .filter((page): page is ManifestProjectItem => 'slug' in page)
150
+ .map((page) => `${baseurl}/${project.slug}/${page.slug}`);
151
+ if (opts?.excludeIndex) return [...pages];
152
+ return [
153
+ opts?.explicitIndex
154
+ ? `${baseurl}/${project.slug}/${project.index}`
155
+ : `${baseurl}/${project.slug}`,
156
+ ...pages,
157
+ ];
158
+ })
159
+ .flat() ?? [];
160
+ return slugs;
161
+ }
162
+
163
+ export function createSitemapIndex(
164
+ domain: string,
165
+ sitemaps: string[],
166
+ style = '/sitemap_index.xsl',
167
+ ) {
168
+ const sitemapsXml = sitemaps
169
+ .map((sitemap) => ` <sitemap>\n <loc>${domain}${sitemap}</loc>\n </sitemap>`)
170
+ .join('\n');
171
+ return `<?xml version="1.0" encoding="UTF-8"?>
172
+ <?xml-stylesheet type="text/xsl" href="${domain}${style}" ?>
173
+ <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
174
+ ${sitemapsXml}
175
+ </sitemapindex>`;
176
+ }
177
+
178
+ export function createSitemap(domain: string, pages: string[], style = '/sitemap_style.xsl') {
179
+ const urlsXml = pages
180
+ .map((url) => ` <url>\n <loc>${domain}${url}</loc>\n </url>`)
181
+ .join('\n');
182
+
183
+ return `<?xml version="1.0" encoding="UTF-8"?>
184
+ <?xml-stylesheet type="text/xsl" href="${domain}${style}" ?>
185
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
186
+ ${urlsXml}
187
+ </urlset>`;
188
+ }
189
+
190
+ export function sitemapStylesheetIndexResponse() {
191
+ return new Response(sitemapStylesheetIndex(), {
192
+ status: 200,
193
+ headers: { 'Content-Type': 'application/xml' },
194
+ });
195
+ }
196
+
197
+ export async function sitemapStylesheetResponse() {
198
+ return new Response(sitemapStylesheet(), {
199
+ status: 200,
200
+ headers: { 'Content-Type': 'application/xml' },
201
+ });
202
+ }
203
+
204
+ export function createSitemapIndexResponse(domain: string, pages: string[]) {
205
+ return new Response(createSitemapIndex(domain, pages), {
206
+ status: 200,
207
+ headers: { 'Content-Type': 'application/xml' },
208
+ });
209
+ }
210
+
211
+ export function createSitemapResponse(domain: string, pages: string[]) {
212
+ return new Response(createSitemap(domain, pages), {
213
+ status: 200,
214
+ headers: { 'Content-Type': 'application/xml' },
215
+ });
216
+ }
package/src/store.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { applyMiddleware, createStore, combineReducers } from 'redux';
2
+ import thunkMiddleware from 'redux-thunk';
3
+ import type { types } from '@curvenote/runtime';
4
+ import runtime from '@curvenote/runtime';
5
+ import type { HostState } from '@curvenote/connect';
6
+ import { host } from '@curvenote/connect';
7
+
8
+ export interface State {
9
+ runtime: types.State;
10
+ app: HostState;
11
+ }
12
+
13
+ export function createCurvenoteReduxStore() {
14
+ return createStore(
15
+ combineReducers({
16
+ runtime: runtime.reducer,
17
+ app: host.reducer,
18
+ }),
19
+ applyMiddleware(thunkMiddleware, runtime.triggerEvaluate, runtime.dangerousEvaluatation),
20
+ );
21
+ }
package/src/types.ts ADDED
@@ -0,0 +1,49 @@
1
+ import type { Root } from 'mdast';
2
+ import type { References } from 'myst-common';
3
+ import type { SiteManifest } from 'myst-config';
4
+ import type { PageFrontmatter } from 'myst-frontmatter';
5
+ import type { Theme } from '@myst-theme/providers';
6
+
7
+ enum KINDS {
8
+ Article = 'Article',
9
+ Notebook = 'Notebook',
10
+ }
11
+
12
+ export type Heading = {
13
+ slug?: string;
14
+ path?: string;
15
+ title: string;
16
+ level: number | 'index';
17
+ group?: string;
18
+ };
19
+
20
+ export type SiteLoader = {
21
+ theme: Theme;
22
+ config?: SiteManifest;
23
+ CONTENT_CDN_PORT?: string | number;
24
+ };
25
+
26
+ export type NavigationLink = {
27
+ group?: string;
28
+ title: string;
29
+ url: string;
30
+ };
31
+
32
+ export type FooterLinks = {
33
+ navigation?: {
34
+ prev?: NavigationLink;
35
+ next?: NavigationLink;
36
+ };
37
+ };
38
+
39
+ export type PageLoader = {
40
+ kind: KINDS;
41
+ file: string;
42
+ sha256: string;
43
+ slug: string;
44
+ domain: string; // This is written in at render time in the site
45
+ frontmatter: PageFrontmatter;
46
+ mdast: Root;
47
+ references: References;
48
+ footer?: FooterLinks;
49
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,5 @@
1
+ export function getDomainFromRequest(request: Request) {
2
+ const url = new URL(request.url);
3
+ const domain = `${url.protocol}//${url.hostname}${url.port ? `:${url.port}` : ''}`;
4
+ return domain;
5
+ }