Skip to content

Commit 003edac

Browse files
committed
feat: top projects list
1 parent 6f4bf96 commit 003edac

File tree

11 files changed

+136
-58
lines changed

11 files changed

+136
-58
lines changed

client_deps.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ export * from "https://raw.githubusercontent.com/lucacasonato/fresh/main/runtime
22
import { IS_BROWSER } from "https://raw.githubusercontent.com/lucacasonato/fresh/main/runtime.ts";
33
import { apply, setup, tw } from "https://esm.sh/[email protected]";
44
export { apply, setup, tw };
5-
export {default as hljs} from "https://jspm.dev/[email protected]";
6-
import {default as hljs} from "https://jspm.dev/[email protected]";
5+
export { default as hljs } from "https://jspm.dev/[email protected]";
76
if (IS_BROWSER) {
87
setup({});
9-
// hljs.highlightAll()
10-
}
8+
}

components/Card.tsx

Whitespace-only changes.

components/Header.tsx

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/** @jsx h */
2+
/** @jsxFrag Fragment */
3+
4+
import { h, tw } from "../client_deps.ts";
5+
6+
export default function Header() {
7+
const container = tw`w-full h-64 flex justify-center items-center flex-col`;
8+
const title = tw`max-w-screen-sm mt-4 font-bold text(4xl gray-900 center)`;
9+
const subtitle = tw`max-w-screen-sm mt-4 text(xl gray-600 center)`;
10+
return (
11+
<section class={container}>
12+
<p class={title}>python.mod.land</p>
13+
<p class={subtitle}>
14+
A fast CDN to use statically typed Python modules in Deno.
15+
</p>
16+
</section>
17+
);
18+
}
19+

components/List.tsx

-20
This file was deleted.

fresh.gen.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
import * as $0 from "./routes/[name].tsx";
66
import * as $1 from "./routes/_render.ts";
77
import * as $2 from "./routes/index.tsx";
8+
import * as $$0 from "./islands/List.tsx";
89

910
const manifest = {
1011
routes: {
1112
"./routes/pkg/[name].tsx": $0,
1213
"./routes/_render.ts": $1,
1314
"./routes/index.tsx": $2,
1415
},
15-
islands: {},
16+
islands: {
17+
"./islands/List.tsx": $$0,
18+
},
1619
baseUrl: import.meta.url,
1720
};
1821

islands/List.tsx

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/** @jsx h */
2+
/** @jsxFrag Fragment */
3+
4+
import { h, tw, useEffect, useState } from "../client_deps.ts";
5+
6+
type Top = {
7+
rows: {
8+
download_count: number;
9+
project: string;
10+
}[];
11+
};
12+
13+
// deno-lint-ignore no-explicit-any
14+
function Card({index, name, count}: any) {
15+
const row = tw`border-b-2 leading-10 hover:bg-gray-100 cursor-pointer`
16+
return (
17+
<tr class={row} onClick={() => {window.location.replace(`pkg/${name}`)}}>
18+
<td class="font-bold">#{index}</td>
19+
<td>{name}</td>
20+
<td class="font-bold">{count}</td>
21+
</tr>
22+
)
23+
}
24+
25+
export default function List() {
26+
const [data, setData] = useState([] as h.JSX.Element[]);
27+
const container = tw`max-w-screen-sm mx-auto px(4 sm:4 md:4) space-y-3`;
28+
const list = tw`max-w-screen-sm mt-4 text(lg gray-600 center)`;
29+
const table = tw`w-full table-auto mt-2`
30+
const header = tw`border(b-2 t-2) leading-10`
31+
useEffect(() => {
32+
fetch(
33+
"https://hugovk.github.io/top-pypi-packages/top-pypi-packages-30-days.min.json",
34+
)
35+
.then((r) => r.json())
36+
.then((r) => {
37+
const top = (r as Top).rows.slice(0, 10);
38+
const data = top.map((mod, i) => <Card index={i+1} name={mod.project} count={mod.download_count} />);
39+
setData(data);
40+
});
41+
}, []);
42+
return (
43+
<div class={container}>
44+
<table class={table}>
45+
<thead class={header}>
46+
<th class="font-bold">No.</th>
47+
<th class="font-bold">Project</th>
48+
<th class="font-bold">Downloads</th>
49+
</thead>
50+
<tbody class={list} onLoad={() => setData([])}>
51+
{data}
52+
</tbody>
53+
</table>
54+
</div>
55+
);
56+
}

routes/[name].tsx

