Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"tasks": {
"test": "deno test --allow-env --allow-write --allow-read"
"test": "deno test --allow-env --allow-write --allow-read --allow-run --allow-net"
}
}
1 change: 1 addition & 0 deletions deno.lock

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

67 changes: 36 additions & 31 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,45 @@ import { SitemapContext } from "./sitemap.ts";
import { Manifest, Plugin, RouteProps } from "./types.ts";

interface PluginOptions {
include?: Array<string | { path: string, options: RouteProps }>
exclude?: Array<string>
include?: Array<string | { path: string; options: RouteProps }>;
exclude?: Array<string>;
}

export const freshSEOPlugin = (manifest: Manifest, opts: PluginOptions = {}): Plugin => {
return {
name: "fresh-seo",
routes: [
{
path: "/sitemap.xml",
handler: (req) => {
const sitemap = new SitemapContext(req.url.replace("/sitemap.xml", ""), manifest);
export const freshSEOPlugin = (
manifest: Manifest,
opts: PluginOptions = {}
): Plugin => {
return {
name: "fresh-seo",
routes: [
{
path: "/sitemap.xml",
handler: (req) => {
const sitemap = new SitemapContext(
req.url.replace("/sitemap.xml", ""),
manifest
);

if (opts.include) {
opts.include.forEach((route) => {
if (typeof route === "string") {
sitemap.add(route);
return;
}
if (opts.include) {
opts.include.forEach((route) => {
if (typeof route === "string") {
sitemap.add(route);
return;
}

sitemap.add(route.path, route.options);
})
}
sitemap.add(route.path, route.options);
});
}

if (opts.exclude) {
opts.exclude.forEach((path) => {
sitemap.remove(path);
})
}
if (opts.exclude) {
opts.exclude.forEach((path) => {
sitemap.remove(path);
});
}


return sitemap.render();
}
}
]
}
}
return sitemap.render();
},
},
],
};
};
12 changes: 12 additions & 0 deletions tests/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// <reference no-default-lib="true" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />

export { TextLineStream } from "https://deno.land/std@0.193.0/streams/text_line_stream.ts";
export {
assert,
assertStringIncludes,
assertThrows,
} from "https://deno.land/std@0.197.0/assert/mod.ts";
6 changes: 6 additions & 0 deletions tests/fixture/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
16 changes: 16 additions & 0 deletions tests/fixture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Fresh project

Your new Fresh project is ready to go. You can follow the Fresh "Getting
Started" guide here: https://fresh.deno.dev/docs/getting-started

### Usage

Make sure to install Deno: https://deno.land/manual/getting_started/installation

Then start the project:

```
deno task start
```

This will watch the project directory and restart as necessary.
12 changes: 12 additions & 0 deletions tests/fixture/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { JSX } from "preact";
import { IS_BROWSER } from "$fresh/runtime.ts";

export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
return (
<button
{...props}
disabled={!IS_BROWSER || props.disabled}
class="px-2 py-1 border-gray-500 border-2 rounded bg-white hover:bg-gray-200 transition-colors"
/>
);
}
29 changes: 29 additions & 0 deletions tests/fixture/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"lock": false,
"tasks": {
"start": "deno run -A --watch=static/,routes/ dev.ts",
"update": "deno run -A -r https://fresh.deno.dev/update ."
},
"lint": {
"rules": {
"tags": [
"fresh",
"recommended"
]
}
},
"imports": {
"$fresh/": "https://deno.land/x/fresh@1.3.1/",
"preact": "https://esm.sh/preact@10.15.1",
"preact/": "https://esm.sh/preact@10.15.1/",
"preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.2.0",
"@preact/signals": "https://esm.sh/*@preact/signals@1.1.3",
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.2.3",
"$std/": "https://deno.land/std@0.193.0/",
"fresh-seo": "../../mod.ts"
},
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
5 changes: 5 additions & 0 deletions tests/fixture/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env -S deno run -A --watch=static/,routes/

import dev from "$fresh/dev.ts";

await dev(import.meta.url, "./main.ts");
34 changes: 34 additions & 0 deletions tests/fixture/fresh.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// DO NOT EDIT. This file is generated by fresh.
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.

import * as $0 from "./routes/_404.tsx";
import * as $1 from "./routes/_500.tsx";
import * as $2 from "./routes/_app.tsx";
import * as $3 from "./routes/_middleware.tsx";
import * as $4 from "./routes/about.tsx";
import * as $5 from "./routes/api/joke.ts";
import * as $6 from "./routes/greet/[name].tsx";
import * as $7 from "./routes/index.tsx";
import * as $8 from "./routes/sitemap.xml.tsx";
import * as $$0 from "./islands/Counter.tsx";

const manifest = {
routes: {
"./routes/_404.tsx": $0,
"./routes/_500.tsx": $1,
"./routes/_app.tsx": $2,
"./routes/_middleware.tsx": $3,
"./routes/about.tsx": $4,
"./routes/api/joke.ts": $5,
"./routes/greet/[name].tsx": $6,
"./routes/index.tsx": $7,
"./routes/sitemap.xml.tsx": $8,
},
islands: {
"./islands/Counter.tsx": $$0,
},
baseUrl: import.meta.url,
};

