@rocket/js 0.1.1 → 0.2.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/README.md +14 -23
- package/dist-types/exports/layouts/atlasBlog.d.ts +2 -0
- package/dist-types/exports/layouts/atlasBlog.d.ts.map +1 -0
- package/dist-types/exports/types/rocket.d.ts +68 -2
- package/dist-types/exports/types/rocket.d.ts.map +1 -1
- package/dist-types/exports/types.d.ts +1 -1
- package/dist-types/exports/types.d.ts.map +1 -1
- package/dist-types/src/PageData.d.ts +3 -1
- package/dist-types/src/PageData.d.ts.map +1 -1
- package/dist-types/src/RocketJsDemo.d.ts.map +1 -1
- package/dist-types/src/SocialPreviewPlayground.d.ts +1 -0
- package/dist-types/src/SocialPreviewPlayground.d.ts.map +1 -1
- package/dist-types/src/asyncMessage.d.ts +5 -0
- package/dist-types/src/asyncMessage.d.ts.map +1 -1
- package/dist-types/src/cli/RocketBuild.d.ts.map +1 -1
- package/dist-types/src/cli/RocketCli.d.ts.map +1 -1
- package/dist-types/src/cli/RocketInit.d.ts +5 -1
- package/dist-types/src/cli/RocketInit.d.ts.map +1 -1
- package/dist-types/src/cli/RocketStart.d.ts +6 -1
- package/dist-types/src/cli/RocketStart.d.ts.map +1 -1
- package/dist-types/src/component-hydration.d.ts.map +1 -1
- package/dist-types/src/components/RocketDrawer.d.ts +8 -0
- package/dist-types/src/components/RocketDrawer.d.ts.map +1 -1
- package/dist-types/src/components/RocketSocialLink.d.ts.map +1 -1
- package/dist-types/src/config.d.ts.map +1 -1
- package/dist-types/src/feeds.d.ts +38 -0
- package/dist-types/src/feeds.d.ts.map +1 -0
- package/dist-types/src/hydration/hydrationLoader.d.ts +13 -4
- package/dist-types/src/hydration/hydrationLoader.d.ts.map +1 -1
- package/dist-types/src/icons.d.ts.map +1 -1
- package/dist-types/src/layouts/atlas/atlasBlogLayout.d.ts +42 -0
- package/dist-types/src/layouts/atlas/atlasBlogLayout.d.ts.map +1 -0
- package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts +4 -0
- package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts.map +1 -1
- package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts.map +1 -1
- package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts.map +1 -1
- package/dist-types/src/layouts/layout-helper.d.ts +3 -3
- package/dist-types/src/layouts/layout-helper.d.ts.map +1 -1
- package/dist-types/src/markdownHook.d.ts.map +1 -1
- package/dist-types/src/menu.d.ts +8 -3
- package/dist-types/src/menu.d.ts.map +1 -1
- package/dist-types/src/menus/MainMenu.d.ts.map +1 -1
- package/dist-types/src/{development-page-module-loader.d.ts → page-module-loader.d.ts} +7 -2
- package/dist-types/src/page-module-loader.d.ts.map +1 -0
- package/dist-types/src/page-runtime.d.ts +11 -0
- package/dist-types/src/page-runtime.d.ts.map +1 -1
- package/dist-types/src/pages.d.ts.map +1 -1
- package/dist-types/src/route-pattern.d.ts +10 -0
- package/dist-types/src/route-pattern.d.ts.map +1 -0
- package/dist-types/src/siteDiscoverability.d.ts +4 -0
- package/dist-types/src/siteDiscoverability.d.ts.map +1 -1
- package/dist-types/src/socialPreviewImages.d.ts +2 -1
- package/dist-types/src/socialPreviewImages.d.ts.map +1 -1
- package/dist-types/src/static-params.d.ts +33 -0
- package/dist-types/src/static-params.d.ts.map +1 -0
- package/dist-types/src/transform.d.ts +4 -0
- package/dist-types/src/transform.d.ts.map +1 -1
- package/dist-types/src/wds-plugin.d.ts.map +1 -1
- package/exports/layouts/atlasBlog.js +11 -0
- package/exports/types/rocket.test.ts +26 -0
- package/exports/types/rocket.ts +78 -2
- package/exports/types.ts +7 -0
- package/package.json +16 -32
- package/src/PageData.js +12 -2
- package/src/RocketJsDemo.js +1 -0
- package/src/SocialPreviewPlayground.js +26 -20
- package/src/asyncMessage.js +8 -2
- package/src/cli/RocketBuild.js +110 -13
- package/src/cli/RocketCli.js +11 -1
- package/src/cli/RocketInit.js +64 -12
- package/src/cli/RocketStart.js +60 -16
- package/src/cli/cli.js +10 -1
- package/src/component-hydration.js +23 -3
- package/src/components/RocketDrawer.js +44 -10
- package/src/components/RocketSocialLink.js +26 -2
- package/src/config.js +33 -4
- package/src/feeds.js +212 -0
- package/src/hydration/hydrationLoader.js +80 -48
- package/src/icons.js +5 -0
- package/src/layouts/atlas/atlasBlog.css +143 -0
- package/src/layouts/atlas/atlasBlogLayout.js +234 -0
- package/src/layouts/atlas/atlasDocLayout.js +10 -1
- package/src/layouts/atlas/atlasHeroLayout.js +10 -6
- package/src/layouts/atlas/atlasNotFoundLayout.js +12 -22
- package/src/layouts/layout-helper.js +5 -5
- package/src/layouts/layout.js +2 -2
- package/src/loaded-page-module.js +3 -1
- package/src/markdownCompiler.js +2 -2
- package/src/markdownHook.js +7 -2
- package/src/menu.js +25 -19
- package/src/menus/MainMenu.js +10 -4
- package/src/{static-page-module-loader.js → page-module-loader.js} +6 -1
- package/src/page-pagination.js +2 -2
- package/src/page-runtime.js +48 -3
- package/src/pages.js +47 -56
- package/src/publicAssets.js +2 -2
- package/src/route-pattern.js +21 -0
- package/src/siteDiscoverability.js +14 -1
- package/src/socialPreviewImages.js +80 -14
- package/src/standalone-demo-url.js +2 -2
- package/src/static-params.js +114 -0
- package/src/transform.js +89 -22
- package/src/wds-plugin.js +16 -3
- package/dist-types/src/development-page-module-loader.d.ts.map +0 -1
- package/dist-types/src/static-page-module-loader.d.ts +0 -15
- package/dist-types/src/static-page-module-loader.d.ts.map +0 -1
- package/src/development-page-module-loader.js +0 -29
package/src/icons.js
CHANGED
|
@@ -131,6 +131,7 @@ export async function resolveRocketIconAsset(requestPath, options = {}) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
const librarySegment = match[1];
|
|
134
|
+
const nameSegment = match[2];
|
|
134
135
|
const resolver = createIconResolver({
|
|
135
136
|
layoutIconLibraries: options.layoutIconLibraries,
|
|
136
137
|
layoutDefaultIconLibrary: options.layoutDefaultIconLibrary,
|
|
@@ -144,6 +145,10 @@ export async function resolveRocketIconAsset(requestPath, options = {}) {
|
|
|
144
145
|
}
|
|
145
146
|
const icons = await indexIconLibrary(library, config);
|
|
146
147
|
for (const [name, svg] of icons) {
|
|
148
|
+
// hashing every icon's SVG is expensive, so narrow by name first
|
|
149
|
+
if (sanitizePathSegment(name) !== nameSegment) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
147
152
|
const url = iconAssetUrl({ library, name, svg });
|
|
148
153
|
if (url === requestPath) {
|
|
149
154
|
return { url, svg, library, name };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
.atlas-blog {
|
|
2
|
+
min-height: 100vh;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
color: var(--docs-text-color);
|
|
6
|
+
background: var(--docs-surface-color);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.atlas-blog-header {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: space-between;
|
|
13
|
+
gap: 1.5rem;
|
|
14
|
+
flex-wrap: wrap;
|
|
15
|
+
padding: 0.75rem clamp(1rem, 4vw, 2.5rem);
|
|
16
|
+
border-bottom: 1px solid var(--docs-line-color);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.atlas-blog-content {
|
|
20
|
+
width: 100%;
|
|
21
|
+
max-width: 760px;
|
|
22
|
+
margin: 0 auto;
|
|
23
|
+
padding: clamp(1.5rem, 4vw, 3rem) 1rem 4rem;
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.atlas-blog-byline {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
flex-wrap: wrap;
|
|
31
|
+
gap: 0.5rem 1rem;
|
|
32
|
+
margin-block: 0.5rem 2rem;
|
|
33
|
+
color: var(--docs-muted-color);
|
|
34
|
+
font-size: 0.9rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.atlas-blog-authors::before {
|
|
38
|
+
content: '·';
|
|
39
|
+
margin-right: 1rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.atlas-blog-tags {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
gap: 0.5rem;
|
|
46
|
+
list-style: none;
|
|
47
|
+
margin: 0;
|
|
48
|
+
padding: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.atlas-blog-tags a,
|
|
52
|
+
.atlas-blog-tags span {
|
|
53
|
+
display: inline-block;
|
|
54
|
+
padding: 0.1rem 0.6rem;
|
|
55
|
+
border: 1px solid var(--docs-line-color);
|
|
56
|
+
border-radius: 999px;
|
|
57
|
+
background: var(--docs-surface-soft-color);
|
|
58
|
+
color: var(--docs-muted-color);
|
|
59
|
+
font-size: 0.8rem;
|
|
60
|
+
text-decoration: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.atlas-blog-tags a:hover {
|
|
64
|
+
border-color: var(--primary-color);
|
|
65
|
+
color: var(--primary-color);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.atlas-blog-intro {
|
|
69
|
+
margin-bottom: 2rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.atlas-blog-feed-link {
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
gap: 0.4rem;
|
|
76
|
+
color: var(--docs-muted-color);
|
|
77
|
+
text-decoration: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.atlas-blog-feed-link:hover {
|
|
81
|
+
color: var(--primary-color);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.atlas-blog-post-list {
|
|
85
|
+
list-style: none;
|
|
86
|
+
margin: 0;
|
|
87
|
+
padding: 0;
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
gap: 1.5rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.atlas-blog-post-card {
|
|
94
|
+
padding: 1.25rem 1.5rem;
|
|
95
|
+
border: 1px solid var(--docs-line-color);
|
|
96
|
+
border-radius: 12px;
|
|
97
|
+
background: var(--docs-surface-soft-color);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.atlas-blog-post-card h2 {
|
|
101
|
+
margin: 0 0 0.25rem;
|
|
102
|
+
font-size: 1.25rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.atlas-blog-post-card h2 a {
|
|
106
|
+
color: var(--docs-text-dark-color);
|
|
107
|
+
text-decoration: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.atlas-blog-post-card h2 a:hover {
|
|
111
|
+
color: var(--primary-color);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.atlas-blog-post-card time {
|
|
115
|
+
color: var(--docs-muted-color);
|
|
116
|
+
font-size: 0.85rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.atlas-blog-post-card p {
|
|
120
|
+
margin: 0.5rem 0 0.75rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.atlas-blog-empty {
|
|
124
|
+
color: var(--docs-muted-color);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.atlas-blog-pagination {
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: space-between;
|
|
131
|
+
gap: 1rem;
|
|
132
|
+
margin-top: 2.5rem;
|
|
133
|
+
color: var(--docs-muted-color);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.atlas-blog-pagination a {
|
|
137
|
+
color: var(--link-color);
|
|
138
|
+
text-decoration: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.atlas-blog-pagination a:hover {
|
|
142
|
+
text-decoration: underline;
|
|
143
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { document } from '../layout-helper.js';
|
|
3
|
+
import { resolve } from '../../resolve.js';
|
|
4
|
+
import { webAwesomeComponents } from '@rocket/js/components/web-awesome.js';
|
|
5
|
+
import { addBootstrapIconLibrary } from '../layout.js';
|
|
6
|
+
import { rocketDemoComponents } from '../../components.js';
|
|
7
|
+
import {
|
|
8
|
+
renderHeaderLogo,
|
|
9
|
+
renderHeaderNavLinks,
|
|
10
|
+
renderSocials,
|
|
11
|
+
renderStylesheets,
|
|
12
|
+
} from './atlasDocLayout.js';
|
|
13
|
+
|
|
14
|
+
/** @typedef {import('@rocket/js/types.js').BlogData} BlogData */
|
|
15
|
+
/** @typedef {import('@rocket/js/types.js').PageCollectionEntry} PageCollectionEntry */
|
|
16
|
+
|
|
17
|
+
/** @type {import('@rocket/js/types.js').Components} */
|
|
18
|
+
export const atlasBlogComponents = {
|
|
19
|
+
'rocket-social-link': {
|
|
20
|
+
file: './components/RocketSocialLink.js',
|
|
21
|
+
className: 'RocketSocialLink',
|
|
22
|
+
loading: 'server',
|
|
23
|
+
},
|
|
24
|
+
...rocketDemoComponents,
|
|
25
|
+
...webAwesomeComponents,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} date date-only ISO string from Page Metadata
|
|
30
|
+
* @param {string | undefined} language
|
|
31
|
+
*/
|
|
32
|
+
export function formatBlogDate(date, language) {
|
|
33
|
+
const parsed = new Date(`${date}T00:00:00Z`);
|
|
34
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
35
|
+
return date;
|
|
36
|
+
}
|
|
37
|
+
return new Intl.DateTimeFormat(language || 'en', {
|
|
38
|
+
dateStyle: 'long',
|
|
39
|
+
timeZone: 'UTC',
|
|
40
|
+
}).format(parsed);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {string[] | undefined} tags
|
|
45
|
+
* @param {BlogData} data
|
|
46
|
+
*/
|
|
47
|
+
export function renderBlogTags(tags, data) {
|
|
48
|
+
if (!tags || tags.length === 0) {
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
return html`
|
|
52
|
+
<ul class="atlas-blog-tags">
|
|
53
|
+
${tags.map(
|
|
54
|
+
tag => html`
|
|
55
|
+
<li>
|
|
56
|
+
${data.tagPathPrefix
|
|
57
|
+
? html`<a href=${blogTagPath(data.tagPathPrefix, tag)} rel="tag">${tag}</a>`
|
|
58
|
+
: html`<span>${tag}</span>`}
|
|
59
|
+
</li>
|
|
60
|
+
`,
|
|
61
|
+
)}
|
|
62
|
+
</ul>
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {string} tagPathPrefix
|
|
68
|
+
* @param {string} tag
|
|
69
|
+
*/
|
|
70
|
+
export function blogTagPath(tagPathPrefix, tag) {
|
|
71
|
+
const prefix = tagPathPrefix.endsWith('/') ? tagPathPrefix : `${tagPathPrefix}/`;
|
|
72
|
+
return `${prefix}${tag}/`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {import('@rocket/js/types.js').PageMetadata} metadata
|
|
77
|
+
* @param {BlogData} data
|
|
78
|
+
* @param {string | undefined} language
|
|
79
|
+
*/
|
|
80
|
+
export function renderBlogByline(metadata, data, language) {
|
|
81
|
+
const authors = metadata.authors || [];
|
|
82
|
+
if (!metadata.date && authors.length === 0 && !(metadata.tags || []).length) {
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
return html`
|
|
86
|
+
<div class="atlas-blog-byline">
|
|
87
|
+
${metadata.date
|
|
88
|
+
? html`<time datetime=${metadata.date}>${formatBlogDate(metadata.date, language)}</time>`
|
|
89
|
+
: ''}
|
|
90
|
+
${authors.length ? html`<span class="atlas-blog-authors">${authors.join(', ')}</span>` : ''}
|
|
91
|
+
${renderBlogTags(metadata.tags, data)}
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {PageCollectionEntry[]} items
|
|
98
|
+
* @param {BlogData} data
|
|
99
|
+
* @param {string | undefined} language
|
|
100
|
+
*/
|
|
101
|
+
export function renderBlogPostList(items, data, language) {
|
|
102
|
+
if (items.length === 0) {
|
|
103
|
+
return html`<p class="atlas-blog-empty">No posts yet.</p>`;
|
|
104
|
+
}
|
|
105
|
+
return html`
|
|
106
|
+
<ol class="atlas-blog-post-list" reversed>
|
|
107
|
+
${items.map(
|
|
108
|
+
item => html`
|
|
109
|
+
<li class="atlas-blog-post-card">
|
|
110
|
+
<h2><a href=${item.url}>${item.metadata.title}</a></h2>
|
|
111
|
+
${item.metadata.date
|
|
112
|
+
? html`<time datetime=${item.metadata.date}
|
|
113
|
+
>${formatBlogDate(item.metadata.date, language)}</time
|
|
114
|
+
>`
|
|
115
|
+
: ''}
|
|
116
|
+
${item.metadata.description ? html`<p>${item.metadata.description}</p>` : ''}
|
|
117
|
+
${renderBlogTags(item.metadata.tags, data)}
|
|
118
|
+
</li>
|
|
119
|
+
`,
|
|
120
|
+
)}
|
|
121
|
+
</ol>
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {import('@rocket/js/types.js').PagePagination | undefined} pagination
|
|
127
|
+
*/
|
|
128
|
+
export function renderBlogPagination(pagination) {
|
|
129
|
+
if (!pagination || pagination.totalPages <= 1) {
|
|
130
|
+
return '';
|
|
131
|
+
}
|
|
132
|
+
return html`
|
|
133
|
+
<nav class="atlas-blog-pagination" aria-label="Blog pages">
|
|
134
|
+
${pagination.previousPath
|
|
135
|
+
? html`<a href=${pagination.previousPath} rel="prev">Newer posts</a>`
|
|
136
|
+
: html`<span></span>`}
|
|
137
|
+
<span>Page ${pagination.currentPage} of ${pagination.totalPages}</span>
|
|
138
|
+
${pagination.nextPath
|
|
139
|
+
? html`<a href=${pagination.nextPath} rel="next">Older posts</a>`
|
|
140
|
+
: html`<span></span>`}
|
|
141
|
+
</nav>
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Shared Atlas blog document chrome for post and index layouts.
|
|
147
|
+
*
|
|
148
|
+
* @param {import('../../PageData.js').PageData} pageData
|
|
149
|
+
* @param {BlogData} data
|
|
150
|
+
* @param {unknown} mainContent
|
|
151
|
+
*/
|
|
152
|
+
function atlasBlogDocument(pageData, data, mainContent) {
|
|
153
|
+
addBootstrapIconLibrary(pageData);
|
|
154
|
+
const cssPath = resolve('@rocket/js/docs/assets/prism-one-light.css', import.meta);
|
|
155
|
+
const siteName = pageData.siteHeadMetadata?.siteName ?? pageData.title;
|
|
156
|
+
const headContent = data.headContent?.({ pageData });
|
|
157
|
+
|
|
158
|
+
return document(
|
|
159
|
+
pageData,
|
|
160
|
+
html`
|
|
161
|
+
<div class="atlas-blog">
|
|
162
|
+
<header class="atlas-header atlas-blog-header">
|
|
163
|
+
<a href=${data.headerData.homeLink} class="logo-header">
|
|
164
|
+
${renderHeaderLogo(data.headerData.logo, siteName)}
|
|
165
|
+
</a>
|
|
166
|
+
<nav class="atlas-header-links" aria-label="Primary navigation">
|
|
167
|
+
${renderHeaderNavLinks(data.headerData.navLinks)}
|
|
168
|
+
${renderSocials(data.headerData.socials, siteName)}
|
|
169
|
+
</nav>
|
|
170
|
+
</header>
|
|
171
|
+
<main id="content" class="atlas-blog-content">${mainContent}</main>
|
|
172
|
+
</div>
|
|
173
|
+
`,
|
|
174
|
+
{
|
|
175
|
+
menu: false,
|
|
176
|
+
headContent: html`
|
|
177
|
+
<link rel="stylesheet" href=${cssPath} />
|
|
178
|
+
<link
|
|
179
|
+
rel="stylesheet"
|
|
180
|
+
href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
|
|
181
|
+
/>
|
|
182
|
+
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasDoc.css', import.meta)}" />
|
|
183
|
+
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasBlog.css', import.meta)}" />
|
|
184
|
+
${data.feedPath
|
|
185
|
+
? html`<link
|
|
186
|
+
rel="alternate"
|
|
187
|
+
type="application/atom+xml"
|
|
188
|
+
href=${data.feedPath}
|
|
189
|
+
title=${siteName}
|
|
190
|
+
/>`
|
|
191
|
+
: ''}
|
|
192
|
+
${renderStylesheets(data.stylesheets)} ${headContent}
|
|
193
|
+
`,
|
|
194
|
+
},
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** @type {import('@rocket/js/types.js').Layout<BlogData>} */
|
|
199
|
+
export const atlasPostLayout = (pageData, data) => {
|
|
200
|
+
const language = pageData.siteHeadMetadata?.language;
|
|
201
|
+
return atlasBlogDocument(
|
|
202
|
+
pageData,
|
|
203
|
+
data,
|
|
204
|
+
html`
|
|
205
|
+
<article class="atlas-blog-post">
|
|
206
|
+
${renderBlogByline(pageData.metadata, data, language)} ${pageData.content}
|
|
207
|
+
</article>
|
|
208
|
+
`,
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/** @type {import('@rocket/js/types.js').Layout<BlogData>} */
|
|
213
|
+
export const atlasBlogIndexLayout = (pageData, data) => {
|
|
214
|
+
const language = pageData.siteHeadMetadata?.language;
|
|
215
|
+
const items = pageData.pagination?.items || [];
|
|
216
|
+
return atlasBlogDocument(
|
|
217
|
+
pageData,
|
|
218
|
+
data,
|
|
219
|
+
html`
|
|
220
|
+
<section class="atlas-blog-index">
|
|
221
|
+
<div class="atlas-blog-intro">
|
|
222
|
+
${pageData.content}
|
|
223
|
+
${data.feedPath
|
|
224
|
+
? html`<a class="atlas-blog-feed-link" href=${data.feedPath}>
|
|
225
|
+
<rocket-icon library="bootstrap" name="rss" aria-hidden="true"></rocket-icon>
|
|
226
|
+
Feed
|
|
227
|
+
</a>`
|
|
228
|
+
: ''}
|
|
229
|
+
</div>
|
|
230
|
+
${renderBlogPostList(items, data, language)} ${renderBlogPagination(pageData.pagination)}
|
|
231
|
+
</section>
|
|
232
|
+
`,
|
|
233
|
+
);
|
|
234
|
+
};
|
|
@@ -119,6 +119,13 @@ export function renderHeaderNav(links = []) {
|
|
|
119
119
|
`;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* @param {string[] | undefined} stylesheets
|
|
124
|
+
*/
|
|
125
|
+
export function renderStylesheets(stylesheets = []) {
|
|
126
|
+
return stylesheets.map(href => html`<link rel="stylesheet" href=${href} />`);
|
|
127
|
+
}
|
|
128
|
+
|
|
122
129
|
/**
|
|
123
130
|
* @param {import('@rocket/js/types.js').PageMetadataCustomValue | undefined} customValue
|
|
124
131
|
* @returns {import('@rocket/js/types.js').AtlasDocAsideTip | false | undefined}
|
|
@@ -203,6 +210,7 @@ export const atlasDocLayout = (pageData, data) => {
|
|
|
203
210
|
const serializedToc = serializeToc(pageData.toc);
|
|
204
211
|
const navigationIconServerBudget =
|
|
205
212
|
data.navigationIconServerBudget ?? DEFAULT_ATLAS_DOC_NAVIGATION_ICON_SERVER_BUDGET;
|
|
213
|
+
const headContent = data.headContent?.({ pageData });
|
|
206
214
|
|
|
207
215
|
return document(
|
|
208
216
|
pageData,
|
|
@@ -262,13 +270,14 @@ export const atlasDocLayout = (pageData, data) => {
|
|
|
262
270
|
`,
|
|
263
271
|
{
|
|
264
272
|
menu: false,
|
|
265
|
-
|
|
273
|
+
headContent: html`
|
|
266
274
|
<link rel="stylesheet" href=${cssPath} />
|
|
267
275
|
<link
|
|
268
276
|
rel="stylesheet"
|
|
269
277
|
href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
|
|
270
278
|
/>
|
|
271
279
|
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasDoc.css', import.meta)}" />
|
|
280
|
+
${renderStylesheets(data.stylesheets)} ${headContent}
|
|
272
281
|
`,
|
|
273
282
|
},
|
|
274
283
|
);
|
|
@@ -3,7 +3,12 @@ import { document } from '../layout-helper.js';
|
|
|
3
3
|
import { resolve } from '../../resolve.js';
|
|
4
4
|
import { webAwesomeComponents } from '@rocket/js/components/web-awesome.js';
|
|
5
5
|
import { addBootstrapIconLibrary } from '../layout.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
renderHeaderLogo,
|
|
8
|
+
renderHeaderNav,
|
|
9
|
+
renderSocials,
|
|
10
|
+
renderStylesheets,
|
|
11
|
+
} from './atlasDocLayout.js';
|
|
7
12
|
import { rocketDemoComponents } from '../../components.js';
|
|
8
13
|
|
|
9
14
|
/** @type {import('@rocket/js/types.js').Components} */
|
|
@@ -257,10 +262,8 @@ export const atlasHeroLayout = (pageData, data) => {
|
|
|
257
262
|
const heroEyebrow = hero.eyebrow ?? hero.sloganTop;
|
|
258
263
|
const heroTitle = hero.title ?? hero.sloganBottom ?? pageData.title;
|
|
259
264
|
const siteName = pageData.siteHeadMetadata?.siteName ?? pageData.title;
|
|
260
|
-
const navLinks = data.headerData.navLinks ?? [
|
|
261
|
-
|
|
262
|
-
{ text: 'Examples', href: '/examples' },
|
|
263
|
-
];
|
|
265
|
+
const navLinks = data.headerData.navLinks ?? [{ text: 'Docs', href: hero.documentationLink }];
|
|
266
|
+
const headContent = data.headContent?.({ pageData });
|
|
264
267
|
|
|
265
268
|
return document(
|
|
266
269
|
pageData,
|
|
@@ -324,13 +327,14 @@ export const atlasHeroLayout = (pageData, data) => {
|
|
|
324
327
|
`,
|
|
325
328
|
{
|
|
326
329
|
menu: false,
|
|
327
|
-
|
|
330
|
+
headContent: html`
|
|
328
331
|
<link rel="stylesheet" href=${cssPath} />
|
|
329
332
|
<link
|
|
330
333
|
rel="stylesheet"
|
|
331
334
|
href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
|
|
332
335
|
/>
|
|
333
336
|
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasHero.css', import.meta)}" />
|
|
337
|
+
${renderStylesheets(data.stylesheets)} ${headContent}
|
|
334
338
|
`,
|
|
335
339
|
},
|
|
336
340
|
);
|
|
@@ -1,26 +1,11 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
2
|
import { document } from '../layout-helper.js';
|
|
3
3
|
import { resolve } from '../../resolve.js';
|
|
4
|
+
import { renderHeaderLogo, renderStylesheets } from './atlasDocLayout.js';
|
|
4
5
|
|
|
5
6
|
/** @type {import('@rocket/js/types.js').Components} */
|
|
6
7
|
export const atlasNotFoundComponents = {};
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
-
* Renders the header logo.
|
|
10
|
-
* @param {Array<string>} logo
|
|
11
|
-
*/
|
|
12
|
-
function renderHeaderLogo(logo) {
|
|
13
|
-
if (logo.length === 1) {
|
|
14
|
-
return html`<img src=${logo[0]} alt="Logo" width="130" />`;
|
|
15
|
-
} else if (logo.length === 2) {
|
|
16
|
-
return html`
|
|
17
|
-
<img src=${logo[0]} alt="Logo" width="36" />
|
|
18
|
-
<img src=${logo[1]} alt="Logo Text" width="88" />
|
|
19
|
-
`;
|
|
20
|
-
}
|
|
21
|
-
return html`<b>Header logo should only contain one or two images.</b>`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
9
|
/**
|
|
25
10
|
* @param {Array<{url: string, name: string, label?: string}>} socials
|
|
26
11
|
*/
|
|
@@ -32,6 +17,8 @@ function renderSocialLinks(socials) {
|
|
|
32
17
|
export const atlasNotFoundLayout = (pageData, data) => {
|
|
33
18
|
const homeLink = data.headerData.homeLink || '/';
|
|
34
19
|
const rocketLogo = data.headerData.logo[0];
|
|
20
|
+
const siteName = pageData.siteHeadMetadata?.siteName ?? pageData.title;
|
|
21
|
+
const headContent = data.headContent?.({ pageData });
|
|
35
22
|
|
|
36
23
|
return document(
|
|
37
24
|
pageData,
|
|
@@ -39,7 +26,7 @@ export const atlasNotFoundLayout = (pageData, data) => {
|
|
|
39
26
|
<div class="atlas-not-found">
|
|
40
27
|
<header class="atlas-not-found-header">
|
|
41
28
|
<a href=${homeLink} class="atlas-not-found-logo">
|
|
42
|
-
${renderHeaderLogo(data.headerData.logo)}
|
|
29
|
+
${renderHeaderLogo(data.headerData.logo, siteName)}
|
|
43
30
|
</a>
|
|
44
31
|
<nav class="atlas-not-found-links" aria-label="Project links">
|
|
45
32
|
${renderSocialLinks(data.headerData.socials)}
|
|
@@ -53,17 +40,20 @@ export const atlasNotFoundLayout = (pageData, data) => {
|
|
|
53
40
|
<div class="atlas-not-found-stars"></div>
|
|
54
41
|
<div class="atlas-not-found-orbit"></div>
|
|
55
42
|
<p class="atlas-not-found-code">404</p>
|
|
56
|
-
|
|
43
|
+
${rocketLogo
|
|
44
|
+
? html`<img class="atlas-not-found-rocket" src=${rocketLogo} alt="" />`
|
|
45
|
+
: html``}
|
|
57
46
|
</div>
|
|
58
47
|
</main>
|
|
59
48
|
</div>
|
|
60
49
|
`,
|
|
61
50
|
{
|
|
62
51
|
menu: false,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
52
|
+
headContent: html`<link
|
|
53
|
+
rel="stylesheet"
|
|
54
|
+
href="${resolve('@rocket/js/layouts/atlasNotFound.css', import.meta)}"
|
|
55
|
+
/>
|
|
56
|
+
${renderStylesheets(data.stylesheets)} ${headContent}`,
|
|
67
57
|
},
|
|
68
58
|
);
|
|
69
59
|
};
|
|
@@ -11,7 +11,7 @@ import { defaultHtmlMenu } from '../menu.js';
|
|
|
11
11
|
* @param {Object} [options]
|
|
12
12
|
* @param {LitHTML} [options.title]
|
|
13
13
|
* @param {'html' | false} [options.menu] render a default menu. set to false if you want your own
|
|
14
|
-
* @param {LitHTML} [options.
|
|
14
|
+
* @param {LitHTML} [options.headContent]
|
|
15
15
|
*/
|
|
16
16
|
export function document(
|
|
17
17
|
data,
|
|
@@ -19,7 +19,7 @@ export function document(
|
|
|
19
19
|
{
|
|
20
20
|
title = data.siteHeadMetadata?.title ?? data.title,
|
|
21
21
|
menu = 'html',
|
|
22
|
-
|
|
22
|
+
headContent = undefined,
|
|
23
23
|
} = {},
|
|
24
24
|
) {
|
|
25
25
|
const siteHeadMetadata = data.siteHeadMetadata;
|
|
@@ -40,12 +40,12 @@ export function document(
|
|
|
40
40
|
}
|
|
41
41
|
</style>`
|
|
42
42
|
: ''}
|
|
43
|
-
${data.clientCode} ${
|
|
43
|
+
${data.clientCode} ${headContent}
|
|
44
44
|
</head>
|
|
45
45
|
<body>
|
|
46
46
|
${menu
|
|
47
|
-
? html`<
|
|
48
|
-
<
|
|
47
|
+
? html`<nav id="menu" aria-label="Site">${defaultHtmlMenu(data.pageTree)}</nav>
|
|
48
|
+
<main id="content">${content}</main>`
|
|
49
49
|
: content}
|
|
50
50
|
</body>
|
|
51
51
|
</html>`;
|
package/src/layouts/layout.js
CHANGED
|
@@ -9,7 +9,7 @@ export const layout = data => {
|
|
|
9
9
|
addBootstrapIconLibrary(data);
|
|
10
10
|
return document(data, data.content, {
|
|
11
11
|
menu: 'html',
|
|
12
|
-
|
|
12
|
+
headContent: html`
|
|
13
13
|
<link
|
|
14
14
|
rel="stylesheet"
|
|
15
15
|
href="${resolve('@rocket/js/docs/assets/prism-one-light.css', import.meta)}"
|
|
@@ -27,7 +27,7 @@ export const singleDemoLayout = data => {
|
|
|
27
27
|
addBootstrapIconLibrary(data);
|
|
28
28
|
return document(data, data.content, {
|
|
29
29
|
menu: false,
|
|
30
|
-
|
|
30
|
+
headContent: html`
|
|
31
31
|
<link
|
|
32
32
|
rel="stylesheet"
|
|
33
33
|
href="${resolve('@awesome.me/webawesome/dist/styles/webawesome.css', import.meta)}"
|
|
@@ -92,6 +92,8 @@ function normalizeMarkdownPageContent(rawModule, { parseComponents }) {
|
|
|
92
92
|
*/
|
|
93
93
|
function hasBrowserLoadedComponents(components) {
|
|
94
94
|
return Object.values(components).some(
|
|
95
|
-
component =>
|
|
95
|
+
component =>
|
|
96
|
+
component.loading === 'client' ||
|
|
97
|
+
(typeof component.loading === 'string' && component.loading.startsWith('hydrate:')),
|
|
96
98
|
);
|
|
97
99
|
}
|
package/src/markdownCompiler.js
CHANGED
|
@@ -5,7 +5,7 @@ import rehypeRaw from 'rehype-raw';
|
|
|
5
5
|
import { unified } from 'unified';
|
|
6
6
|
import { visit } from 'unist-util-visit';
|
|
7
7
|
import { extractMdCode } from './extractCode.js';
|
|
8
|
-
import { mdToJs, mdToJsSingleDemo } from './transform.js';
|
|
8
|
+
import { isDemoCodeNode, mdToJs, mdToJsSingleDemo } from './transform.js';
|
|
9
9
|
import { init, parse as parseExports } from 'es-module-lexer';
|
|
10
10
|
import ts from 'typescript';
|
|
11
11
|
import { parseRequestDemoMetadata } from './requestDemoMetadata.js';
|
|
@@ -235,7 +235,7 @@ function extractDemoNames() {
|
|
|
235
235
|
/** @type {import('unist-util-visit').Visitor} */
|
|
236
236
|
const visitor = _node => {
|
|
237
237
|
const node = /** @type {import('mdast').Code} */ (_node);
|
|
238
|
-
if (node
|
|
238
|
+
if (isDemoCodeNode(node) && typeof node.value === 'string') {
|
|
239
239
|
for (const exported of parseExports(node.value)[1]) {
|
|
240
240
|
demoNames.push(exported.ln || exported.n);
|
|
241
241
|
}
|
package/src/markdownHook.js
CHANGED
|
@@ -102,7 +102,11 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
102
102
|
},
|
|
103
103
|
};
|
|
104
104
|
if (match[0] === 'Setup' && isLocalFile(url)) {
|
|
105
|
-
|
|
105
|
+
// Fire-and-forget: awaiting a reply here can deadlock. The main thread
|
|
106
|
+
// blocks in Atomics.wait during e.g. a nested module.register() call, so
|
|
107
|
+
// it may be unable to answer until this resolve returns. postMessage
|
|
108
|
+
// delivery is ordered, which is all the dependency tracking needs.
|
|
109
|
+
sendPort.postMessage({
|
|
106
110
|
parent: getPath(/** @type {string} */ (context.parentURL)),
|
|
107
111
|
url: getPath(resolve.url),
|
|
108
112
|
});
|
|
@@ -116,7 +120,8 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
116
120
|
...resolve.importAttributes,
|
|
117
121
|
type: 'cache' + lastReload.toString(36),
|
|
118
122
|
};
|
|
119
|
-
|
|
123
|
+
// Fire-and-forget, see above.
|
|
124
|
+
sendPort.postMessage({
|
|
120
125
|
parent: getPath(/** @type {string} */ (context.parentURL)),
|
|
121
126
|
url: getPath(resolve.url),
|
|
122
127
|
});
|