+35-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,43 @@
11
/** @jsx h */
2-
import { Handlers } from "../server_deps.ts";
3-
import { checkExist } from "../utils.ts";
2+
/** @jsxFrag Fragment */
3+
import { Fragment, h, tw, hljs } from "../client_deps.ts";
4+
import Header from "../components/Header.tsx";
5+
import { Handlers, css } from "../server_deps.ts";
6+
import { checkExist, isHtmlRequest } from "../utils.ts";
7+
// deno-lint-ignore no-explicit-any
8+
function Block(props: any) {
9+
const block = tw`bg-gray-100 p-3 hljs rounded`;
10+
// deno-lint-ignore no-explicit-any
11+
const code = (hljs as any).highlight(props.code, {language: 'javascript'}).value
12+
return (
13+
<div class={block}>
14+
<pre><code dangerouslySetInnerHTML={{__html: code}}></code></pre>
15+
</div>
16+
);
17+
}
418
export const handler: Handlers = {
519
GET(_, ctx) {
6-
let exists: boolean;
7-
checkExist(ctx.params.name, (_exists: boolean) => {
8-
exists = _exists;
9-
});
10-
const mod = exists!
11-
? `import { python } from "https://deno.land/x/[email protected]/mod.ts";
12-
export const python_mod = python.import("${ctx.params.name}");
13-
export default python_mod;`
14-
: `404 not found`;
20+
if (isHtmlRequest(_)) {
21+
return ctx.render()
22+
}
23+
const mod =
24+
`import { python } from "https://deno.land/x/[email protected]/mod.ts";\nexport const python_mod = python.import("${ctx.params.name}");\nexport default python_mod;`;
1525
return new Response(mod, {
1626
headers: { "Content-Type": "application/javascript" },
1727
});
1828
},
1929
};
30+
31+
export default function ModulePage(ctx: any) {
32+
const main = tw`max-w-screen-sm mx-auto px(4 sm:4 md:4) space-y-3 mb-8`;
33+
const text = tw`text-gray-600 text-lg`;
34+
return <>
35+
<style>{css}</style>
36+
<Header/>
37+
<section class={main}>
38+
<p class={text}>Import from a URL</p>
39+
<Block code={`import ${ctx.params.name.replace(".","")} from "https://python.mod.land/pkg/${ctx.params.name}"`}></Block>
40+
</section>
41+
</>
42+
}
43+

routes/_render.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// This module adds twind support.
2-
31
import { setup } from "../client_deps.ts";
42
import { RenderContext, RenderFn, virtualSheet } from "../server_deps.ts";
53

routes/index.tsx

+11-19
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
/** @jsxFrag Fragment */
33

44
import { Fragment, h, Head, hljs, tw } from "../client_deps.ts";
5-
import { List } from "../components/List.tsx";
5+
import { css } from "../server_deps.ts";
6+
import Header from "../components/Header.tsx";
7+
import List from "../islands/List.tsx";
68

79
export default function Index() {
8-
const main = tw`max-w-screen-sm mx-auto px(4 sm:4 md:4) space-y-3`;
10+
const main = tw`max-w-screen-sm mx-auto px(4 sm:4 md:4) space-y-3 mb-8`;
11+
const projects = tw`max-w-screen-sm mx-auto px(4 sm:4 md:4) space-y-3 mb-8 `;
912
const text = tw`text-gray-600 text-lg`;
1013

1114
return (
@@ -16,35 +19,24 @@ export default function Index() {
1619
name="description"
1720
content="A fast CDN to use statically typed Python modules in Deno."
1821
/>
19-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.0/styles/default.min.css"/>
22+
<style>{css}</style>
2023
</Head>
21-
<Hero />
24+
<Header/>
2225
<section class={main}>
2326
<p class={text}>Import from a URL</p>
2427
<Block code={'import np from "https://python.mod.land/pkg/numpy"'}></Block>
28+
</section>
29+
<section class={projects}>
30+
<p class={text}>Top Projects</p>
2531
<List/>
2632
</section>
2733
</>
2834
);
2935
}
3036

31-
function Hero() {
32-
const container = tw`w-full h-64 flex justify-center items-center flex-col`;
33-
const title = tw`max-w-screen-sm mt-4 font-bold text(4xl gray-900 center)`;
34-
const subtitle = tw`max-w-screen-sm mt-4 text(xl gray-600 center)`;
35-
return (
36-
<section class={container}>
37-
<p class={title}>python.mod.land</p>
38-
<p class={subtitle}>
39-
A fast CDN to use statically typed Python modules in Deno.
40-
</p>
41-
</section>
42-
);
43-
}
44-
4537
// deno-lint-ignore no-explicit-any
4638
function Block(props: any) {
47-
const block = tw`bg-gray-100 p-3`;
39+
const block = tw`bg-gray-100 p-3 hljs rounded`;
4840
// deno-lint-ignore no-explicit-any
4941
const code = (hljs as any).highlight(props.code, {language: 'javascript'}).value
5042
return (

server_deps.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
export * from "https://raw.githubusercontent.com/lucacasonato/fresh/main/server.ts";
22

3-
export { virtualSheet } from "https://esm.sh/[email protected]/sheets";
3+
export { virtualSheet } from "https://esm.sh/[email protected]/sheets";
4+
const link =
5+
`https://raw.githubusercontent.com/highlightjs/highlight.js/main/src/styles/atom-one-dark.css`;
6+
export const css = await fetch(link).then((file) => file.text())

utils.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
import { accepts } from "https://deno.land/x/[email protected]/negotiation.ts";
12
// deno-lint-ignore no-explicit-any
23
export function checkExist(name: string, callback: (exists: any) => void) {
34
fetch(`https://pypi.org/pypi/${name}`, { method: "head" }).then((res) => {
45
callback(res.status === 200);
56
});
67
}
8+
9+
export function isHtmlRequest(req: Request) {
10+
return accepts(req, "application/*", "text/html") === "text/html";
11+
}

0 commit comments

Comments
 (0)