Spaces:
Sleeping
Sleeping
T1ckbase
commited on
Commit
·
d31dfe1
1
Parent(s):
7214d28
deno fresh
Browse files- .gitignore +11 -0
- .vscode/extensions.json +6 -0
- .vscode/settings.json +20 -0
- .vscode/tailwind.json +55 -0
- Dockerfile +18 -0
- README.md +16 -12
- components/Button.tsx +12 -0
- deno.json +27 -0
- dev.ts +8 -0
- fresh.config.ts +9 -0
- fresh.gen.ts +27 -0
- islands/Counter.tsx +16 -0
- main.ts +13 -0
- routes/_404.tsx +27 -0
- routes/_app.tsx +16 -0
- routes/api/joke.ts +21 -0
- routes/greet/[name].tsx +5 -0
- routes/index.tsx +25 -0
- static/favicon.ico +0 -0
- static/logo.svg +6 -0
- static/styles.css +3 -0
- tailwind.config.ts +7 -0
.gitignore
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# dotenv environment variable files
|
2 |
+
.env
|
3 |
+
.env.development.local
|
4 |
+
.env.test.local
|
5 |
+
.env.production.local
|
6 |
+
.env.local
|
7 |
+
|
8 |
+
# Fresh build directory
|
9 |
+
_fresh/
|
10 |
+
# npm dependencies
|
11 |
+
node_modules/
|
.vscode/extensions.json
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"recommendations": [
|
3 |
+
"denoland.vscode-deno",
|
4 |
+
"bradlc.vscode-tailwindcss"
|
5 |
+
]
|
6 |
+
}
|
.vscode/settings.json
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"deno.enable": true,
|
3 |
+
"deno.lint": true,
|
4 |
+
"editor.defaultFormatter": "denoland.vscode-deno",
|
5 |
+
"[typescriptreact]": {
|
6 |
+
"editor.defaultFormatter": "denoland.vscode-deno"
|
7 |
+
},
|
8 |
+
"[typescript]": {
|
9 |
+
"editor.defaultFormatter": "denoland.vscode-deno"
|
10 |
+
},
|
11 |
+
"[javascriptreact]": {
|
12 |
+
"editor.defaultFormatter": "denoland.vscode-deno"
|
13 |
+
},
|
14 |
+
"[javascript]": {
|
15 |
+
"editor.defaultFormatter": "denoland.vscode-deno"
|
16 |
+
},
|
17 |
+
"css.customData": [
|
18 |
+
".vscode/tailwind.json"
|
19 |
+
]
|
20 |
+
}
|
.vscode/tailwind.json
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"version": 1.1,
|
3 |
+
"atDirectives": [
|
4 |
+
{
|
5 |
+
"name": "@tailwind",
|
6 |
+
"description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
|
7 |
+
"references": [
|
8 |
+
{
|
9 |
+
"name": "Tailwind Documentation",
|
10 |
+
"url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
|
11 |
+
}
|
12 |
+
]
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"name": "@apply",
|
16 |
+
"description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.",
|
17 |
+
"references": [
|
18 |
+
{
|
19 |
+
"name": "Tailwind Documentation",
|
20 |
+
"url": "https://tailwindcss.com/docs/functions-and-directives#apply"
|
21 |
+
}
|
22 |
+
]
|
23 |
+
},
|
24 |
+
{
|
25 |
+
"name": "@responsive",
|
26 |
+
"description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n",
|
27 |
+
"references": [
|
28 |
+
{
|
29 |
+
"name": "Tailwind Documentation",
|
30 |
+
"url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
|
31 |
+
}
|
32 |
+
]
|
33 |
+
},
|
34 |
+
{
|
35 |
+
"name": "@screen",
|
36 |
+
"description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n",
|
37 |
+
"references": [
|
38 |
+
{
|
39 |
+
"name": "Tailwind Documentation",
|
40 |
+
"url": "https://tailwindcss.com/docs/functions-and-directives#screen"
|
41 |
+
}
|
42 |
+
]
|
43 |
+
},
|
44 |
+
{
|
45 |
+
"name": "@variants",
|
46 |
+
"description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n",
|
47 |
+
"references": [
|
48 |
+
{
|
49 |
+
"name": "Tailwind Documentation",
|
50 |
+
"url": "https://tailwindcss.com/docs/functions-and-directives#variants"
|
51 |
+
}
|
52 |
+
]
|
53 |
+
}
|
54 |
+
]
|
55 |
+
}
|
Dockerfile
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM denoland/deno:latest
|
2 |
+
|
3 |
+
EXPOSE 7860
|
4 |
+
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Prefer not to run as root.
|
8 |
+
USER deno
|
9 |
+
|
10 |
+
RUN deno install --entrypoint main.ts
|
11 |
+
|
12 |
+
COPY . .
|
13 |
+
|
14 |
+
# Compile the main app so that it doesn't need to be compiled each startup/entry.
|
15 |
+
RUN deno cache main.ts
|
16 |
+
RUN deno task build
|
17 |
+
|
18 |
+
CMD ["run", "-A", "main.ts"]
|
README.md
CHANGED
@@ -1,12 +1,16 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
# Fresh project
|
2 |
+
|
3 |
+
Your new Fresh project is ready to go. You can follow the Fresh "Getting
|
4 |
+
Started" guide here: https://fresh.deno.dev/docs/getting-started
|
5 |
+
|
6 |
+
### Usage
|
7 |
+
|
8 |
+
Make sure to install Deno: https://deno.land/manual/getting_started/installation
|
9 |
+
|
10 |
+
Then start the project:
|
11 |
+
|
12 |
+
```
|
13 |
+
deno task start
|
14 |
+
```
|
15 |
+
|
16 |
+
This will watch the project directory and restart as necessary.
|
components/Button.tsx
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { JSX } from "preact";
|
2 |
+
import { IS_BROWSER } from "$fresh/runtime.ts";
|
3 |
+
|
4 |
+
export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
|
5 |
+
return (
|
6 |
+
<button
|
7 |
+
{...props}
|
8 |
+
disabled={!IS_BROWSER || props.disabled}
|
9 |
+
class="px-2 py-1 border-gray-500 border-2 rounded bg-white hover:bg-gray-200 transition-colors"
|
10 |
+
/>
|
11 |
+
);
|
12 |
+
}
|
deno.json
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"lock": false,
|
3 |
+
"tasks": {
|
4 |
+
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
|
5 |
+
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
|
6 |
+
"manifest": "deno task cli manifest $(pwd)",
|
7 |
+
"start": "deno run -A --watch=static/,routes/ dev.ts",
|
8 |
+
"build": "deno run -A dev.ts build",
|
9 |
+
"preview": "deno run -A main.ts",
|
10 |
+
"update": "deno run -A -r https://fresh.deno.dev/update ."
|
11 |
+
},
|
12 |
+
"lint": { "rules": { "tags": ["fresh", "recommended"] } },
|
13 |
+
"exclude": ["**/_fresh/*"],
|
14 |
+
"imports": {
|
15 |
+
"$fresh/": "https://deno.land/x/[email protected]/",
|
16 |
+
"preact": "https://esm.sh/[email protected]",
|
17 |
+
"preact/": "https://esm.sh/[email protected]/",
|
18 |
+
"@preact/signals": "https://esm.sh/*@preact/[email protected]",
|
19 |
+
"@preact/signals-core": "https://esm.sh/*@preact/[email protected]",
|
20 |
+
"tailwindcss": "npm:[email protected]",
|
21 |
+
"tailwindcss/": "npm:/[email protected]/",
|
22 |
+
"tailwindcss/plugin": "npm:/[email protected]/plugin.js",
|
23 |
+
"$std/": "https://deno.land/[email protected]/"
|
24 |
+
},
|
25 |
+
"compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" },
|
26 |
+
"nodeModulesDir": "auto"
|
27 |
+
}
|
dev.ts
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env -S deno run -A --watch=static/,routes/
|
2 |
+
|
3 |
+
import dev from "$fresh/dev.ts";
|
4 |
+
import config from "./fresh.config.ts";
|
5 |
+
|
6 |
+
import "$std/dotenv/load.ts";
|
7 |
+
|
8 |
+
await dev(import.meta.url, "./main.ts", config);
|
fresh.config.ts
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { defineConfig } from "$fresh/server.ts";
|
2 |
+
import tailwind from "$fresh/plugins/tailwind.ts";
|
3 |
+
|
4 |
+
export default defineConfig({
|
5 |
+
plugins: [tailwind()],
|
6 |
+
server: {
|
7 |
+
port: 7860
|
8 |
+
}
|
9 |
+
});
|
fresh.gen.ts
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// DO NOT EDIT. This file is generated by Fresh.
|
2 |
+
// This file SHOULD be checked into source version control.
|
3 |
+
// This file is automatically updated during development when running `dev.ts`.
|
4 |
+
|
5 |
+
import * as $_404 from "./routes/_404.tsx";
|
6 |
+
import * as $_app from "./routes/_app.tsx";
|
7 |
+
import * as $api_joke from "./routes/api/joke.ts";
|
8 |
+
import * as $greet_name_ from "./routes/greet/[name].tsx";
|
9 |
+
import * as $index from "./routes/index.tsx";
|
10 |
+
import * as $Counter from "./islands/Counter.tsx";
|
11 |
+
import type { Manifest } from "$fresh/server.ts";
|
12 |
+
|
13 |
+
const manifest = {
|
14 |
+
routes: {
|
15 |
+
"./routes/_404.tsx": $_404,
|
16 |
+
"./routes/_app.tsx": $_app,
|
17 |
+
"./routes/api/joke.ts": $api_joke,
|
18 |
+
"./routes/greet/[name].tsx": $greet_name_,
|
19 |
+
"./routes/index.tsx": $index,
|
20 |
+
},
|
21 |
+
islands: {
|
22 |
+
"./islands/Counter.tsx": $Counter,
|
23 |
+
},
|
24 |
+
baseUrl: import.meta.url,
|
25 |
+
} satisfies Manifest;
|
26 |
+
|
27 |
+
export default manifest;
|
islands/Counter.tsx
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { Signal } from "@preact/signals";
|
2 |
+
import { Button } from "../components/Button.tsx";
|
3 |
+
|
4 |
+
interface CounterProps {
|
5 |
+
count: Signal<number>;
|
6 |
+
}
|
7 |
+
|
8 |
+
export default function Counter(props: CounterProps) {
|
9 |
+
return (
|
10 |
+
<div class="flex gap-8 py-6">
|
11 |
+
<Button onClick={() => props.count.value -= 1}>-1</Button>
|
12 |
+
<p class="text-3xl tabular-nums">{props.count}</p>
|
13 |
+
<Button onClick={() => props.count.value += 1}>+1</Button>
|
14 |
+
</div>
|
15 |
+
);
|
16 |
+
}
|
main.ts
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/// <reference no-default-lib="true" />
|
2 |
+
/// <reference lib="dom" />
|
3 |
+
/// <reference lib="dom.iterable" />
|
4 |
+
/// <reference lib="dom.asynciterable" />
|
5 |
+
/// <reference lib="deno.ns" />
|
6 |
+
|
7 |
+
import "$std/dotenv/load.ts";
|
8 |
+
|
9 |
+
import { start } from "$fresh/server.ts";
|
10 |
+
import manifest from "./fresh.gen.ts";
|
11 |
+
import config from "./fresh.config.ts";
|
12 |
+
|
13 |
+
await start(manifest, config);
|
routes/_404.tsx
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { Head } from "$fresh/runtime.ts";
|
2 |
+
|
3 |
+
export default function Error404() {
|
4 |
+
return (
|
5 |
+
<>
|
6 |
+
<Head>
|
7 |
+
<title>404 - Page not found</title>
|
8 |
+
</Head>
|
9 |
+
<div class="px-4 py-8 mx-auto bg-[#86efac]">
|
10 |
+
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
11 |
+
<img
|
12 |
+
class="my-6"
|
13 |
+
src="/logo.svg"
|
14 |
+
width="128"
|
15 |
+
height="128"
|
16 |
+
alt="the Fresh logo: a sliced lemon dripping with juice"
|
17 |
+
/>
|
18 |
+
<h1 class="text-4xl font-bold">404 - Page not found</h1>
|
19 |
+
<p class="my-4">
|
20 |
+
The page you were looking for doesn't exist.
|
21 |
+
</p>
|
22 |
+
<a href="/" class="underline">Go back home</a>
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
</>
|
26 |
+
);
|
27 |
+
}
|
routes/_app.tsx
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { type PageProps } from "$fresh/server.ts";
|
2 |
+
export default function App({ Component }: PageProps) {
|
3 |
+
return (
|
4 |
+
<html>
|
5 |
+
<head>
|
6 |
+
<meta charset="utf-8" />
|
7 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
8 |
+
<title>deno-fresh-test</title>
|
9 |
+
<link rel="stylesheet" href="/styles.css" />
|
10 |
+
</head>
|
11 |
+
<body>
|
12 |
+
<Component />
|
13 |
+
</body>
|
14 |
+
</html>
|
15 |
+
);
|
16 |
+
}
|
routes/api/joke.ts
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { FreshContext } from "$fresh/server.ts";
|
2 |
+
|
3 |
+
// Jokes courtesy of https://punsandoneliners.com/randomness/programmer-jokes/
|
4 |
+
const JOKES = [
|
5 |
+
"Why do Java developers often wear glasses? They can't C#.",
|
6 |
+
"A SQL query walks into a bar, goes up to two tables and says “can I join you?”",
|
7 |
+
"Wasn't hard to crack Forrest Gump's password. 1forrest1.",
|
8 |
+
"I love pressing the F5 key. It's refreshing.",
|
9 |
+
"Called IT support and a chap from Australia came to fix my network connection. I asked “Do you come from a LAN down under?”",
|
10 |
+
"There are 10 types of people in the world. Those who understand binary and those who don't.",
|
11 |
+
"Why are assembly programmers often wet? They work below C level.",
|
12 |
+
"My favourite computer based band is the Black IPs.",
|
13 |
+
"What programme do you use to predict the music tastes of former US presidential candidates? An Al Gore Rhythm.",
|
14 |
+
"An SEO expert walked into a bar, pub, inn, tavern, hostelry, public house.",
|
15 |
+
];
|
16 |
+
|
17 |
+
export const handler = (_req: Request, _ctx: FreshContext): Response => {
|
18 |
+
const randomIndex = Math.floor(Math.random() * JOKES.length);
|
19 |
+
const body = JOKES[randomIndex];
|
20 |
+
return new Response(body);
|
21 |
+
};
|
routes/greet/[name].tsx
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { PageProps } from "$fresh/server.ts";
|
2 |
+
|
3 |
+
export default function Greet(props: PageProps) {
|
4 |
+
return <div>Hello {props.params.name}</div>;
|
5 |
+
}
|
routes/index.tsx
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useSignal } from "@preact/signals";
|
2 |
+
import Counter from "../islands/Counter.tsx";
|
3 |
+
|
4 |
+
export default function Home() {
|
5 |
+
const count = useSignal(3);
|
6 |
+
return (
|
7 |
+
<div class="px-4 py-8 mx-auto bg-[#86efac]">
|
8 |
+
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
9 |
+
<img
|
10 |
+
class="my-6"
|
11 |
+
src="/logo.svg"
|
12 |
+
width="128"
|
13 |
+
height="128"
|
14 |
+
alt="the Fresh logo: a sliced lemon dripping with juice"
|
15 |
+
/>
|
16 |
+
<h1 class="text-4xl font-bold">Welcome to Fresh</h1>
|
17 |
+
<p class="my-4">
|
18 |
+
Try updating this message in the
|
19 |
+
<code class="mx-2">./routes/index.tsx</code> file, and refresh.
|
20 |
+
</p>
|
21 |
+
<Counter count={count} />
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
);
|
25 |
+
}
|
static/favicon.ico
ADDED
|
static/logo.svg
ADDED
|
static/styles.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
@tailwind base;
|
2 |
+
@tailwind components;
|
3 |
+
@tailwind utilities;
|
tailwind.config.ts
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { type Config } from "tailwindcss";
|
2 |
+
|
3 |
+
export default {
|
4 |
+
content: [
|
5 |
+
"{routes,islands,components}/**/*.{ts,tsx,js,jsx}",
|
6 |
+
],
|
7 |
+
} satisfies Config;
|