export default manifest;
16 changes: 16 additions & 0 deletions tests/fixture/islands/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Signal } from "@preact/signals";
import { Button } from "../components/Button.tsx";

interface CounterProps {
count: Signal<number>;
}

export default function Counter(props: CounterProps) {
return (
<div class="flex gap-8 py-6">
<Button onClick={() => props.count.value -= 1}>-1</Button>
<p class="text-3xl">{props.count}</p>
<Button onClick={() => props.count.value += 1}>+1</Button>
</div>
);
}
15 changes: 15 additions & 0 deletions tests/fixture/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// <reference no-default-lib="true" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />

import "$std/dotenv/load.ts";

import { start } from "$fresh/server.ts";
import manifest from "./fresh.gen.ts";
import { freshSEOPlugin } from "fresh-seo";

await start(manifest, {
plugins: [freshSEOPlugin(manifest)],
});
5 changes: 5 additions & 0 deletions tests/fixture/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { freshSEOPlugin } from "fresh-seo";
import manifest from "./fresh.gen.ts";
export const options = {
plugins: [freshSEOPlugin(manifest)],
};
28 changes: 28 additions & 0 deletions tests/fixture/routes/_404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

import { Head } from "$fresh/runtime.ts";

export default function Error404() {
return (
<>
<Head>
<title>404 - Page not found</title>
</Head>
<div class="px-4 py-8 mx-auto bg-[#86efac]">
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
<img
class="my-6"
src="/logo.svg"
width="128"
height="128"
alt="the fresh logo: a sliced lemon dripping with juice"
/>
<h1 class="text-4xl font-bold">404 - Page not found</h1>
<p class="my-4">
The page you were looking for doesn't exist.
</p>
<a href="/" class="underline">Go back home</a>
</div>
</div>
</>
);
}
27 changes: 27 additions & 0 deletions tests/fixture/routes/_500.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Head } from "$fresh/runtime.ts";

export default function Error500() {
return (
<>
<Head>
<title>500 - Internal Server Error</title>
</Head>
<div class="px-4 py-8 mx-auto bg-[#86efac]">
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
<img
class="my-6"
src="/logo.svg"
width="128"
height="128"
alt="the fresh logo: a sliced lemon dripping with juice"
/>
<h1 class="text-4xl font-bold">500 - Internal Server Error</h1>
<p class="my-4">Sorry! Something went wrong.</p>
<a href="/" class="underline">
Go back home
</a>
</div>
</div>
</>
);
}
13 changes: 13 additions & 0 deletions tests/fixture/routes/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AppProps } from "$fresh/server.ts";
import { Head } from "$fresh/runtime.ts";

export default function App({ Component }: AppProps) {
return (
<>
<Head>
<link rel="stylesheet" href="/styles.css" />
</Head>
<Component />
</>
);
}
15 changes: 15 additions & 0 deletions tests/fixture/routes/_middleware.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { MiddlewareHandlerContext } from "$fresh/server.ts";

export const handler = [timing];

async function timing(
_req: Request,
ctx: MiddlewareHandlerContext
): Promise<Response> {
const start = performance.now();
const res = await ctx.next();
const end = performance.now();
const dur = (end - start).toFixed(1);
res.headers.set("Server-Timing", `handler;dur=${dur}`);
return res;
}
3 changes: 3 additions & 0 deletions tests/fixture/routes/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function About() {
return <div>This is the about page</div>;
}
21 changes: 21 additions & 0 deletions tests/fixture/routes/api/joke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HandlerContext } from "$fresh/server.ts";

// Jokes courtesy of https://punsandoneliners.com/randomness/programmer-jokes/
const JOKES = [
"Why do Java developers often wear glasses? They can't C#.",
"A SQL query walks into a bar, goes up to two tables and says “can I join you?”",
"Wasn't hard to crack Forrest Gump's password. 1forrest1.",
"I love pressing the F5 key. It's refreshing.",
"Called IT support and a chap from Australia came to fix my network connection. I asked “Do you come from a LAN down under?”",
"There are 10 types of people in the world. Those who understand binary and those who don't.",
"Why are assembly programmers often wet? They work below C level.",
"My favourite computer based band is the Black IPs.",
"What programme do you use to predict the music tastes of former US presidential candidates? An Al Gore Rhythm.",
"An SEO expert walked into a bar, pub, inn, tavern, hostelry, public house.",
];

export const handler = (_req: Request, _ctx: HandlerContext): Response => {
const randomIndex = Math.floor(Math.random() * JOKES.length);
const body = JOKES[randomIndex];
return new Response(body);
};
5 changes: 5 additions & 0 deletions tests/fixture/routes/greet/[name].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PageProps } from "$fresh/server.ts";

export default function Greet(props: PageProps) {
return <div>Hello {props.params.name}</div>;
}
Loading