Skip to content

Commit

Permalink
feat: use mdx instead of gfm
Browse files Browse the repository at this point in the history
  • Loading branch information
lishaduck committed Jan 21, 2024
1 parent a2035b7 commit 970ed4e
Show file tree
Hide file tree
Showing 20 changed files with 240 additions and 61 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
"tailwindCSS.experimental.classRegex": [
"tw`([^`]*)",
["tw\\(([^\\)]*)\\)", "`([^`]*)`"]
]
],
"explorer.fileNesting.patterns": {
"*.mdx": "${capture}.js"
}
}
4 changes: 2 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test:coverage:genhtml": "genhtml -o cov/html cov/cov.lcov",
"manifest": "deno task cli manifest $(pwd)",
"start": "deno run -A --watch=src/ src/dev.ts",
"build": "deno run -A src/dev.ts build",
"build": "deno run -A tool/compile-mdx.ts && deno run -A src/dev.ts build",
"preview": "deno run -A src/main.ts",
"update": "deno run -A -r https://fresh.deno.dev/update .",
"esm": "deno run -A https://esm.sh/v135",
Expand All @@ -25,9 +25,9 @@
"imports": {
"$std/": "https://deno.land/std@0.211.0/",
"$fresh/": "https://deno.land/x/fresh@1.6.1/",
"$gfm": "https://deno.land/x/gfm@0.3.0/mod.ts",
"$tabler_icons/": "https://deno.land/x/tabler_icons_tsx@0.0.6/tsx/",
"@headlessui/react": "https://esm.sh/v135/*@headlessui/react@1.7.17",
"@mdx-js/mdx": "npm:@mdx-js/mdx",
"@preact/signals-core": "https://esm.sh/v135/@preact/signals-core@1.5.1",
"@preact/signals": "https://esm.sh/v135/*@preact/signals@1.2.2",
"preact": "https://esm.sh/v135/preact@10.19.3",
Expand Down
16 changes: 16 additions & 0 deletions src/content/getting-started.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Fragment as _Fragment, jsx as _jsx} from "preact/jsx-runtime";
export const title = "Getting Started";
export const description = "Getting Started with green energy!";
export const category = "green";
function _createMdxContent(props) {
return _jsx(_Fragment, {});
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || ({});
return MDXLayout ? _jsx(MDXLayout, {
...props,
children: _jsx(_createMdxContent, {
...props
})
}) : _createMdxContent(props);
}
5 changes: 0 additions & 5 deletions src/content/getting-started.md

This file was deleted.

3 changes: 3 additions & 0 deletions src/content/getting-started.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const title = "Getting Started";
export const description = "Getting Started with green energy!";
export const category = "green";
29 changes: 29 additions & 0 deletions src/content/guarantees-in-life.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "preact/jsx-runtime";
export const title = "Taxes";
export const description = "\"There are only two guarantees in life: death and taxes.\"";
export const category = "monies";
function _createMdxContent(props) {
const _components = {
h2: "h2",
p: "p",
...props.components
};
return _jsxs(_Fragment, {
children: [_jsx(_components.h2, {
children: "Tax Rebates"
}), "\n", _jsx(_components.p, {
children: "Looking for information about tax rebates and incentives for green\nenergy?"
}), "\n", _jsx(_components.p, {
children: "Please keep in mind that, like death, taxes are a certainty, and thus\ntax evasion is illegal. If you wish to avoid taxes, please consult a\nregistered accountant rather than willy-nilly skipping them based on\nour advice."
})]
});
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || ({});
return MDXLayout ? _jsx(MDXLayout, {
...props,
children: _jsx(_createMdxContent, {
...props
})
}) : _createMdxContent(props);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
---
title: Taxes
description: "There are only two guarantees in life: death and taxes."
category: monies
---
export const title = "Taxes"
export const description = "\"There are only two guarantees in life: death and taxes.\""
export const category = "monies"

## Tax Rebates

Expand Down
16 changes: 16 additions & 0 deletions src/content/pricing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Fragment as _Fragment, jsx as _jsx} from "preact/jsx-runtime";
export const title = "Pricing";
export const description = "Pricing for green energy";
export const category = "monies";
function _createMdxContent(props) {
return _jsx(_Fragment, {});
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || ({});
return MDXLayout ? _jsx(MDXLayout, {
...props,
children: _jsx(_createMdxContent, {
...props
})
}) : _createMdxContent(props);
}
5 changes: 0 additions & 5 deletions src/content/pricing.md

