summaryrefslogtreecommitdiffstats
path: root/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/index.mdx10
-rw-r--r--src/pages/index.tsx64
-rw-r--r--src/pages/pkg/corvos@[version].ts35
-rw-r--r--src/pages/releases/[version].tsx100
-rw-r--r--src/pages/releases/feed.ts19
-rw-r--r--src/pages/releases/index.mdx8
-rw-r--r--src/pages/releases/index.tsx51
-rw-r--r--src/pages/sitemap.ts8
8 files changed, 295 insertions, 0 deletions
diff --git a/src/pages/index.mdx b/src/pages/index.mdx
new file mode 100644
index 0000000..1d35a1d
--- /dev/null
+++ b/src/pages/index.mdx
@@ -0,0 +1,10 @@
1---
2type: "home"
3title: "Corvos ยท static site generator"
4description: "Project website of Corvos, a static site generator for Deno."
5---
6
7import { template } from "./index.tsx";
8export { template };
9
10Corvos is a Static Site Generator with the goal to provide a customizeable, type-safe experience.
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
new file mode 100644
index 0000000..b1581b7
--- /dev/null
+++ b/src/pages/index.tsx
@@ -0,0 +1,64 @@
1import { BaseLayout } from "$/ui/base/BaseLayout.tsx";
2import { ReleaseCard } from "$/ui/components/ReleaseCard.tsx";
3import { SiteHeader } from "$/ui/components/SiteHeader.tsx";
4import { CardList } from "$/ui/layouts/CardList.tsx";
5import { Container } from "$/ui/layouts/Container.tsx";
6import { Button } from "$/ui/objects/Button.tsx";
7import { Divider } from "$/ui/objects/Divider.tsx";
8import { Heading } from "$/ui/objects/Heading.tsx";
9import { Icon } from "$/ui/objects/Icon.tsx";
10import site from "@/corvos.config.ts";
11
12export const template = site.$.template({ type: "home" }, (page, pages) => {
13 const query = site.$.query(pages);
14 const releasesIndex = query.type(".html").match({ type: "releases-index" }).one();
15 const releases = query.type(".html").match({ type: "release" }).many().toArray();
16
17 return (
18 <BaseLayout page={page}>
19 <SiteHeader
20 url={page.url}
21 sm={
22 <div class="l-media__block l-media__block--main">
23 <Heading class="u-mbs-0 u-elp">{page.data.title}</Heading>
24 </div>
25 }
26 />
27
28 <Container fixed="150" pad-inline pad-block class="c-home-banner">
29 <Heading as="h1" class="c-home-banner__intro">
30 <strong class="o-heading__highlight">
31 <a class="p-name u-url u-uid" href={site.$.url("", true)}>
32 Corvos
33 </a>
34 </strong>{" "}
35 &ndash; A static site generator for Deno.
36 </Heading>
37
38 <div class="u-mbs-400 c-subtitle">{{ __html: page.content }}</div>
39
40 <div class="u-mbs-700">
41 <Button
42 href={releasesIndex.url}
43 post={<Icon icon="arrow-right" variant="bold" />}
44 size="xl"
45 variant="primary"
46 wide
47 >
48 Releases
49 </Button>
50 </div>
51 </Container>
52
53 <Divider level="faint" />
54
55 <Container class="u-mbs-neutralize" fixed="150" pad-block pad-inline>
56 <CardList keyboard-nav>
57 {releases.map((page) => (
58 <ReleaseCard page={page} heading-level="h3" list />
59 ))}
60 </CardList>
61 </Container>
62 </BaseLayout>
63 );
64});
diff --git a/src/pages/pkg/corvos@[version].ts b/src/pages/pkg/corvos@[version].ts
new file mode 100644
index 0000000..6dcb65a
--- /dev/null
+++ b/src/pages/pkg/corvos@[version].ts
@@ -0,0 +1,35 @@
1import * as zip from "@zip-js/zip-js";
2import { Page, PipelineStageError } from "corvos";
3import { binaryLoader } from "corvos/core/loaders/binary.ts";
4
5import { strapiLoader } from "$/deps/strapi.tsx";
6import { releaseStrapiSchema } from "$/schemas/releases.ts";
7import site from "@/corvos.config.ts";
8
9export const pages = site.$.pageGenerator(async function* () {
10 for await (const item of strapiLoader.loadCollection("corvos-releases", releaseStrapiSchema, {
11 "populate[0]": "files",
12 "sort[0]": "date:desc",
13 })) {
14 if (item instanceof PipelineStageError) {
15 yield item;
16 continue;
17 }
18
19 const res = await binaryLoader(new URL(item.files.url));
20 const reader = new zip.ZipReader(new zip.Uint8ArrayReader(res.content));
21
22 for await (const entry of reader.getEntriesGenerator()) {
23 if (entry.directory) {
24 continue;
25 }
26
27 yield new Page(
28 ".",
29 new Uint8Array(await entry.arrayBuffer()),
30 { version: item.version },
31 `/pkg/corvos@${item.version}/${entry.filename}`,
32 );
33 }
34 }
35});
diff --git a/src/pages/releases/[version].tsx b/src/pages/releases/[version].tsx
new file mode 100644
index 0000000..84d807a
--- /dev/null
+++ b/src/pages/releases/[version].tsx
@@ -0,0 +1,100 @@
1import { Page, PipelineStageError } from "corvos";
2
3import { strapiLoader } from "$/deps/strapi.tsx";
4import { releaseStrapiSchema } from "$/schemas/releases.ts";
5import { BaseLayout } from "$/ui/base/BaseLayout.tsx";
6import { ReleaseCard } from "$/ui/components/ReleaseCard.tsx";
7import { SiteHeader } from "$/ui/components/SiteHeader.tsx";
8import { CardList } from "$/ui/layouts/CardList.tsx";
9import { Container } from "$/ui/layouts/Container.tsx";
10import { HList } from "$/ui/layouts/HList.tsx";
11import { ActionButton } from "$/ui/objects/ActionButton.tsx";
12import { Badge } from "$/ui/objects/Badge.tsx";
13import { Body } from "$/ui/objects/Body.tsx";
14import { Divider } from "$/ui/objects/Divider.tsx";
15import { Heading } from "$/ui/objects/Heading.tsx";
16import { Icon } from "$/ui/objects/Icon.tsx";
17import site from "@/corvos.config.ts";
18
19export const pages = site.$.pageGenerator(async function* () {
20 for await (const item of strapiLoader.loadCollection("corvos-releases", releaseStrapiSchema, {
21 "populate[0]": "files",
22 "sort[0]": "date:desc",
23 })) {
24 if (item instanceof PipelineStageError) {
25 yield item;
26 } else {
27 yield new Page(".strapi", item.notes ?? [], {
28 ...item,
29 title: `Corvos ${item.version}`,
30 type: "release" as const,
31 });
32 }
33 }
34});
35
36export const template = site.$.template({ type: "release" }, (page, pages) => {
37 const query = site.$.query(pages);
38
39 const feed = query.type(".rss").match({ type: "releases" }).one();
40
41 const prev = query.type(".html").match({ type: "release" }).prev(page);
42 const next = query.type(".html").match({ type: "release" }).next(page);
43
44 return (
45 <BaseLayout page={page}>
46 <SiteHeader
47 mode="compact"
48 url={page.url}
49 end={
50 <div class="l-media__block">
51 <ActionButton
52 align-block
53 class="u-mbs-0"
54 href={feed.url}
55 icon={<Icon icon="rss-simple" variant="bold" />}
56 level="quiet"
57 pill
58 title="RSS Feed"
59 />
60 </div>
61 }
62 >
63 <div class="l-media__block l-media__block--main">
64 <Heading class="u-mbs-0 u-elp">{page.data.title}</Heading>
65 </div>
66 </SiteHeader>
67
68 <Container as="main" class="u-mbs-neutralize h-entry" fixed="150" pad-block pad-inline>
69 <HList aria-label="Categories">
70 <li>
71 <Badge as="strong" pill selected>
72 <time class="dt-published" datetime={page.data.date.toISOString()}>
73 {page.data.date.toLocaleDateString(undefined, {
74 day: "numeric",
75 month: "short",
76 year: "numeric",
77 })}
78 </time>
79 </Badge>
80 </li>
81 </HList>
82
83 <Heading as="h1" class="u-mbs-200 p-name" display highlight level="xxl">
84 {page.data.title}
85 </Heading>
86
87 <Body class="e-content">{{ __html: page.content }}</Body>
88 </Container>
89
90 <Divider level="faint" />
91
92 <Container as="footer" class="u-mbs-neutralize" fixed="150" pad-block pad-inline>
93 <CardList layout="grid">
94 {prev && <ReleaseCard heading-level="h2" page={prev} list />}
95 {next && <ReleaseCard heading-level="h2" page={next} list />}
96 </CardList>
97 </Container>
98 </BaseLayout>
99 );
100});
diff --git a/src/pages/releases/feed.ts b/src/pages/releases/feed.ts
new file mode 100644
index 0000000..b430ca5
--- /dev/null
+++ b/src/pages/releases/feed.ts
@@ -0,0 +1,19 @@
1import type { FeedItem } from "corvos/plugins/feeds.ts";
2
3import site from "@/corvos.config.ts";
4
5export const feeds = site.$.feedGenerator(function* (pages) {
6 const items = site.$.query(pages)
7 .match({ type: "release" })
8 .many()
9 .take(20)
10 .map(
11 (page): FeedItem => ({
12 title: page.data.title,
13 url: page.url,
14 content: page.content,
15 updated: page.data.date,
16 }),
17 );
18 yield { type: "releases", title: `Releases`, url: "/releases/", items };
19});
diff --git a/src/pages/releases/index.mdx b/src/pages/releases/index.mdx
new file mode 100644
index 0000000..6519c76
--- /dev/null
+++ b/src/pages/releases/index.mdx
@@ -0,0 +1,8 @@
1---
2type: "releases-index"
3title: "Releases"
4description: "All releases of Corvos."
5---
6
7import { template } from "./index.tsx";
8export { template };
diff --git a/src/pages/releases/index.tsx b/src/pages/releases/index.tsx
new file mode 100644
index 0000000..132eee7
--- /dev/null
+++ b/src/pages/releases/index.tsx
@@ -0,0 +1,51 @@
1import { BaseLayout } from "$/ui/base/BaseLayout.tsx";
2import { ReleaseCard } from "$/ui/components/ReleaseCard.tsx";
3import { SiteHeader } from "$/ui/components/SiteHeader.tsx";
4import { CardList } from "$/ui/layouts/CardList.tsx";
5import { Container } from "$/ui/layouts/Container.tsx";
6import { ActionButton } from "$/ui/objects/ActionButton.tsx";
7import { Heading } from "$/ui/objects/Heading.tsx";
8import { Icon } from "$/ui/objects/Icon.tsx";
9import { PlaceholderBox } from "$/ui/objects/PlaceholderBox.tsx";
10import site from "@/corvos.config.ts";
11
12export const template = site.$.template({ type: "releases-index" }, (page, pages) => {
13 const query = site.$.query(pages);
14 const items = query.type(".html").match({ type: "release" }).many().toArray();
15 const feed = query.type(".rss").match({ type: "releases" }).one();
16
17 return (
18 <BaseLayout page={page}>
19 <SiteHeader
20 url={page.url}
21 end={
22 <div class="l-media__block">
23 <ActionButton
24 align-block
25 class="u-mbs-0"
26 href={feed.url}
27 icon={<Icon icon="rss-simple" variant="bold" />}
28 level="quiet"
29 pill
30 title="RSS Feed"
31 />
32 </div>
33 }
34 sm={
35 <div class="l-media__block l-media__block--main">
36 <Heading class="u-mbs-0 u-elp">{page.data.title}</Heading>
37 </div>
38 }
39 ></SiteHeader>
40
41 <Container as="main" fixed pad-block pad-inline>
42 <CardList keyboard-nav>
43 {items.map((item) => (
44 <ReleaseCard page={item} heading-level="h2" list />
45 ))}
46 {!items.length && <PlaceholderBox as="em">Nothing there yet</PlaceholderBox>}
47 </CardList>
48 </Container>
49 </BaseLayout>
50 );
51});
diff --git a/src/pages/sitemap.ts b/src/pages/sitemap.ts
new file mode 100644
index 0000000..378a9ed
--- /dev/null
+++ b/src/pages/sitemap.ts
@@ -0,0 +1,8 @@
1import site from "@/corvos.config.ts";
2
3export const sitemap = site.$.sitemap((pages) => ({
4 items: pages.map((page) => ({
5 loc: page.url,
6 lastmod: page.data.modifiedAt,
7 })),
8}));