@rocket/js 0.2.1 → 0.3.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/dist-types/exports/adapters/cloudflare.d.ts +2 -0
- package/dist-types/exports/adapters/cloudflare.d.ts.map +1 -0
- package/dist-types/exports/types/rocket.d.ts +11 -0
- 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 +9 -0
- package/dist-types/src/PageData.d.ts.map +1 -1
- package/dist-types/src/RocketCodeBlock.d.ts.map +1 -1
- package/dist-types/src/RocketJsDemo.d.ts.map +1 -1
- package/dist-types/src/adapters/cloudflare.d.ts +27 -0
- package/dist-types/src/adapters/cloudflare.d.ts.map +1 -0
- package/dist-types/src/adapters/netlify.d.ts.map +1 -1
- package/dist-types/src/adapters/redirects.d.ts +14 -0
- package/dist-types/src/adapters/redirects.d.ts.map +1 -0
- package/dist-types/src/icons.d.ts +27 -0
- package/dist-types/src/icons.d.ts.map +1 -1
- package/dist-types/src/layouts/atlas/atlasBlogLayout.d.ts.map +1 -1
- 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.map +1 -1
- package/dist-types/src/markdownHook.d.ts.map +1 -1
- package/dist-types/src/menus/MainMenu.d.ts.map +1 -1
- package/dist-types/src/menus/RocketMenu.d.ts.map +1 -1
- package/dist-types/src/menus/RocketToc.d.ts.map +1 -1
- package/dist-types/src/menus/pageNavigation.d.ts.map +1 -1
- package/dist-types/src/publicAssets.d.ts.map +1 -1
- package/exports/adapters/cloudflare.js +1 -0
- package/exports/types/rocket.ts +17 -4
- package/exports/types.ts +1 -0
- package/package.json +40 -26
- package/src/PageData.js +15 -0
- package/src/RocketCodeBlock.js +11 -9
- package/src/RocketJsDemo.js +7 -5
- package/src/adapters/cloudflare.js +522 -0
- package/src/adapters/netlify.js +2 -24
- package/src/adapters/redirects.js +31 -0
- package/src/cli/RocketBuild.js +5 -2
- package/src/config.js +1 -1
- package/src/icons.js +138 -0
- package/src/layouts/atlas/atlasBlogLayout.js +45 -31
- package/src/layouts/atlas/atlasDocLayout.js +22 -16
- package/src/layouts/atlas/atlasHeroLayout.js +39 -31
- package/src/layouts/atlas/atlasNotFoundLayout.js +5 -3
- package/src/layouts/layout-helper.js +38 -26
- package/src/main.js +15 -0
- package/src/markdownCompiler.js +5 -1
- package/src/menus/MainMenu.js +17 -13
- package/src/menus/RocketMenu.js +25 -19
- package/src/menus/RocketToc.js +7 -5
- package/src/menus/pageNavigation.js +24 -10
- package/src/publicAssets.js +9 -2
- package/src/transform.js +7 -1
- package/src/wds-plugin.js +2 -1
package/src/icons.js
CHANGED
|
@@ -5,6 +5,7 @@ import { readFileSync } from 'node:fs';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import * as parse5 from 'parse5';
|
|
8
|
+
import { resolve } from './resolve.js';
|
|
8
9
|
|
|
9
10
|
const require = createRequire(import.meta.url);
|
|
10
11
|
|
|
@@ -13,6 +14,8 @@ const ICON_REFERENCE_CONFIG_FIELDS = new Set(['library', 'name']);
|
|
|
13
14
|
const ROCKET_ICON_ASSET_PREFIX = '/_rocket/icons/';
|
|
14
15
|
const ROCKET_ICON_DEFINE_MODULE_PATH = '/_rocket/rocket-icon.js';
|
|
15
16
|
const ROCKET_ICON_CLASS_MODULE_PATH = '/_rocket/RocketIcon.js';
|
|
17
|
+
const WEB_AWESOME_ICON_ASSET_PREFIX = '/_rocket/wa-icons/';
|
|
18
|
+
const WEB_AWESOME_ICON_LIBRARY_MODULE = '@awesome.me/webawesome/dist/components/icon/library.js';
|
|
16
19
|
const SHADOW_ICON_STYLE =
|
|
17
20
|
':host{display:inline-block;width:1em;height:1em;vertical-align:-0.125em;line-height:1}' +
|
|
18
21
|
':host([hidden]){display:none}' +
|
|
@@ -66,6 +69,52 @@ export class IconAssetStore {
|
|
|
66
69
|
/** @type {Map<string, { url: string; svg: string; library: string; name: string }>} */
|
|
67
70
|
this.assets = new Map();
|
|
68
71
|
this.needsRuntime = false;
|
|
72
|
+
/** @type {Map<string, { library: string; config: import('@rocket/js/types.js').NormalizedIconLibraryConfig }>} */
|
|
73
|
+
this.webAwesomeIconLibraries = new Map();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Publishes every icon of an Icon Library at `/_rocket/wa-icons/{library}/{name}.svg`, because
|
|
78
|
+
* browser code may ask `wa-icon` for any name.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} library
|
|
81
|
+
* @param {import('@rocket/js/types.js').NormalizedIconLibraryConfig} config
|
|
82
|
+
*/
|
|
83
|
+
addWebAwesomeIconLibrary(library, config) {
|
|
84
|
+
this.webAwesomeIconLibraries.set(sanitizePathSegment(library), { library, config });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {string} url
|
|
89
|
+
* @returns {Promise<{ url: string; svg: string } | undefined>}
|
|
90
|
+
*/
|
|
91
|
+
async getWebAwesomeIcon(url) {
|
|
92
|
+
const match = /^\/_rocket\/wa-icons\/([^/]+)\/([^/]+)\.svg$/.exec(url);
|
|
93
|
+
const entry = match && this.webAwesomeIconLibraries.get(match[1]);
|
|
94
|
+
if (!match || !entry) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
let name;
|
|
98
|
+
try {
|
|
99
|
+
name = decodeURIComponent(match[2]);
|
|
100
|
+
} catch {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const svg = (await indexIconLibrary(entry.library, entry.config)).get(name);
|
|
104
|
+
return svg === undefined ? undefined : { url, svg };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async webAwesomeIconOutputs() {
|
|
108
|
+
const outputs = [];
|
|
109
|
+
for (const [segment, { library, config }] of this.webAwesomeIconLibraries) {
|
|
110
|
+
for (const [name, svg] of await indexIconLibrary(library, config)) {
|
|
111
|
+
outputs.push({
|
|
112
|
+
url: `${WEB_AWESOME_ICON_ASSET_PREFIX}${segment}/${name}.svg`,
|
|
113
|
+
svg,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return outputs;
|
|
69
118
|
}
|
|
70
119
|
|
|
71
120
|
/**
|
|
@@ -177,6 +226,7 @@ export function validateIconLibrariesConfig(iconLibraries) {
|
|
|
177
226
|
* _iconLibraries?: Map<string, import('@rocket/js/types.js').NormalizedIconLibraryConfig>;
|
|
178
227
|
* _defaultIconLibrary?: string;
|
|
179
228
|
* _iconReferences?: import('@rocket/js/types.js').IconReferenceConfig[];
|
|
229
|
+
* _webAwesomeIconLibrary?: string;
|
|
180
230
|
* _hydrationScript?: string;
|
|
181
231
|
* _hasBrowserLoadedComponents?: boolean;
|
|
182
232
|
* };
|
|
@@ -185,6 +235,15 @@ export function validateIconLibrariesConfig(iconLibraries) {
|
|
|
185
235
|
* @returns {Promise<string>}
|
|
186
236
|
*/
|
|
187
237
|
export async function finalizeRocketIcons(html, options = {}) {
|
|
238
|
+
const output = await finalizeRocketIconHostsAndManifest(html, options);
|
|
239
|
+
return finalizeWebAwesomeIcons(output, options);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @param {string} html
|
|
244
|
+
* @param {Parameters<typeof finalizeRocketIcons>[1] & {}} options
|
|
245
|
+
*/
|
|
246
|
+
async function finalizeRocketIconHostsAndManifest(html, options) {
|
|
188
247
|
const lowerHtml = html.toLowerCase();
|
|
189
248
|
const hasIconHosts = lowerHtml.includes('<rocket-icon');
|
|
190
249
|
const hasIconLoadingPolicy =
|
|
@@ -261,6 +320,85 @@ export async function finalizeRocketIcons(html, options = {}) {
|
|
|
261
320
|
});
|
|
262
321
|
}
|
|
263
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Points Web Awesome's `default` icon library at the Page's Web Awesome Icon Library, so
|
|
325
|
+
* `wa-icon` elements created by browser code load self-hosted SVGs instead of a CDN.
|
|
326
|
+
*
|
|
327
|
+
* @param {string} html
|
|
328
|
+
* @param {Parameters<typeof finalizeRocketIcons>[1] & {}} options
|
|
329
|
+
*/
|
|
330
|
+
async function finalizeWebAwesomeIcons(html, options) {
|
|
331
|
+
const library = options.pageData?._webAwesomeIconLibrary;
|
|
332
|
+
if (!library) {
|
|
333
|
+
return html;
|
|
334
|
+
}
|
|
335
|
+
const resolver = createIconResolver({
|
|
336
|
+
layoutIconLibraries: options.layoutIconLibraries || options.pageData?._iconLibraries,
|
|
337
|
+
layoutDefaultIconLibrary:
|
|
338
|
+
options.layoutDefaultIconLibrary || options.pageData?._defaultIconLibrary,
|
|
339
|
+
projectIconLibraries: options.iconLibraries,
|
|
340
|
+
projectDefaultIconLibrary: options.defaultIconLibrary,
|
|
341
|
+
});
|
|
342
|
+
const config = resolver.libraries.get(library);
|
|
343
|
+
if (!config) {
|
|
344
|
+
throw new Error(`Web Awesome Icon Library "${library}" is not configured.`);
|
|
345
|
+
}
|
|
346
|
+
options.iconAssetStore?.addWebAwesomeIconLibrary(library, config);
|
|
347
|
+
|
|
348
|
+
const iconBaseUrl = `${WEB_AWESOME_ICON_ASSET_PREFIX}${sanitizePathSegment(library)}/`;
|
|
349
|
+
const registrationHtml =
|
|
350
|
+
'<script type="module" data-rocket-wa-icon-library>' +
|
|
351
|
+
`import { registerIconLibrary } from '${resolve(WEB_AWESOME_ICON_LIBRARY_MODULE, import.meta)}';` +
|
|
352
|
+
`registerIconLibrary('default', { resolver: name => '${iconBaseUrl}' + encodeURIComponent(name) + '.svg' });` +
|
|
353
|
+
'</script>';
|
|
354
|
+
return insertWebAwesomeIconRegistration(html, registrationHtml);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Places the registration after every import map, because browsers ignore or restrict an import
|
|
359
|
+
* map that follows a module script. Otherwise it goes before the Page's first head script: module
|
|
360
|
+
* scripts run in document order, so it runs before component code. Scripts inside HTML comments
|
|
361
|
+
* are ignored.
|
|
362
|
+
*
|
|
363
|
+
* @param {string} html
|
|
364
|
+
* @param {string} insertion
|
|
365
|
+
*/
|
|
366
|
+
function insertWebAwesomeIconRegistration(html, insertion) {
|
|
367
|
+
const scanHtml = html
|
|
368
|
+
.replace(/<!--[\s\S]*?(?:-->|$)/g, comment => ' '.repeat(comment.length))
|
|
369
|
+
.toLowerCase();
|
|
370
|
+
const headClose = scanHtml.indexOf('</head>');
|
|
371
|
+
/** @type {number[]} */
|
|
372
|
+
const scriptStarts = [];
|
|
373
|
+
let afterImportMaps = 0;
|
|
374
|
+
const scriptOpen = /<script(?=[\s>/])[^>]*>/g;
|
|
375
|
+
let match;
|
|
376
|
+
while ((match = scriptOpen.exec(scanHtml))) {
|
|
377
|
+
const close = scanHtml.indexOf('</script', scriptOpen.lastIndex);
|
|
378
|
+
const closeEnd = close === -1 ? -1 : scanHtml.indexOf('>', close);
|
|
379
|
+
const end = closeEnd === -1 ? scanHtml.length : closeEnd + 1;
|
|
380
|
+
if (/\btype\s*=\s*["']?importmap["'\s/>]/.test(match[0])) {
|
|
381
|
+
afterImportMaps = end;
|
|
382
|
+
} else {
|
|
383
|
+
scriptStarts.push(match.index);
|
|
384
|
+
}
|
|
385
|
+
scriptOpen.lastIndex = end;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const firstHeadScript = scriptStarts.find(
|
|
389
|
+
start => start >= afterImportMaps && (headClose === -1 || start < headClose),
|
|
390
|
+
);
|
|
391
|
+
let index;
|
|
392
|
+
if (firstHeadScript !== undefined) {
|
|
393
|
+
index = firstHeadScript;
|
|
394
|
+
} else if (headClose !== -1 && headClose >= afterImportMaps) {
|
|
395
|
+
index = headClose;
|
|
396
|
+
} else {
|
|
397
|
+
index = afterImportMaps;
|
|
398
|
+
}
|
|
399
|
+
return html.slice(0, index) + insertion + html.slice(index);
|
|
400
|
+
}
|
|
401
|
+
|
|
264
402
|
/**
|
|
265
403
|
* @param {unknown} iconLibraries
|
|
266
404
|
* @param {string} owner
|
|
@@ -53,9 +53,11 @@ export function renderBlogTags(tags, data) {
|
|
|
53
53
|
${tags.map(
|
|
54
54
|
tag => html`
|
|
55
55
|
<li>
|
|
56
|
-
${
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
${
|
|
57
|
+
data.tagPathPrefix
|
|
58
|
+
? html`<a href=${blogTagPath(data.tagPathPrefix, tag)} rel="tag">${tag}</a>`
|
|
59
|
+
: html`<span>${tag}</span>`
|
|
60
|
+
}
|
|
59
61
|
</li>
|
|
60
62
|
`,
|
|
61
63
|
)}
|
|
@@ -84,9 +86,11 @@ export function renderBlogByline(metadata, data, language) {
|
|
|
84
86
|
}
|
|
85
87
|
return html`
|
|
86
88
|
<div class="atlas-blog-byline">
|
|
87
|
-
${
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
${
|
|
90
|
+
metadata.date
|
|
91
|
+
? html`<time datetime=${metadata.date}>${formatBlogDate(metadata.date, language)}</time>`
|
|
92
|
+
: ''
|
|
93
|
+
}
|
|
90
94
|
${authors.length ? html`<span class="atlas-blog-authors">${authors.join(', ')}</span>` : ''}
|
|
91
95
|
${renderBlogTags(metadata.tags, data)}
|
|
92
96
|
</div>
|
|
@@ -108,11 +112,13 @@ export function renderBlogPostList(items, data, language) {
|
|
|
108
112
|
item => html`
|
|
109
113
|
<li class="atlas-blog-post-card">
|
|
110
114
|
<h2><a href=${item.url}>${item.metadata.title}</a></h2>
|
|
111
|
-
${
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
${
|
|
116
|
+
item.metadata.date
|
|
117
|
+
? html`<time datetime=${item.metadata.date}
|
|
118
|
+
>${formatBlogDate(item.metadata.date, language)}</time
|
|
119
|
+
>`
|
|
120
|
+
: ''
|
|
121
|
+
}
|
|
116
122
|
${item.metadata.description ? html`<p>${item.metadata.description}</p>` : ''}
|
|
117
123
|
${renderBlogTags(item.metadata.tags, data)}
|
|
118
124
|
</li>
|
|
@@ -131,13 +137,17 @@ export function renderBlogPagination(pagination) {
|
|
|
131
137
|
}
|
|
132
138
|
return html`
|
|
133
139
|
<nav class="atlas-blog-pagination" aria-label="Blog pages">
|
|
134
|
-
${
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
${
|
|
141
|
+
pagination.previousPath
|
|
142
|
+
? html`<a href=${pagination.previousPath} rel="prev">Newer posts</a>`
|
|
143
|
+
: html`<span></span>`
|
|
144
|
+
}
|
|
137
145
|
<span>Page ${pagination.currentPage} of ${pagination.totalPages}</span>
|
|
138
|
-
${
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
${
|
|
147
|
+
pagination.nextPath
|
|
148
|
+
? html`<a href=${pagination.nextPath} rel="next">Older posts</a>`
|
|
149
|
+
: html`<span></span>`
|
|
150
|
+
}
|
|
141
151
|
</nav>
|
|
142
152
|
`;
|
|
143
153
|
}
|
|
@@ -181,14 +191,16 @@ function atlasBlogDocument(pageData, data, mainContent) {
|
|
|
181
191
|
/>
|
|
182
192
|
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasDoc.css', import.meta)}" />
|
|
183
193
|
<link rel="stylesheet" href="${resolve('@rocket/js/layouts/atlasBlog.css', import.meta)}" />
|
|
184
|
-
${
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
194
|
+
${
|
|
195
|
+
data.feedPath
|
|
196
|
+
? html`<link
|
|
197
|
+
rel="alternate"
|
|
198
|
+
type="application/atom+xml"
|
|
199
|
+
href=${data.feedPath}
|
|
200
|
+
title=${siteName}
|
|
201
|
+
/>`
|
|
202
|
+
: ''
|
|
203
|
+
}
|
|
192
204
|
${renderStylesheets(data.stylesheets)} ${headContent}
|
|
193
205
|
`,
|
|
194
206
|
},
|
|
@@ -220,12 +232,14 @@ export const atlasBlogIndexLayout = (pageData, data) => {
|
|
|
220
232
|
<section class="atlas-blog-index">
|
|
221
233
|
<div class="atlas-blog-intro">
|
|
222
234
|
${pageData.content}
|
|
223
|
-
${
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
235
|
+
${
|
|
236
|
+
data.feedPath
|
|
237
|
+
? html`<a class="atlas-blog-feed-link" href=${data.feedPath}>
|
|
238
|
+
<rocket-icon library="bootstrap" name="rss" aria-hidden="true"></rocket-icon>
|
|
239
|
+
Feed
|
|
240
|
+
</a>`
|
|
241
|
+
: ''
|
|
242
|
+
}
|
|
229
243
|
</div>
|
|
230
244
|
${renderBlogPostList(items, data, language)} ${renderBlogPagination(pageData.pagination)}
|
|
231
245
|
</section>
|
|
@@ -245,22 +245,28 @@ export const atlasDocLayout = (pageData, data) => {
|
|
|
245
245
|
|
|
246
246
|
<main id="content" class="atlas-content">${pageData.content}</main>
|
|
247
247
|
|
|
248
|
-
${
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
248
|
+
${
|
|
249
|
+
pageNavigation.previous || pageNavigation.next
|
|
250
|
+
? html`<nav id="prev-next" slot="main-footer" class="atlas-prev-next" aria-label="Page">
|
|
251
|
+
${
|
|
252
|
+
pageNavigation.previous
|
|
253
|
+
? html`<rocket-previous-page
|
|
254
|
+
.pageTree=${pageData.pageTree}
|
|
255
|
+
.currentPath=${pageData.url}
|
|
256
|
+
></rocket-previous-page>`
|
|
257
|
+
: ''
|
|
258
|
+
}
|
|
259
|
+
${
|
|
260
|
+
pageNavigation.next
|
|
261
|
+
? html`<rocket-next-page
|
|
262
|
+
.pageTree=${pageData.pageTree}
|
|
263
|
+
.currentPath=${pageData.url}
|
|
264
|
+
></rocket-next-page>`
|
|
265
|
+
: ''
|
|
266
|
+
}
|
|
267
|
+
</nav>`
|
|
268
|
+
: ''
|
|
269
|
+
}
|
|
264
270
|
|
|
265
271
|
<aside slot="aside" class="atlas-toc">
|
|
266
272
|
<rocket-toc toc=${serializedToc}></rocket-toc>
|
|
@@ -69,16 +69,18 @@ function renderTrustBadges(badges) {
|
|
|
69
69
|
|
|
70
70
|
return html`
|
|
71
71
|
<li>
|
|
72
|
-
${
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
${
|
|
73
|
+
href && icon
|
|
74
|
+
? html`
|
|
75
|
+
<rocket-social-link
|
|
76
|
+
url=${href}
|
|
77
|
+
name=${icon}
|
|
78
|
+
label=${text}
|
|
79
|
+
aria-label=${text}
|
|
80
|
+
></rocket-social-link>
|
|
81
|
+
`
|
|
82
|
+
: html`<span class="trust-badge-text">${text}</span>`
|
|
83
|
+
}
|
|
82
84
|
</li>
|
|
83
85
|
`;
|
|
84
86
|
})}
|
|
@@ -142,13 +144,15 @@ function renderWhyCard(card) {
|
|
|
142
144
|
<h3>${card.title}</h3>
|
|
143
145
|
<p>${card.description}</p>
|
|
144
146
|
</div>
|
|
145
|
-
${
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
${card.tags
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
${
|
|
148
|
+
card.tags?.length
|
|
149
|
+
? html`
|
|
150
|
+
<ul class="tag-list" aria-label="${card.title} tags">
|
|
151
|
+
${card.tags.map(tag => html`<li>${tag}</li>`)}
|
|
152
|
+
</ul>
|
|
153
|
+
`
|
|
154
|
+
: html``
|
|
155
|
+
}
|
|
152
156
|
</article>
|
|
153
157
|
`;
|
|
154
158
|
}
|
|
@@ -303,25 +307,29 @@ export const atlasHeroLayout = (pageData, data) => {
|
|
|
303
307
|
${renderInstallPill(hero)} ${renderTrustBadges(hero.badges ?? [])}
|
|
304
308
|
</div>
|
|
305
309
|
|
|
306
|
-
${
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
<div class="
|
|
310
|
-
<
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
${
|
|
311
|
+
hero.logoNoText
|
|
312
|
+
? html`
|
|
313
|
+
<div class="hero-art" aria-hidden="true">
|
|
314
|
+
<div class="rocket-visual">
|
|
315
|
+
<span class="spark spark-one"></span>
|
|
316
|
+
<span class="spark spark-two"></span>
|
|
317
|
+
<span class="spark spark-three"></span>
|
|
318
|
+
<img src=${hero.logoNoText} alt="" width="370" />
|
|
319
|
+
</div>
|
|
314
320
|
</div>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
321
|
+
`
|
|
322
|
+
: html``
|
|
323
|
+
}
|
|
318
324
|
</section>
|
|
319
325
|
<div class="home-content">${pageData.content}</div>
|
|
320
326
|
${renderWhyRocket(data.whyRocketData)}
|
|
321
327
|
${renderHomeColumns(data.quickStartData, data.workflowData)}
|
|
322
|
-
${
|
|
323
|
-
|
|
324
|
-
|
|
328
|
+
${
|
|
329
|
+
data.featuresData?.length
|
|
330
|
+
? html`<rocket-feature-list .features=${data.featuresData}></rocket-feature-list>`
|
|
331
|
+
: html``
|
|
332
|
+
}
|
|
325
333
|
</main>
|
|
326
334
|
<rocket-footer .data=${data.footerData}></rocket-footer>
|
|
327
335
|
`,
|
|
@@ -40,9 +40,11 @@ export const atlasNotFoundLayout = (pageData, data) => {
|
|
|
40
40
|
<div class="atlas-not-found-stars"></div>
|
|
41
41
|
<div class="atlas-not-found-orbit"></div>
|
|
42
42
|
<p class="atlas-not-found-code">404</p>
|
|
43
|
-
${
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
${
|
|
44
|
+
rocketLogo
|
|
45
|
+
? html`<img class="atlas-not-found-rocket" src=${rocketLogo} alt="" />`
|
|
46
|
+
: html``
|
|
47
|
+
}
|
|
46
48
|
</div>
|
|
47
49
|
</main>
|
|
48
50
|
</div>
|
|
@@ -30,23 +30,27 @@ export function document(
|
|
|
30
30
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
31
31
|
<title>${title}</title>
|
|
32
32
|
${siteHeadMetadataTemplate(siteHeadMetadata)}
|
|
33
|
-
${
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
${
|
|
34
|
+
menu
|
|
35
|
+
? html`<style>
|
|
36
|
+
body {
|
|
37
|
+
display: flex;
|
|
38
|
+
}
|
|
39
|
+
#menu {
|
|
40
|
+
margin-right: 1em;
|
|
41
|
+
}
|
|
42
|
+
</style>`
|
|
43
|
+
: ''
|
|
44
|
+
}
|
|
43
45
|
${data.clientCode} ${headContent}
|
|
44
46
|
</head>
|
|
45
47
|
<body>
|
|
46
|
-
${
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
${
|
|
49
|
+
menu
|
|
50
|
+
? html`<nav id="menu" aria-label="Site">${defaultHtmlMenu(data.pageTree)}</nav>
|
|
51
|
+
<main id="content">${content}</main>`
|
|
52
|
+
: content
|
|
53
|
+
}
|
|
50
54
|
</body>
|
|
51
55
|
</html>`;
|
|
52
56
|
}
|
|
@@ -63,21 +67,27 @@ function siteHeadMetadataTemplate(metadata) {
|
|
|
63
67
|
${metadata.indexing === 'noindex' ? html`<meta name="robots" content="noindex" />` : ''}
|
|
64
68
|
<link rel="canonical" href=${metadata.canonicalUrl} />
|
|
65
69
|
${metadata.icons?.ico ? html`<link rel="icon" href=${metadata.icons.ico} sizes="any" />` : ''}
|
|
66
|
-
${
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
${
|
|
71
|
+
metadata.icons?.svg
|
|
72
|
+
? html`<link rel="icon" href=${metadata.icons.svg} type="image/svg+xml" />`
|
|
73
|
+
: ''
|
|
74
|
+
}
|
|
75
|
+
${
|
|
76
|
+
metadata.icons?.appleTouchIcon
|
|
77
|
+
? html`<link rel="apple-touch-icon" href=${metadata.icons.appleTouchIcon} />`
|
|
78
|
+
: ''
|
|
79
|
+
}
|
|
72
80
|
${metadata.themeColor ? html`<meta name="theme-color" content=${metadata.themeColor} />` : ''}
|
|
73
81
|
<meta property="og:site_name" content=${metadata.siteName} />
|
|
74
82
|
<meta property="og:title" content=${metadata.title} />
|
|
75
83
|
<meta property="og:description" content=${metadata.description} />
|
|
76
84
|
<meta property="og:url" content=${metadata.canonicalUrl} />
|
|
77
85
|
<meta property="og:type" content="website" />
|
|
78
|
-
${
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
${
|
|
87
|
+
metadata.socialPreview?.image
|
|
88
|
+
? html`<meta property="og:image" content=${metadata.socialPreview.image} />`
|
|
89
|
+
: ''
|
|
90
|
+
}
|
|
81
91
|
<meta
|
|
82
92
|
name="twitter:card"
|
|
83
93
|
content=${metadata.socialPreview?.image ? 'summary_large_image' : 'summary'}
|
|
@@ -85,8 +95,10 @@ function siteHeadMetadataTemplate(metadata) {
|
|
|
85
95
|
<meta name="twitter:title" content=${metadata.title} />
|
|
86
96
|
<meta name="twitter:description" content=${metadata.description} />
|
|
87
97
|
<meta name="twitter:url" content=${metadata.canonicalUrl} />
|
|
88
|
-
${
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
${
|
|
99
|
+
metadata.socialPreview?.image
|
|
100
|
+
? html`<meta name="twitter:image" content=${metadata.socialPreview.image} />`
|
|
101
|
+
: ''
|
|
102
|
+
}
|
|
91
103
|
`;
|
|
92
104
|
}
|
package/src/main.js
CHANGED
|
@@ -6,6 +6,7 @@ import { MessageChannel } from 'node:worker_threads';
|
|
|
6
6
|
import { customElements } from '@lit-labs/ssr-dom-shim';
|
|
7
7
|
import { readConfig } from './config.js';
|
|
8
8
|
import { preferProjectPackagesPlugin } from './prefer-project-packages-plugin.js';
|
|
9
|
+
import { getPages } from './pages.js';
|
|
9
10
|
|
|
10
11
|
const configFilePath = process.argv[2] || undefined;
|
|
11
12
|
const startOptions = readStartOptions(process.argv[3]);
|
|
@@ -49,6 +50,20 @@ let devServerConfig = {
|
|
|
49
50
|
port: startOptions.port ?? 8888,
|
|
50
51
|
};
|
|
51
52
|
|
|
53
|
+
if (config.adapter?.adjustDevServerConfig) {
|
|
54
|
+
try {
|
|
55
|
+
devServerConfig = await config.adapter.adjustDevServerConfig(devServerConfig, {
|
|
56
|
+
pages: await getPages(process.cwd(), config.includeGlobs, config.excludeRegex),
|
|
57
|
+
projectRoot: process.cwd(),
|
|
58
|
+
config,
|
|
59
|
+
});
|
|
60
|
+
} catch (error) {
|
|
61
|
+
// Adapter startup checks are author-facing, so show the message like the CLI does.
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
console.error(error instanceof Error && !process.env.ROCKET_DEBUG ? error.message : error);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
52
67
|
devServerConfig = config.adjustDevServerConfig(devServerConfig);
|
|
53
68
|
|
|
54
69
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
package/src/markdownCompiler.js
CHANGED
|
@@ -237,7 +237,11 @@ function extractDemoNames() {
|
|
|
237
237
|
const node = /** @type {import('mdast').Code} */ (_node);
|
|
238
238
|
if (isDemoCodeNode(node) && typeof node.value === 'string') {
|
|
239
239
|
for (const exported of parseExports(node.value)[1]) {
|
|
240
|
-
|
|
240
|
+
if (exported.type === 'direct') {
|
|
241
|
+
demoNames.push(exported.localName || exported.name);
|
|
242
|
+
} else if (exported.type === 'reexport') {
|
|
243
|
+
demoNames.push(exported.name);
|
|
244
|
+
}
|
|
241
245
|
}
|
|
242
246
|
}
|
|
243
247
|
};
|
package/src/menus/MainMenu.js
CHANGED
|
@@ -39,19 +39,23 @@ export class MainMenu extends LitElement {
|
|
|
39
39
|
classes[level] = true;
|
|
40
40
|
return html`
|
|
41
41
|
<li>
|
|
42
|
-
${
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
${
|
|
43
|
+
page.menuNoLink
|
|
44
|
+
? html`<span class=${classMap(classes)}>${title}</span>`
|
|
45
|
+
: html`<a
|
|
46
|
+
href=${ifDefined(page.url)}
|
|
47
|
+
class=${classMap(classes)}
|
|
48
|
+
aria-current=${ifDefined(isCurrent ? 'page' : undefined)}
|
|
49
|
+
>${title}</a
|
|
50
|
+
>`
|
|
51
|
+
}
|
|
52
|
+
${
|
|
53
|
+
page.children.length > 0
|
|
54
|
+
? html`<ul>
|
|
55
|
+
${page.children.map(child => this.list(child, depth + 1))}
|
|
56
|
+
</ul>`
|
|
57
|
+
: ''
|
|
58
|
+
}
|
|
55
59
|
</li>
|
|
56
60
|
`;
|
|
57
61
|
}
|