Skip to content

Commit

Permalink
feat: new [components <Head> and <Config>](https://vike.dev/useCo…
Browse files Browse the repository at this point in the history
  • Loading branch information
brillout authored Aug 9, 2024
1 parent 4c52c6d commit ed1c070
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 67 deletions.
43 changes: 40 additions & 3 deletions examples/full/.testRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { testRun };

import { test, expect, run, fetchHtml, page, getServerUrl, autoRetry, partRegex } from "@brillout/test-e2e";
import assert from "node:assert";
const dataHk = partRegex`data-hk="${/[0-9-]+/}"`;

let isProd: boolean;

Expand All @@ -15,13 +16,15 @@ function testRun(cmd: `pnpm run ${"dev" | "preview"}`) {
title: "My Vike + Solid App",
text: "Rendered to HTML.",
counter: true,
image: true,
});

testUrl({
url: "/star-wars",
title: "6 Star Wars Movies",
description: "All the 6 movies from the Star Wars franchise",
text: "A New Hope",
image: true,
});

testUrl({
Expand All @@ -41,6 +44,8 @@ function testRun(cmd: `pnpm run ${"dev" | "preview"}`) {
});

testNavigationBetweenWithSSRAndWithoutSSR();

testUseConfig();
}

function testNavigationBetweenWithSSRAndWithoutSSR() {
Expand Down Expand Up @@ -91,27 +96,33 @@ function testUrl({
text,
counter,
noSSR,
image,
}: {
url: string;
title: string;
description?: string;
text: string;
counter?: true;
noSSR?: true;
image?: true;
}) {
test(url + " (HTML)", async () => {
const html = await fetchHtml(url);
if (!noSSR) {
expect(html).toContain(text);
}

const dataHkHash = /[0-9-]+/;

expect(getTitle(html)).toBe(title);
expect(html).toMatch(partRegex`<link data-hk="${dataHkHash}" rel="icon" href="${getAssetUrl("logo.svg")}">`);
expect(html).toMatch(partRegex`<link ${dataHk} rel="icon" href="${getAssetUrl("logo.svg")}">`);

if (!description) description = "Demo showcasing Vike + Solid";
expect(html).toMatch(partRegex`<meta name="description" content="${description}">`);

if (image) {
expect(html).toMatch(partRegex`<meta property="og:image" content="${getAssetUrl("logo-new.svg")}">`);
} else {
expect(html).not.toContain("og:image");
}
});
test(url + " (Hydration)", async () => {
await page.goto(getServerUrl() + url);
Expand All @@ -123,6 +134,32 @@ function testUrl({
});
}

function testUseConfig() {
test("useConfig() HTML", async () => {
const html = await fetchHtml("/images");
expect(html).toMatch(
partRegex`<script ${dataHk} type="application/ld+json">{"@context":"https://schema.org/","contentUrl":{"src":"${getAssetUrl(
"logo-new.svg",
)}"},"creator":{"@type":"Person","name":"brillout"}}</script>`,
);
expect(html).toMatch(
partRegex`<script ${dataHk} type="application/ld+json">{"@context":"https://schema.org/","contentUrl":{"src":"${getAssetUrl(
"logo.svg",
)}"},"creator":{"@type":"Person","name":"Romuald Brillout"}}</script>`,
);
});
test("useConfig() hydration", async () => {
await page.goto(getServerUrl() + "/");
await testCounter();
ensureWasClientSideRouted("/pages/index");
await page.click('a:has-text("useConfig()")');
await testCounter();
ensureWasClientSideRouted("/pages/index");
await page.goto(getServerUrl() + "/images");
await testCounter();
});
}

function getTitle(html: string) {
const title = html.match(/<title>(.*?)<\/title>/i)?.[1];
return title;
Expand Down
1 change: 1 addition & 0 deletions examples/full/pages/+Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function Layout(props: { children?: JSX.Element }) {
<Link href="/without-ssr">Without SSR</Link>
<Link href="/starship">Nested Layout 1</Link>
<Link href="/stardust">Nested Layout 2</Link>
<Link href="/images">useConfig()</Link>
</Sidebar>
<Content>{props.children}</Content>
</div>
Expand Down
47 changes: 47 additions & 0 deletions examples/full/pages/images/+Page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export { Page };

import { Head } from "vike-solid/Head";
import logoOld from "../../assets/logo.svg";
import logoNew from "../../assets/logo-new.svg";
import { Counter } from "../../components/Counter";

function Page() {
return (
<>
<p>
Page showcasing an <code>&lt;Image&gt;</code> component that adds/teleports structured data (
<code>&lt;script type="application/ld+json"&gt;</code>) to <code>&lt;head&gt;</code>, see HTML.
</p>
<div>
New logo: <Image src={logoNew} author="brillout" />
</div>
<br />
<div>
Old logo: <Image src={logoOld} author="Romuald Brillout" />
</div>
<br />
<Counter />
</>
);
}

function Image({ src, author }: { src: string; author: string }) {
return (
<>
<img src={src} height={48} style={{ "vertical-align": "middle", "margin-left": "10px" }} />
<Head>
<script
type="application/ld+json"
innerHTML={JSON.stringify({
"@context": "https://schema.org/",
contentUrl: { src },
creator: {
"@type": "Person",
name: author,
},
})}
></script>
</Head>
</>
);
}
7 changes: 6 additions & 1 deletion examples/full/pages/index/+Page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export { Page };

import { clientOnly } from "vike-solid/clientOnly";
import { Config } from "vike-solid/Config";
import image from "../../assets/logo-new.svg";

const ClientOnlyCounter = clientOnly(() => import("./Counter"));
const ClientOnlyCounterSlow = clientOnly(async () => {
Expand All @@ -8,9 +12,10 @@ const ClientOnlyCounterSlow = clientOnly(async () => {
return import("./Counter");
});

export default function Page() {
function Page() {
return (
<>
<Config image={image}></Config>
<h1>My Vike + Solid App</h1>
This page is:
<ul>
Expand Down
13 changes: 13 additions & 0 deletions examples/full/pages/star-wars/index/+data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,27 @@ export { data };
export type Data = Awaited<ReturnType<typeof data>>;

import fetch from "node-fetch";
import { useConfig } from "vike-solid/useConfig";
import type { Movie, MovieDetails } from "../types.js";
import image from "../../../assets/logo-new.svg";

const data = async () => {
const config = useConfig();

const response = await fetch("https://brillout.github.io/star-wars/api/films.json");
const moviesData = (await response.json()) as MovieDetails[];

const n = moviesData.length;
config({
title: `${n} Star Wars Movies`, // <title>
description: `All the ${n} movies from the Star Wars franchise`, // <meta name="description">
image, // <meta property="og:image">
});

// We remove data we don't need because the data is passed to the client; we should
// minimize what is sent over the network.
const movies = minimize(moviesData);

return movies;
};

Expand Down
9 changes: 0 additions & 9 deletions examples/full/pages/star-wars/index/+description.ts

This file was deleted.

9 changes: 0 additions & 9 deletions examples/full/pages/star-wars/index/+title.ts

This file was deleted.

55 changes: 11 additions & 44 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions vike-solid/components/Config/Config-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export { Config };

// Same as ./Config-server.ts but importing useConfig-client.js

import { useConfig } from "../../hooks/useConfig/useConfig-client.js";
import type { ConfigFromHook } from "../../types/Config.js";

/**
* Set configurations inside React components.
*
* https://vike.dev/useConfig
*/
function Config(props: ConfigFromHook): null {
const config = useConfig();
config(props);
return null;
}
17 changes: 17 additions & 0 deletions vike-solid/components/Config/Config-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export { Config };

// Same as ./Config-client.ts but importing useConfig-server.js

import { useConfig } from "../../hooks/useConfig/useConfig-server.js";
import type { ConfigFromHook } from "../../types/Config.js";

/**
* Set configurations inside React components.
*
* https://vike.dev/useConfig
*/
function Config(props: ConfigFromHook): null {
const config = useConfig();
config(props);
return null;
}
Loading

0 comments on commit ed1c070

Please sign in to comment.