This file was deleted.

3 changes: 3 additions & 0 deletions src/content/pricing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const title = "Pricing";
export const description = "Pricing for green energy";
export const category = "monies";
16 changes: 16 additions & 0 deletions src/content/programs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Fragment as _Fragment, jsx as _jsx} from "preact/jsx-runtime";
export const title = "Programs";
export const description = "Green energy programs";
export const category = "green";
function _createMdxContent(props) {
return _jsx(_Fragment, {});
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || ({});
return MDXLayout ? _jsx(MDXLayout, {
...props,
children: _jsx(_createMdxContent, {
...props
})
}) : _createMdxContent(props);
}
5 changes: 0 additions & 5 deletions src/content/programs.md

This file was deleted.

3 changes: 3 additions & 0 deletions src/content/programs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const title = "Programs";
export const description = "Green energy programs";
export const category = "green";
46 changes: 46 additions & 0 deletions src/content/solar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from "preact/jsx-runtime";
export const title = "Solar Energy Solutions";
export const description = "Solar Energy is an undertapped energy resource.";
export const category = "solar";
function _createMdxContent(props) {
const _components = {
a: "a",
em: "em",
h2: "h2",
p: "p",
...props.components
};
return _jsxs(_Fragment, {
children: [_jsx(_components.h2, {
children: "What is it?"
}), "\n", _jsx(_components.p, {
children: "Solar panels are useful. They collect energy from the sun, and can be placed on roofs discreetly."
}), "\n", _jsx(_components.h2, {
children: "Cost"
}), "\n", _jsx(_components.h2, {
children: "Tax Rebates"
}), "\n", _jsx(_components.h2, {
children: "Best Practices"
}), "\n", _jsx(_components.h2, {
children: "Buy Now"
}), "\n", _jsxs(_components.p, {
children: ["You can use our ", _jsx(_components.a, {
href: "/calculator/",
children: "online calculator"
}), " to calculate costs and buy ", _jsx(_components.em, {
children: "your"
}), " solar energy solution today!"]
}), "\n", _jsx(_components.h2, {
children: "Sources"
})]
});
}
export default function MDXContent(props = {}) {
const {wrapper: MDXLayout} = props.components || ({});
return MDXLayout ? _jsx(MDXLayout, {
...props,
children: _jsx(_createMdxContent, {
...props
})
}) : _createMdxContent(props);
}
8 changes: 3 additions & 5 deletions src/content/solar.md → src/content/solar.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
---
title: Solar Energy Solutions
description: Solar Energy is an undertapped energy resource.
category: solar
---
export const title = "Solar Energy Solutions";
export const description = "Solar Energy is an undertapped energy resource.";
export const category = "solar";

## What is it?

Expand Down
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ import "$std/dotenv/load.ts";
import { start } from "$fresh/server.ts";
import config from "./fresh.config.ts";
import manifest from "./fresh.gen.ts";
import "./utils/imports.ts";

await start(manifest, config);
38 changes: 17 additions & 21 deletions src/routes/solutions/[slug].tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
import { Head } from "$fresh/runtime.ts";
import type { Handlers, PageProps } from "$fresh/server.ts";
import { render } from "$gfm";
import type { JSX } from "preact";
import { Cover } from "../../components/Cover.tsx";
import { Meta } from "../../components/Meta.tsx";
import type { FreshContextHelper } from "../../utils/handlers.ts";
import { IconSolarPanel } from "../../utils/icons.ts";
import { type SolutionPage, solutions } from "../../utils/solutions.ts";
import type { MDXFile } from "../../utils/solutions.ts";

export interface SolutionProps {
readonly page: SolutionPage;
readonly page: MDXFile;
}

