@rocket/js 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +233 -2
- package/dist-types/exports/MainMenu.d.ts +2 -0
- package/dist-types/exports/MainMenu.d.ts.map +1 -0
- package/dist-types/exports/PageData.d.ts +2 -0
- package/dist-types/exports/PageData.d.ts.map +1 -0
- package/dist-types/exports/RocketCodeBlock.d.ts +2 -0
- package/dist-types/exports/RocketCodeBlock.d.ts.map +1 -0
- package/dist-types/exports/RocketIcon.d.ts +2 -0
- package/dist-types/exports/RocketIcon.d.ts.map +1 -0
- package/dist-types/exports/RocketJsDemo.d.ts +2 -0
- package/dist-types/exports/RocketJsDemo.d.ts.map +1 -0
- package/dist-types/exports/RocketRequestDemo.d.ts +2 -0
- package/dist-types/exports/RocketRequestDemo.d.ts.map +1 -0
- package/dist-types/exports/SocialPreviewPlayground.d.ts +2 -0
- package/dist-types/exports/SocialPreviewPlayground.d.ts.map +1 -0
- package/dist-types/exports/adapters/netlify.d.ts +2 -0
- package/dist-types/exports/adapters/netlify.d.ts.map +1 -0
- package/dist-types/exports/asyncMessage.d.ts +2 -0
- package/dist-types/exports/asyncMessage.d.ts.map +1 -0
- package/dist-types/exports/component-hydration.d.ts +2 -0
- package/dist-types/exports/component-hydration.d.ts.map +1 -0
- package/dist-types/exports/components/web-awesome.d.ts +3 -0
- package/dist-types/exports/components/web-awesome.d.ts.map +1 -0
- package/dist-types/exports/components.d.ts +2 -0
- package/dist-types/exports/components.d.ts.map +1 -0
- package/dist-types/exports/config.d.ts +2 -0
- package/dist-types/exports/config.d.ts.map +1 -0
- package/dist-types/exports/debounce.d.ts +2 -0
- package/dist-types/exports/debounce.d.ts.map +1 -0
- package/dist-types/exports/define/RocketCodeBlock.d.ts +2 -0
- package/dist-types/exports/define/RocketCodeBlock.d.ts.map +1 -0
- package/dist-types/exports/define/RocketIcon.d.ts +2 -0
- package/dist-types/exports/define/RocketIcon.d.ts.map +1 -0
- package/dist-types/exports/define/RocketJsDemo.d.ts +2 -0
- package/dist-types/exports/define/RocketJsDemo.d.ts.map +1 -0
- package/dist-types/exports/define/RocketRequestDemo.d.ts +2 -0
- package/dist-types/exports/define/RocketRequestDemo.d.ts.map +1 -0
- package/dist-types/exports/define/menus.d.ts +2 -0
- package/dist-types/exports/define/menus.d.ts.map +1 -0
- package/dist-types/exports/extractCode.d.ts +2 -0
- package/dist-types/exports/extractCode.d.ts.map +1 -0
- package/dist-types/exports/globalData.d.ts +2 -0
- package/dist-types/exports/globalData.d.ts.map +1 -0
- package/dist-types/exports/hydration/hydrationLoader.d.ts +2 -0
- package/dist-types/exports/hydration/hydrationLoader.d.ts.map +1 -0
- package/dist-types/exports/icons.d.ts +2 -0
- package/dist-types/exports/icons.d.ts.map +1 -0
- package/dist-types/exports/layout-helper.d.ts +2 -0
- package/dist-types/exports/layout-helper.d.ts.map +1 -0
- package/dist-types/exports/layout.d.ts +2 -0
- package/dist-types/exports/layout.d.ts.map +1 -0
- package/dist-types/exports/layouts/atlasDoc.d.ts +2 -0
- package/dist-types/exports/layouts/atlasDoc.d.ts.map +1 -0
- package/dist-types/exports/layouts/atlasHero.d.ts +2 -0
- package/dist-types/exports/layouts/atlasHero.d.ts.map +1 -0
- package/dist-types/exports/layouts/atlasNotFound.d.ts +2 -0
- package/dist-types/exports/layouts/atlasNotFound.d.ts.map +1 -0
- package/dist-types/exports/loaded-page-module.d.ts +2 -0
- package/dist-types/exports/loaded-page-module.d.ts.map +1 -0
- package/dist-types/exports/markdownHook.d.ts +2 -0
- package/dist-types/exports/markdownHook.d.ts.map +1 -0
- package/dist-types/exports/menu.d.ts +2 -0
- package/dist-types/exports/menu.d.ts.map +1 -0
- package/dist-types/exports/menus.d.ts +6 -0
- package/dist-types/exports/menus.d.ts.map +1 -0
- package/dist-types/exports/page-runtime.d.ts +2 -0
- package/dist-types/exports/page-runtime.d.ts.map +1 -0
- package/dist-types/exports/pages.d.ts +2 -0
- package/dist-types/exports/pages.d.ts.map +1 -0
- package/dist-types/exports/resolve.d.ts +2 -0
- package/dist-types/exports/resolve.d.ts.map +1 -0
- package/dist-types/exports/ssr.d.ts +2 -0
- package/dist-types/exports/ssr.d.ts.map +1 -0
- package/dist-types/exports/standalone-demo-url.d.ts +2 -0
- package/dist-types/exports/standalone-demo-url.d.ts.map +1 -0
- package/dist-types/exports/transform.d.ts +2 -0
- package/dist-types/exports/transform.d.ts.map +1 -0
- package/dist-types/exports/types/hydration.d.ts +23 -0
- package/dist-types/exports/types/hydration.d.ts.map +1 -0
- package/dist-types/exports/types/rocket.d.ts +504 -0
- package/dist-types/exports/types/rocket.d.ts.map +1 -0
- package/dist-types/exports/types.d.ts +3 -0
- package/dist-types/exports/types.d.ts.map +1 -0
- package/dist-types/exports/wds-plugin.d.ts +2 -0
- package/dist-types/exports/wds-plugin.d.ts.map +1 -0
- package/dist-types/src/PageData.d.ts +82 -0
- package/dist-types/src/PageData.d.ts.map +1 -0
- package/dist-types/src/RocketCodeBlock.d.ts +64 -0
- package/dist-types/src/RocketCodeBlock.d.ts.map +1 -0
- package/dist-types/src/RocketIcon.d.ts +35 -0
- package/dist-types/src/RocketIcon.d.ts.map +1 -0
- package/dist-types/src/RocketJsDemo.d.ts +59 -0
- package/dist-types/src/RocketJsDemo.d.ts.map +1 -0
- package/dist-types/src/RocketJsDemo.test-browser.d.ts +3 -0
- package/dist-types/src/RocketJsDemo.test-browser.d.ts.map +1 -0
- package/dist-types/src/RocketRequestDemo.d.ts +57 -0
- package/dist-types/src/RocketRequestDemo.d.ts.map +1 -0
- package/dist-types/src/RocketRequestDemo.test-browser.d.ts +3 -0
- package/dist-types/src/RocketRequestDemo.test-browser.d.ts.map +1 -0
- package/dist-types/src/SocialPreviewPlayground.d.ts +102 -0
- package/dist-types/src/SocialPreviewPlayground.d.ts.map +1 -0
- package/dist-types/src/adapters/netlify.d.ts +54 -0
- package/dist-types/src/adapters/netlify.d.ts.map +1 -0
- package/dist-types/src/asyncMessage.d.ts +14 -0
- package/dist-types/src/asyncMessage.d.ts.map +1 -0
- package/dist-types/src/cli/RocketBuild.d.ts +78 -0
- package/dist-types/src/cli/RocketBuild.d.ts.map +1 -0
- package/dist-types/src/cli/RocketCli.d.ts +17 -0
- package/dist-types/src/cli/RocketCli.d.ts.map +1 -0
- package/dist-types/src/cli/RocketInit.d.ts +22 -0
- package/dist-types/src/cli/RocketInit.d.ts.map +1 -0
- package/dist-types/src/cli/RocketStart.d.ts +45 -0
- package/dist-types/src/cli/RocketStart.d.ts.map +1 -0
- package/dist-types/src/cli/cli.d.ts +3 -0
- package/dist-types/src/cli/cli.d.ts.map +1 -0
- package/dist-types/src/component-hydration.d.ts +26 -0
- package/dist-types/src/component-hydration.d.ts.map +1 -0
- package/dist-types/src/components/FeatureList.d.ts +15 -0
- package/dist-types/src/components/FeatureList.d.ts.map +1 -0
- package/dist-types/src/components/Footer.d.ts +17 -0
- package/dist-types/src/components/Footer.d.ts.map +1 -0
- package/dist-types/src/components/Header.d.ts +6 -0
- package/dist-types/src/components/Header.d.ts.map +1 -0
- package/dist-types/src/components/RocketDrawer.d.ts +20 -0
- package/dist-types/src/components/RocketDrawer.d.ts.map +1 -0
- package/dist-types/src/components/RocketSocialLink.d.ts +30 -0
- package/dist-types/src/components/RocketSocialLink.d.ts.map +1 -0
- package/dist-types/src/components.d.ts +7 -0
- package/dist-types/src/components.d.ts.map +1 -0
- package/dist-types/src/config.d.ts +6 -0
- package/dist-types/src/config.d.ts.map +1 -0
- package/dist-types/src/debounce.d.ts +8 -0
- package/dist-types/src/debounce.d.ts.map +1 -0
- package/dist-types/src/defaultSocialPreviewTemplate.d.ts +31 -0
- package/dist-types/src/defaultSocialPreviewTemplate.d.ts.map +1 -0
- package/dist-types/src/development-page-module-loader.d.ts +15 -0
- package/dist-types/src/development-page-module-loader.d.ts.map +1 -0
- package/dist-types/src/extractCode.d.ts +5 -0
- package/dist-types/src/extractCode.d.ts.map +1 -0
- package/dist-types/src/hydration/evaluate.d.ts +20 -0
- package/dist-types/src/hydration/evaluate.d.ts.map +1 -0
- package/dist-types/src/hydration/extractStrategies.d.ts +5 -0
- package/dist-types/src/hydration/extractStrategies.d.ts.map +1 -0
- package/dist-types/src/hydration/hydrationLoader.d.ts +64 -0
- package/dist-types/src/hydration/hydrationLoader.d.ts.map +1 -0
- package/dist-types/src/icons.d.ts +182 -0
- package/dist-types/src/icons.d.ts.map +1 -0
- package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts +45 -0
- package/dist-types/src/layouts/atlas/atlasDocLayout.d.ts.map +1 -0
- package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts +7 -0
- package/dist-types/src/layouts/atlas/atlasHeroLayout.d.ts.map +1 -0
- package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts +5 -0
- package/dist-types/src/layouts/atlas/atlasNotFoundLayout.d.ts.map +1 -0
- package/dist-types/src/layouts/layout-helper.d.ts +16 -0
- package/dist-types/src/layouts/layout-helper.d.ts.map +1 -0
- package/dist-types/src/layouts/layout.d.ts +7 -0
- package/dist-types/src/layouts/layout.d.ts.map +1 -0
- package/dist-types/src/loaded-page-module.d.ts +51 -0
- package/dist-types/src/loaded-page-module.d.ts.map +1 -0
- package/dist-types/src/main.d.ts +2 -0
- package/dist-types/src/main.d.ts.map +1 -0
- package/dist-types/src/markdownCompiler.d.ts +22 -0
- package/dist-types/src/markdownCompiler.d.ts.map +1 -0
- package/dist-types/src/markdownHook.d.ts +6 -0
- package/dist-types/src/markdownHook.d.ts.map +1 -0
- package/dist-types/src/menu.d.ts +22 -0
- package/dist-types/src/menu.d.ts.map +1 -0
- package/dist-types/src/menus/MainMenu.d.ts +23 -0
- package/dist-types/src/menus/MainMenu.d.ts.map +1 -0
- package/dist-types/src/menus/RocketMenu.d.ts +23 -0
- package/dist-types/src/menus/RocketMenu.d.ts.map +1 -0
- package/dist-types/src/menus/RocketNextPage.d.ts +18 -0
- package/dist-types/src/menus/RocketNextPage.d.ts.map +1 -0
- package/dist-types/src/menus/RocketPreviousPage.d.ts +18 -0
- package/dist-types/src/menus/RocketPreviousPage.d.ts.map +1 -0
- package/dist-types/src/menus/RocketToc.d.ts +54 -0
- package/dist-types/src/menus/RocketToc.d.ts.map +1 -0
- package/dist-types/src/menus/pageNavigation.d.ts +41 -0
- package/dist-types/src/menus/pageNavigation.d.ts.map +1 -0
- package/dist-types/src/page-pagination.d.ts +69 -0
- package/dist-types/src/page-pagination.d.ts.map +1 -0
- package/dist-types/src/page-runtime.d.ts +110 -0
- package/dist-types/src/page-runtime.d.ts.map +1 -0
- package/dist-types/src/pages.d.ts +10 -0
- package/dist-types/src/pages.d.ts.map +1 -0
- package/dist-types/src/publicAssets.d.ts +70 -0
- package/dist-types/src/publicAssets.d.ts.map +1 -0
- package/dist-types/src/requestDemoMetadata.d.ts +19 -0
- package/dist-types/src/requestDemoMetadata.d.ts.map +1 -0
- package/dist-types/src/resolve.d.ts +7 -0
- package/dist-types/src/resolve.d.ts.map +1 -0
- package/dist-types/src/siteDiscoverability.d.ts +33 -0
- package/dist-types/src/siteDiscoverability.d.ts.map +1 -0
- package/dist-types/src/siteHeadMetadata.d.ts +20 -0
- package/dist-types/src/siteHeadMetadata.d.ts.map +1 -0
- package/dist-types/src/socialPreviewImages.d.ts +186 -0
- package/dist-types/src/socialPreviewImages.d.ts.map +1 -0
- package/dist-types/src/socialPreviewTemplatePreview.d.ts +22 -0
- package/dist-types/src/socialPreviewTemplatePreview.d.ts.map +1 -0
- package/dist-types/src/ssr.d.ts +6 -0
- package/dist-types/src/ssr.d.ts.map +1 -0
- package/dist-types/src/standalone-demo-url.d.ts +60 -0
- package/dist-types/src/standalone-demo-url.d.ts.map +1 -0
- package/dist-types/src/static-page-module-loader.d.ts +15 -0
- package/dist-types/src/static-page-module-loader.d.ts.map +1 -0
- package/dist-types/src/transform.d.ts +10 -0
- package/dist-types/src/transform.d.ts.map +1 -0
- package/dist-types/src/urlLifecycle.d.ts +23 -0
- package/dist-types/src/urlLifecycle.d.ts.map +1 -0
- package/dist-types/src/wds-plugin.d.ts +15 -0
- package/dist-types/src/wds-plugin.d.ts.map +1 -0
- package/docs/assets/home-background.svg +1 -0
- package/docs/assets/prism-one-light.css +368 -0
- package/docs/assets/rocket-logo-dark-with-text-below.svg +8 -0
- package/docs/assets/rocket-logo-dark-with-text.svg +7 -0
- package/docs/assets/rocket-logo-dark.svg +7 -0
- package/docs/assets/rocket-logo-light-with-text-below.svg +14 -0
- package/docs/assets/rocket-logo-light-with-text.svg +13 -0
- package/docs/assets/rocket-logo-light.svg +12 -0
- package/docs/assets/rocket-text-no-logo.svg +3 -0
- package/exports/MainMenu.js +1 -0
- package/exports/PageData.js +1 -0
- package/exports/RocketCodeBlock.js +1 -0
- package/exports/RocketIcon.js +1 -0
- package/exports/RocketJsDemo.js +1 -0
- package/exports/RocketRequestDemo.js +1 -0
- package/exports/SocialPreviewPlayground.js +1 -0
- package/exports/adapters/netlify.js +1 -0
- package/exports/asyncMessage.js +1 -0
- package/exports/component-hydration.js +1 -0
- package/exports/components/web-awesome.js +63 -0
- package/exports/components.js +1 -0
- package/exports/config.js +1 -0
- package/exports/debounce.js +1 -0
- package/exports/define/RocketCodeBlock.js +2 -0
- package/exports/define/RocketIcon.js +3 -0
- package/exports/define/RocketJsDemo.js +5 -0
- package/exports/define/RocketRequestDemo.js +5 -0
- package/exports/define/menus.js +14 -0
- package/exports/extractCode.js +1 -0
- package/exports/globalData.js +1 -0
- package/exports/hydration/hydrationLoader.js +1 -0
- package/exports/icons.js +11 -0
- package/exports/layout-helper.js +1 -0
- package/exports/layout.js +1 -0
- package/exports/layouts/_atlas.css +3 -0
- package/exports/layouts/atlasDoc.js +5 -0
- package/exports/layouts/atlasHero.js +1 -0
- package/exports/layouts/atlasNotFound.js +4 -0
- package/exports/loaded-page-module.js +5 -0
- package/exports/markdownHook.js +4 -0
- package/exports/menu.js +4 -0
- package/exports/menus.js +5 -0
- package/exports/page-runtime.js +5 -0
- package/exports/pages.js +1 -0
- package/exports/resolve.js +1 -0
- package/exports/ssr.js +1 -0
- package/exports/standalone-demo-url.js +10 -0
- package/exports/transform.js +1 -0
- package/exports/types/hydration.ts +26 -0
- package/exports/types/rocket.ts +598 -0
- package/exports/types.ts +71 -0
- package/exports/wds-plugin.js +1 -0
- package/package.json +192 -9
- package/src/PageData.js +244 -0
- package/src/RocketCodeBlock.js +516 -0
- package/src/RocketIcon.js +291 -0
- package/src/RocketJsDemo.js +397 -0
- package/src/RocketJsDemo.test-browser.js +228 -0
- package/src/RocketRequestDemo.js +439 -0
- package/src/RocketRequestDemo.test-browser.js +301 -0
- package/src/SocialPreviewPlayground.js +573 -0
- package/src/adapters/netlify.js +814 -0
- package/src/asyncMessage.js +21 -0
- package/src/cli/RocketBuild.js +581 -0
- package/src/cli/RocketCli.js +47 -0
- package/src/cli/RocketInit.js +636 -0
- package/src/cli/RocketStart.js +145 -0
- package/src/cli/cli.js +7 -0
- package/src/component-hydration.js +86 -0
- package/src/components/FeatureList.js +114 -0
- package/src/components/Footer.js +116 -0
- package/src/components/Header.js +122 -0
- package/src/components/RocketDrawer.js +193 -0
- package/src/components/RocketSocialLink.js +128 -0
- package/src/components/assets/discord.svg +7 -0
- package/src/components/assets/github.svg +4 -0
- package/src/components/assets/gitlab.svg +1 -0
- package/src/components/assets/info.txt +1 -0
- package/src/components/assets/license.svg +3 -0
- package/src/components/assets/npm.svg +5 -0
- package/src/components/assets/slack.svg +5 -0
- package/src/components/assets/telegram.svg +4 -0
- package/src/components/assets/twitter.svg +1 -0
- package/src/components.js +34 -0
- package/src/config.js +319 -0
- package/src/debounce.js +21 -0
- package/src/defaultSocialPreviewTemplate.js +118 -0
- package/src/development-page-module-loader.js +29 -0
- package/src/extractCode.js +41 -0
- package/src/hydration/evaluate.js +54 -0
- package/src/hydration/extractStrategies.js +91 -0
- package/src/hydration/hydrationLoader.js +330 -0
- package/src/icons.js +898 -0
- package/src/layouts/atlas/atlasDoc.css +877 -0
- package/src/layouts/atlas/atlasDocLayout.js +275 -0
- package/src/layouts/atlas/atlasHero.css +774 -0
- package/src/layouts/atlas/atlasHeroLayout.js +337 -0
- package/src/layouts/atlas/atlasNotFound.css +365 -0
- package/src/layouts/atlas/atlasNotFoundLayout.js +69 -0
- package/src/layouts/layout-helper.js +92 -0
- package/src/layouts/layout.js +52 -0
- package/src/loaded-page-module.js +97 -0
- package/src/main.js +72 -0
- package/src/markdownCompiler.js +303 -0
- package/src/markdownHook.js +148 -0
- package/src/menu.js +210 -0
- package/src/menus/MainMenu.js +58 -0
- package/src/menus/RocketMenu.js +191 -0
- package/src/menus/RocketNextPage.js +25 -0
- package/src/menus/RocketPreviousPage.js +29 -0
- package/src/menus/RocketToc.js +309 -0
- package/src/menus/pageNavigation.js +285 -0
- package/src/page-pagination.js +241 -0
- package/src/page-runtime.js +481 -0
- package/src/pages.js +537 -0
- package/src/publicAssets.js +336 -0
- package/src/requestDemoMetadata.js +97 -0
- package/src/resolve.js +15 -0
- package/src/siteDiscoverability.js +184 -0
- package/src/siteHeadMetadata.js +69 -0
- package/src/socialPreviewImages.js +482 -0
- package/src/socialPreviewTemplatePreview.js +352 -0
- package/src/ssr.js +14 -0
- package/src/standalone-demo-url.js +147 -0
- package/src/static-page-module-loader.js +29 -0
- package/src/transform.js +720 -0
- package/src/urlLifecycle.js +57 -0
- package/src/wds-plugin.js +307 -0
package/src/config.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/** Runs on: server */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { validateIconLibrariesConfig } from './icons.js';
|
|
4
|
+
|
|
5
|
+
const REDIRECT_STATUSES = new Set([301, 302, 307, 308]);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} [filePath]
|
|
9
|
+
* @returns {Promise<import("@rocket/js/types.js").ResolvedRocketConfig>}
|
|
10
|
+
*/
|
|
11
|
+
export async function readConfig(filePath) {
|
|
12
|
+
const configFile = await import(
|
|
13
|
+
filePath ? path.join(process.cwd(), filePath) : path.join(process.cwd(), 'rocket-config.js')
|
|
14
|
+
);
|
|
15
|
+
if (configFile.default === undefined) {
|
|
16
|
+
throw new Error('rocket-config.js must have a default export');
|
|
17
|
+
}
|
|
18
|
+
/** @type {import("@rocket/js/types.js").RocketConfig} */
|
|
19
|
+
const config = configFile.default;
|
|
20
|
+
validateRedirectConfig(config.urlLifecycle?.redirects);
|
|
21
|
+
const siteHeadMetadata = normalizeSiteHeadMetadataConfig(config.siteHeadMetadata);
|
|
22
|
+
validateIconLibrariesConfig(config.iconLibraries);
|
|
23
|
+
validateDefaultIconLibraryConfig(config.defaultIconLibrary);
|
|
24
|
+
const siteOrigin = siteHeadMetadata
|
|
25
|
+
? requireSiteHeadMetadataSiteOrigin(config.siteOrigin)
|
|
26
|
+
: config.siteOrigin;
|
|
27
|
+
config.includeGlobs = config.includeGlobs.map(glob => {
|
|
28
|
+
if (!glob.includes('*') && !glob.includes('.')) {
|
|
29
|
+
// If the glob is a directory, include all files in the directory
|
|
30
|
+
return `${glob}${glob.endsWith('/') ? '' : '/'}**`;
|
|
31
|
+
}
|
|
32
|
+
return glob;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
excludeRegex: [],
|
|
37
|
+
adjustDevServerConfig: _ => _,
|
|
38
|
+
...config,
|
|
39
|
+
...(siteOrigin ? { siteOrigin } : {}),
|
|
40
|
+
...(siteHeadMetadata ? { siteHeadMetadata } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {unknown} defaultIconLibrary
|
|
46
|
+
*/
|
|
47
|
+
function validateDefaultIconLibraryConfig(defaultIconLibrary) {
|
|
48
|
+
if (defaultIconLibrary === undefined) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (typeof defaultIconLibrary !== 'string' || defaultIconLibrary.trim() === '') {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'Invalid Icon Library Configuration: defaultIconLibrary must be a non-empty string',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const siteHeadMetadataFields = new Set([
|
|
59
|
+
'siteName',
|
|
60
|
+
'defaultDescription',
|
|
61
|
+
'language',
|
|
62
|
+
'icons',
|
|
63
|
+
'themeColor',
|
|
64
|
+
'socialPreview',
|
|
65
|
+
]);
|
|
66
|
+
const siteHeadMetadataIconFields = new Set(['ico', 'svg', 'appleTouchIcon']);
|
|
67
|
+
const siteHeadMetadataSocialPreviewFields = new Set(['delivery', 'template']);
|
|
68
|
+
const siteHeadMetadataSocialPreviewDeliveryValues = new Set(['static']);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {unknown} siteHeadMetadata
|
|
72
|
+
* @returns {import("@rocket/js/types.js").SiteHeadMetadataConfig | undefined}
|
|
73
|
+
*/
|
|
74
|
+
function normalizeSiteHeadMetadataConfig(siteHeadMetadata) {
|
|
75
|
+
if (siteHeadMetadata === undefined) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
if (!isPlainRecord(siteHeadMetadata)) {
|
|
79
|
+
throw invalidSiteHeadMetadata('siteHeadMetadata', 'must be an object');
|
|
80
|
+
}
|
|
81
|
+
for (const field of Object.keys(siteHeadMetadata)) {
|
|
82
|
+
if (!siteHeadMetadataFields.has(field)) {
|
|
83
|
+
throw invalidSiteHeadMetadata(
|
|
84
|
+
`siteHeadMetadata.${field}`,
|
|
85
|
+
'is not a known Site Head Metadata field',
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const normalized = /** @type {import("@rocket/js/types.js").SiteHeadMetadataConfig} */ ({
|
|
90
|
+
siteName: readRequiredSiteHeadMetadataString(siteHeadMetadata, 'siteName'),
|
|
91
|
+
defaultDescription: readRequiredSiteHeadMetadataString(siteHeadMetadata, 'defaultDescription'),
|
|
92
|
+
language: readRequiredSiteHeadMetadataString(siteHeadMetadata, 'language'),
|
|
93
|
+
});
|
|
94
|
+
if (hasOwn(siteHeadMetadata, 'icons')) {
|
|
95
|
+
normalized.icons = readSiteHeadMetadataIcons(siteHeadMetadata.icons);
|
|
96
|
+
}
|
|
97
|
+
if (hasOwn(siteHeadMetadata, 'themeColor')) {
|
|
98
|
+
normalized.themeColor = readSiteHeadMetadataString(
|
|
99
|
+
siteHeadMetadata.themeColor,
|
|
100
|
+
'siteHeadMetadata.themeColor',
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (hasOwn(siteHeadMetadata, 'socialPreview')) {
|
|
104
|
+
normalized.socialPreview = readSiteHeadMetadataSocialPreview(siteHeadMetadata.socialPreview);
|
|
105
|
+
}
|
|
106
|
+
return normalized;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {unknown} socialPreview
|
|
111
|
+
* @returns {NonNullable<import('@rocket/js/types.js').SiteHeadMetadataConfig['socialPreview']>}
|
|
112
|
+
*/
|
|
113
|
+
function readSiteHeadMetadataSocialPreview(socialPreview) {
|
|
114
|
+
if (!isPlainRecord(socialPreview)) {
|
|
115
|
+
throw invalidSiteHeadMetadata('siteHeadMetadata.socialPreview', 'must be an object');
|
|
116
|
+
}
|
|
117
|
+
for (const field of Object.keys(socialPreview)) {
|
|
118
|
+
if (!siteHeadMetadataSocialPreviewFields.has(field)) {
|
|
119
|
+
throw invalidSiteHeadMetadata(
|
|
120
|
+
`siteHeadMetadata.socialPreview.${field}`,
|
|
121
|
+
'is not a known Social Preview field',
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (
|
|
126
|
+
hasOwn(socialPreview, 'delivery') &&
|
|
127
|
+
!siteHeadMetadataSocialPreviewDeliveryValues.has(/** @type {string} */ (socialPreview.delivery))
|
|
128
|
+
) {
|
|
129
|
+
throw invalidSiteHeadMetadata('siteHeadMetadata.socialPreview.delivery', "must be 'static'");
|
|
130
|
+
}
|
|
131
|
+
if (hasOwn(socialPreview, 'template') && typeof socialPreview.template !== 'function') {
|
|
132
|
+
throw invalidSiteHeadMetadata('siteHeadMetadata.socialPreview.template', 'must be a function');
|
|
133
|
+
}
|
|
134
|
+
const template =
|
|
135
|
+
/** @type {NonNullable<import('@rocket/js/types.js').SiteHeadMetadataConfig['socialPreview']>['template'] | undefined} */ (
|
|
136
|
+
socialPreview.template
|
|
137
|
+
);
|
|
138
|
+
return {
|
|
139
|
+
delivery: 'static',
|
|
140
|
+
...(hasOwn(socialPreview, 'template') ? { template } : {}),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {Record<string, unknown>} siteHeadMetadata
|
|
146
|
+
* @param {'siteName' | 'defaultDescription' | 'language'} field
|
|
147
|
+
*/
|
|
148
|
+
function readRequiredSiteHeadMetadataString(siteHeadMetadata, field) {
|
|
149
|
+
return readSiteHeadMetadataString(siteHeadMetadata[field], `siteHeadMetadata.${field}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @param {unknown} icons
|
|
154
|
+
* @returns {import("@rocket/js/types.js").SiteHeadMetadataIconsConfig}
|
|
155
|
+
*/
|
|
156
|
+
function readSiteHeadMetadataIcons(icons) {
|
|
157
|
+
if (!isPlainRecord(icons)) {
|
|
158
|
+
throw invalidSiteHeadMetadata('siteHeadMetadata.icons', 'must be an object');
|
|
159
|
+
}
|
|
160
|
+
for (const field of Object.keys(icons)) {
|
|
161
|
+
if (!siteHeadMetadataIconFields.has(field)) {
|
|
162
|
+
throw invalidSiteHeadMetadata(
|
|
163
|
+
`siteHeadMetadata.icons.${field}`,
|
|
164
|
+
'is not a known Favicon Asset field',
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
...(hasOwn(icons, 'ico')
|
|
170
|
+
? { ico: readSiteHeadMetadataString(icons.ico, 'siteHeadMetadata.icons.ico') }
|
|
171
|
+
: {}),
|
|
172
|
+
...(hasOwn(icons, 'svg')
|
|
173
|
+
? { svg: readSiteHeadMetadataString(icons.svg, 'siteHeadMetadata.icons.svg') }
|
|
174
|
+
: {}),
|
|
175
|
+
...(hasOwn(icons, 'appleTouchIcon')
|
|
176
|
+
? {
|
|
177
|
+
appleTouchIcon: readSiteHeadMetadataString(
|
|
178
|
+
icons.appleTouchIcon,
|
|
179
|
+
'siteHeadMetadata.icons.appleTouchIcon',
|
|
180
|
+
),
|
|
181
|
+
}
|
|
182
|
+
: {}),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @param {unknown} value
|
|
188
|
+
* @param {string} field
|
|
189
|
+
*/
|
|
190
|
+
function readSiteHeadMetadataString(value, field) {
|
|
191
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
192
|
+
throw invalidSiteHeadMetadata(field, 'must be a non-empty string');
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @param {string} field
|
|
199
|
+
* @param {string} message
|
|
200
|
+
*/
|
|
201
|
+
function invalidSiteHeadMetadata(field, message) {
|
|
202
|
+
return new Error(`Invalid Site Head Metadata: ${field} ${message}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {string | undefined} siteOrigin
|
|
207
|
+
*/
|
|
208
|
+
function requireSiteHeadMetadataSiteOrigin(siteOrigin) {
|
|
209
|
+
if (typeof siteOrigin !== 'string' || siteOrigin.trim() === '') {
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Site Head Metadata requires a Site Origin. ` +
|
|
212
|
+
`Add siteOrigin: 'https://example.com' to rocket-config.js.`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
return normalizeSiteOrigin(siteOrigin);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @param {string} siteOrigin
|
|
220
|
+
*/
|
|
221
|
+
function normalizeSiteOrigin(siteOrigin) {
|
|
222
|
+
let url;
|
|
223
|
+
try {
|
|
224
|
+
url = new URL(siteOrigin);
|
|
225
|
+
} catch {
|
|
226
|
+
throw invalidSiteOriginError(siteOrigin);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (url.origin === 'null' || url.pathname !== '/' || url.search || url.hash) {
|
|
230
|
+
throw invalidSiteOriginError(siteOrigin);
|
|
231
|
+
}
|
|
232
|
+
return url.origin;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @param {string} siteOrigin
|
|
237
|
+
*/
|
|
238
|
+
function invalidSiteOriginError(siteOrigin) {
|
|
239
|
+
return new Error(
|
|
240
|
+
`Invalid Site Origin ${JSON.stringify(siteOrigin)}. ` +
|
|
241
|
+
`Use an absolute origin such as 'https://example.com'.`,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @param {import("@rocket/js/types.js").RedirectConfig[] | undefined} redirects
|
|
247
|
+
*/
|
|
248
|
+
function validateRedirectConfig(redirects = []) {
|
|
249
|
+
const sources = new Set();
|
|
250
|
+
for (const redirect of redirects) {
|
|
251
|
+
if (!isInternalAbsolutePath(redirect.source)) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`Invalid Redirect source ${JSON.stringify(
|
|
254
|
+
redirect.source,
|
|
255
|
+
)}. Redirect sources must be internal absolute paths.`,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
if (sources.has(redirect.source)) {
|
|
259
|
+
throw new Error(`Duplicate Redirect source ${JSON.stringify(redirect.source)}.`);
|
|
260
|
+
}
|
|
261
|
+
sources.add(redirect.source);
|
|
262
|
+
if (!isInternalAbsolutePath(redirect.target) && !isAbsoluteHttpUrl(redirect.target)) {
|
|
263
|
+
throw new Error(
|
|
264
|
+
`Invalid Redirect target ${JSON.stringify(
|
|
265
|
+
redirect.target,
|
|
266
|
+
)}. Redirect targets must be internal absolute paths or absolute http: or https: URLs.`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (redirect.status !== undefined && !REDIRECT_STATUSES.has(redirect.status)) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`Invalid Redirect status ${JSON.stringify(
|
|
272
|
+
redirect.status,
|
|
273
|
+
)}. Redirect statuses must be 301, 302, 307, or 308.`,
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @param {unknown} value
|
|
281
|
+
*/
|
|
282
|
+
function isInternalAbsolutePath(value) {
|
|
283
|
+
return typeof value === 'string' && value.startsWith('/') && !value.startsWith('//');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @param {unknown} value
|
|
288
|
+
*/
|
|
289
|
+
function isAbsoluteHttpUrl(value) {
|
|
290
|
+
if (typeof value !== 'string') {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
const url = new URL(value);
|
|
295
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
296
|
+
} catch {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @param {unknown} value
|
|
303
|
+
* @returns {value is Record<string, unknown>}
|
|
304
|
+
*/
|
|
305
|
+
function isPlainRecord(value) {
|
|
306
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
const prototype = Object.getPrototypeOf(value);
|
|
310
|
+
return prototype === Object.prototype || prototype === null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* @param {object} object
|
|
315
|
+
* @param {string} key
|
|
316
|
+
*/
|
|
317
|
+
function hasOwn(object, key) {
|
|
318
|
+
return Object.prototype.hasOwnProperty.call(object, key);
|
|
319
|
+
}
|
package/src/debounce.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template {(...args: any) => any} F
|
|
3
|
+
* @param {F} fn
|
|
4
|
+
* @param {number} timeout
|
|
5
|
+
* @returns {(...args: Parameters<F>) => ReturnType<F>}
|
|
6
|
+
*/
|
|
7
|
+
export function debounce(fn, timeout) {
|
|
8
|
+
const func = function (/** @type {Parameters<F>} */ ...args) {
|
|
9
|
+
if (ret._ready) {
|
|
10
|
+
ret._ready = false;
|
|
11
|
+
setTimeout(() => {
|
|
12
|
+
ret._ready = true;
|
|
13
|
+
return fn(...args);
|
|
14
|
+
}, timeout);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
func._ready = true;
|
|
18
|
+
/** @type {((...args: any) => any) & {_ready: boolean}} */
|
|
19
|
+
const ret = func;
|
|
20
|
+
return ret;
|
|
21
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export const DEFAULT_SOCIAL_PREVIEW_IMAGE_WIDTH = 1200;
|
|
2
|
+
export const DEFAULT_SOCIAL_PREVIEW_IMAGE_HEIGHT = 630;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {{
|
|
6
|
+
* site?: { language: string; name: string };
|
|
7
|
+
* page?: { title: string; documentTitle?: string; description: string; canonicalUrl: string };
|
|
8
|
+
* language?: string;
|
|
9
|
+
* siteName?: string;
|
|
10
|
+
* title?: string;
|
|
11
|
+
* description?: string;
|
|
12
|
+
* canonicalUrl?: string;
|
|
13
|
+
* }} facts
|
|
14
|
+
*/
|
|
15
|
+
export function defaultSocialPreviewTemplate({
|
|
16
|
+
site,
|
|
17
|
+
page,
|
|
18
|
+
language,
|
|
19
|
+
siteName,
|
|
20
|
+
title,
|
|
21
|
+
description,
|
|
22
|
+
canonicalUrl,
|
|
23
|
+
}) {
|
|
24
|
+
language ??= site?.language;
|
|
25
|
+
siteName ??= site?.name;
|
|
26
|
+
title ??= page?.title;
|
|
27
|
+
description ??= page?.description;
|
|
28
|
+
canonicalUrl ??= page?.canonicalUrl;
|
|
29
|
+
if (!language || !siteName || !title || !description || !canonicalUrl) {
|
|
30
|
+
throw new Error('Default Social Preview Template requires complete site and Page facts.');
|
|
31
|
+
}
|
|
32
|
+
return `<!doctype html>
|
|
33
|
+
<html lang="${escapeHtml(language)}">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="utf-8">
|
|
36
|
+
<style>
|
|
37
|
+
* { box-sizing: border-box; }
|
|
38
|
+
html,
|
|
39
|
+
body {
|
|
40
|
+
width: ${DEFAULT_SOCIAL_PREVIEW_IMAGE_WIDTH}px;
|
|
41
|
+
height: ${DEFAULT_SOCIAL_PREVIEW_IMAGE_HEIGHT}px;
|
|
42
|
+
margin: 0;
|
|
43
|
+
}
|
|
44
|
+
body {
|
|
45
|
+
display: grid;
|
|
46
|
+
place-items: stretch;
|
|
47
|
+
padding: 54px;
|
|
48
|
+
color: #f8fafc;
|
|
49
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
50
|
+
background:
|
|
51
|
+
radial-gradient(circle at 18% 18%, rgba(56, 189, 248, 0.42), transparent 34%),
|
|
52
|
+
radial-gradient(circle at 84% 22%, rgba(168, 85, 247, 0.38), transparent 30%),
|
|
53
|
+
linear-gradient(135deg, #0f172a 0%, #111827 52%, #020617 100%);
|
|
54
|
+
}
|
|
55
|
+
main {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
justify-content: space-between;
|
|
59
|
+
min-height: 100%;
|
|
60
|
+
border: 1px solid rgba(248, 250, 252, 0.22);
|
|
61
|
+
border-radius: 42px;
|
|
62
|
+
padding: 58px 64px;
|
|
63
|
+
background: rgba(15, 23, 42, 0.68);
|
|
64
|
+
box-shadow: 0 24px 90px rgba(0, 0, 0, 0.32);
|
|
65
|
+
}
|
|
66
|
+
.site {
|
|
67
|
+
margin: 0;
|
|
68
|
+
color: #7dd3fc;
|
|
69
|
+
font-size: 34px;
|
|
70
|
+
font-weight: 800;
|
|
71
|
+
letter-spacing: 0.035em;
|
|
72
|
+
text-transform: uppercase;
|
|
73
|
+
}
|
|
74
|
+
h1 {
|
|
75
|
+
max-width: 930px;
|
|
76
|
+
margin: 38px 0 0;
|
|
77
|
+
font-size: 76px;
|
|
78
|
+
line-height: 0.98;
|
|
79
|
+
letter-spacing: -0.055em;
|
|
80
|
+
}
|
|
81
|
+
.description {
|
|
82
|
+
max-width: 900px;
|
|
83
|
+
margin: 28px 0 0;
|
|
84
|
+
color: #cbd5e1;
|
|
85
|
+
font-size: 36px;
|
|
86
|
+
line-height: 1.22;
|
|
87
|
+
}
|
|
88
|
+
.url {
|
|
89
|
+
margin: 46px 0 0;
|
|
90
|
+
color: #94a3b8;
|
|
91
|
+
font-size: 26px;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body>
|
|
96
|
+
<main>
|
|
97
|
+
<section>
|
|
98
|
+
<p class="site">${escapeHtml(siteName)}</p>
|
|
99
|
+
<h1>${escapeHtml(title)}</h1>
|
|
100
|
+
<p class="description">${escapeHtml(description)}</p>
|
|
101
|
+
</section>
|
|
102
|
+
<p class="url">${escapeHtml(canonicalUrl)}</p>
|
|
103
|
+
</main>
|
|
104
|
+
</body>
|
|
105
|
+
</html>`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {string} value
|
|
110
|
+
*/
|
|
111
|
+
function escapeHtml(value) {
|
|
112
|
+
return value
|
|
113
|
+
.replaceAll('&', '&')
|
|
114
|
+
.replaceAll('"', '"')
|
|
115
|
+
.replaceAll("'", ''')
|
|
116
|
+
.replaceAll('<', '<')
|
|
117
|
+
.replaceAll('>', '>');
|
|
118
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { normalizeLoadedPageModule } from './loaded-page-module.js';
|
|
2
|
+
import { parseComponents } from './components.js';
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('./page-runtime.js').PageModuleLoaderOptions} PageModuleLoaderOptions */
|
|
5
|
+
|
|
6
|
+
export function createDevelopmentPageModuleLoader() {
|
|
7
|
+
return {
|
|
8
|
+
/**
|
|
9
|
+
* @param {PageModuleLoaderOptions} options
|
|
10
|
+
*/
|
|
11
|
+
async load({ page, variant }) {
|
|
12
|
+
if (!page.file.endsWith('.js')) {
|
|
13
|
+
const importAttributes = { type: 'rocketLoadMdInitial' };
|
|
14
|
+
if (typeof variant === 'object' && variant.kind === 'standalone-demo') {
|
|
15
|
+
Object.assign(importAttributes, { singleDemo: variant.demoName });
|
|
16
|
+
}
|
|
17
|
+
const module = await import(`./${page.file}`, {
|
|
18
|
+
with: importAttributes,
|
|
19
|
+
});
|
|
20
|
+
return normalizeLoadedPageModule({ kind: 'markdown', module, parseComponents });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const module = await import(`./${page.file}`, {
|
|
24
|
+
with: { type: 'rocketLoadJsInitial' },
|
|
25
|
+
});
|
|
26
|
+
return normalizeLoadedPageModule({ kind: 'javascript', module });
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Runs on: import-hook */
|
|
2
|
+
import { remove } from 'unist-util-remove';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} meta
|
|
6
|
+
*/
|
|
7
|
+
export function extractMdCode(meta) {
|
|
8
|
+
/** @type {import('unified').Plugin} */
|
|
9
|
+
return function unifiedProcessor() {
|
|
10
|
+
/** @type {string | null} */
|
|
11
|
+
let jsCode = null;
|
|
12
|
+
|
|
13
|
+
/** @type {import('unist-util-is').TestFunction} */
|
|
14
|
+
const removeFunction = _node => {
|
|
15
|
+
// technically not correct, but we check
|
|
16
|
+
const node = /** @type {import('mdast').Code} */ (_node);
|
|
17
|
+
if (node.type === 'code' && node.lang === 'js' && node.meta === meta) {
|
|
18
|
+
jsCode = jsCode === null ? node.value : jsCode + node.value + ';';
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {import('unist').Node} tree
|
|
26
|
+
* @param {import('vfile').VFile} file
|
|
27
|
+
*/
|
|
28
|
+
return function transformer(tree, file) {
|
|
29
|
+
remove(tree, removeFunction);
|
|
30
|
+
if (!file.data) {
|
|
31
|
+
file.data = {};
|
|
32
|
+
}
|
|
33
|
+
if (!file.data.code) {
|
|
34
|
+
file.data.code = {};
|
|
35
|
+
}
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
file.data.code[meta] = jsCode;
|
|
38
|
+
return tree;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* From: https://github.com/modernweb-dev/rocket/blob/main/packages/engine/src/hydration/evaluate.js
|
|
3
|
+
* Runs on: client
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @param {object} options
|
|
7
|
+
* @param {string} options.strategyTemplate
|
|
8
|
+
* @param {import('@rocket/js/types.js').Strategy[]} options.strategies
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
export function evaluate({ strategyTemplate, strategies }) {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
const conditions = strategyTemplate.replace(/{{(\d+)}}/g, (match, number) => {
|
|
14
|
+
if (strategies[number]) {
|
|
15
|
+
return strategies[number].resolveAble ? 1 : 0;
|
|
16
|
+
}
|
|
17
|
+
return match;
|
|
18
|
+
});
|
|
19
|
+
const result = evaluateConditions(conditions);
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} input
|
|
25
|
+
* @returns {boolean}
|
|
26
|
+
*/
|
|
27
|
+
export function evaluateConditions(input) {
|
|
28
|
+
let state;
|
|
29
|
+
let mode = 'and';
|
|
30
|
+
|
|
31
|
+
const str = input.replace('&&', '&').replace('||', '|');
|
|
32
|
+
|
|
33
|
+
for (const char of str) {
|
|
34
|
+
if (char === ' ') {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (char === '&') {
|
|
38
|
+
mode = 'and';
|
|
39
|
+
}
|
|
40
|
+
if (char === '|') {
|
|
41
|
+
mode = 'or';
|
|
42
|
+
}
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
if (!isNaN(char)) {
|
|
45
|
+
// is number
|
|
46
|
+
const i = parseInt(char);
|
|
47
|
+
state = state === undefined ? i : mode === 'and' ? state & i : state | i;
|
|
48
|
+
if (mode === 'or' && state === 1) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return !!state;
|
|
54
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* From: https://github.com/modernweb-dev/rocket/blob/packages/engine/src/hydration/extractStrategies.js
|
|
3
|
+
* Runs on: client
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} str
|
|
8
|
+
* @returns {string[]}
|
|
9
|
+
*/
|
|
10
|
+
function getParts(str) {
|
|
11
|
+
const parts = [];
|
|
12
|
+
let captured = '';
|
|
13
|
+
for (const char of str.split('')) {
|
|
14
|
+
if ((char === '&' && captured.endsWith('&')) || (char === '|' && captured.endsWith('|'))) {
|
|
15
|
+
parts.push(captured.slice(0, -1).trim());
|
|
16
|
+
parts.push(char.repeat(2));
|
|
17
|
+
captured = '';
|
|
18
|
+
} else {
|
|
19
|
+
captured += char;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (captured) {
|
|
24
|
+
parts.push(captured.trim());
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return parts;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {string} part
|
|
33
|
+
* @param {string} type
|
|
34
|
+
* @returns {{ type: string; resolveAble: boolean; options?: string; }}
|
|
35
|
+
*/
|
|
36
|
+
function getStrategy(part, type) {
|
|
37
|
+
/** @type {{ type: string; resolveAble: boolean; options?: string; }} */
|
|
38
|
+
const strategy = {
|
|
39
|
+
type,
|
|
40
|
+
resolveAble: false,
|
|
41
|
+
};
|
|
42
|
+
if (part.length > type.length) {
|
|
43
|
+
const rawOptions = part.slice(type.length).trim();
|
|
44
|
+
if (rawOptions.startsWith("('") && rawOptions.endsWith("')")) {
|
|
45
|
+
const options = rawOptions.slice(2, -2);
|
|
46
|
+
strategy.options = options;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (type === 'onIdle' || type === 'onDelay' || type === 'onClientLoad') {
|
|
50
|
+
strategy.resolveAble = true;
|
|
51
|
+
}
|
|
52
|
+
return strategy;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} input
|
|
57
|
+
*/
|
|
58
|
+
export function extractStrategies(input) {
|
|
59
|
+
const parts = getParts(input);
|
|
60
|
+
|
|
61
|
+
/** @type {import('@rocket/js/types.js').LoadingStrategy} */
|
|
62
|
+
const result = {
|
|
63
|
+
strategyAttribute: input,
|
|
64
|
+
strategies: [],
|
|
65
|
+
strategyTemplate: '',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
let templatePartsIndex = 0;
|
|
69
|
+
for (const [i, part] of parts.entries()) {
|
|
70
|
+
const type = part.includes('(') ? part.substring(0, part.indexOf('(')) : part;
|
|
71
|
+
switch (type) {
|
|
72
|
+
// global events
|
|
73
|
+
case 'onClientLoad':
|
|
74
|
+
case 'onClick':
|
|
75
|
+
case 'onFocus':
|
|
76
|
+
// element events eslint fall through
|
|
77
|
+
case 'onHover':
|
|
78
|
+
case 'onMedia':
|
|
79
|
+
case 'onVisible':
|
|
80
|
+
// modifiers eslint fall through
|
|
81
|
+
case 'onIdle':
|
|
82
|
+
case 'onDelay':
|
|
83
|
+
result.strategies.push(getStrategy(part, type));
|
|
84
|
+
parts[i] = `{{${templatePartsIndex}}}`;
|
|
85
|
+
templatePartsIndex += 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
result.strategyTemplate = parts.join(' ');
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
}
|