export const handler: Handlers<SolutionProps> = {
GET(
async GET(
_req: Request,
ctx: FreshContextHelper<SolutionProps>,
): Response | Promise<Response> {
const solution = solutions.find(
(page: SolutionPage): boolean => page?.slug === ctx.params["slug"],
);
): Promise<Response> {
try {
const file: MDXFile = await import(
`../../content/${ctx.params["slug"]}.js`
);

return solution === undefined
? ctx.renderNotFound()
: ctx.render({ page: solution });
return ctx.render({ page: file });
} catch {
return ctx.renderNotFound();
}
},
};

export default function Solution({
data,
}: PageProps<SolutionProps>): JSX.Element {
const pageTitle = data.page.data.title;
const description = data.page.data.description;
const pageTitle = data.page.title;
const description = data.page.description;

return (
<>
Expand All @@ -50,14 +51,9 @@ export default function Solution({
>
<p class="my-4 dark:text-white">{description}</p>
</Cover>
<article
class="p-10 prose prose-lg dark:prose-invert max-w-none prose-headings:flex prose-headings:flex-row prose-headings:items-center bg-slate-200 dark:bg-slate-800"
// biome-ignore lint/security/noDangerouslySetInnerHtml: required for markdown w/out a custom renderer
dangerouslySetInnerHTML={{
// TODO(lishaduck): AOT compile this using MDX.
__html: render(data.page.markdown ?? ""),
}}
/>
<article class="p-10 prose prose-lg dark:prose-invert max-w-none prose-headings:flex prose-headings:flex-row prose-headings:items-center bg-slate-200 dark:bg-slate-800">
<data.page.default />
</article>
</main>
</>
);
Expand Down
5 changes: 5 additions & 0 deletions src/utils/imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
async () => await import("../content/programs.js");
async () => await import("../content/pricing.js");
async () => await import("../content/guarantees-in-life.js");
async () => await import("../content/getting-started.js");
async () => await import("../content/solar.js");
25 changes: 13 additions & 12 deletions src/utils/solutions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { extract } from "$std/front_matter/yaml.ts";
import { join } from "$std/path/posix/join.ts";
import type { ComponentType } from "preact";
import { z } from "zod";

export type SolutionPage = z.infer<typeof solutionPageSchema>;
Expand All @@ -18,7 +17,6 @@ const solutionDataSchema = z
const solutionPageSchema = z
.object({
slug: z.string(), // The slug of the solution without a trailing slash.
markdown: z.string(),
data: solutionDataSchema,
})
.strict()
Expand All @@ -38,19 +36,24 @@ const solutionPagesSchema = solutionPagesNullableSchema.transform(
),
);

export interface MDXFile extends SolutionData {
readonly default: ComponentType<{ readonly [x: string]: unknown }>;
}

const dir = "src/content";
const categorySort = ["green", "monies", "solar"];

export const solutions = await getSolutions();

/** Get all solutions. */
export async function getSolutions(): Promise<SolutionPages> {
const files = Deno.readDir(dir);
const promises = [];
for await (const file of files) {
const slug = file.name.replace(".md", "");
promises.push(getSolution(slug));
for await (const entry of Deno.readDir(dir)) {
if (entry.isFile && entry.name.match(/mdx?/)) {
promises.push(getSolution(entry.name.replace(/\.[^\.]*$/, "")));
}
}

const unparsedSolutions = await Promise.all(promises);
const solutions = solutionPagesSchema.parse(unparsedSolutions);

Expand All @@ -60,17 +63,15 @@ export async function getSolutions(): Promise<SolutionPages> {
categorySort.indexOf(b.data.category),
);
}

/** Get a solution. */
export async function getSolution(
slug: string,
): Promise<SolutionPage | undefined> {
try {
const markdown = await Deno.readTextFile(join(dir, `${slug}.md`));
const extracted = extract(markdown);
const frontmatter = solutionDataSchema.parse(extracted.attrs);
const solution = { frontmatter, body: extracted.body };
const file: MDXFile = await import(`../content/${slug}.js`);

return { markdown: solution.body, data: solution.frontmatter, slug };
return { data: file, slug };
} catch (error) {
console.error(error);
return undefined;
Expand Down
Loading

0 comments on commit 970ed4e

Please sign in to comment.