From 58c0f976afbc4f7337b9bc9079cb1a2ef3e9c144 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Mon, 21 Mar 2022 22:50:07 +0300 Subject: [PATCH] feat: add context and env --- makefile | 2 +- src/components/layout.mts | 22 ++++++++++++---------- src/components/page_layout.mts | 27 +++++++++++++++++---------- src/config.mts | 8 +++++++- src/context.mts | 3 +++ src/main.mts | 4 +--- src/server.mts | 19 ++++++++++++------- src/views/about.mts | 4 +++- src/views/e404.mts | 4 +++- src/views/works.mts | 5 +++-- static/styles.css | 28 +++++++++++++++++++++++++++- 11 files changed, 89 insertions(+), 37 deletions(-) create mode 100644 src/context.mts diff --git a/makefile b/makefile index 407cd6d..6ae86ed 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ hr: deno run -A ~/sandbox/hr/server.ts target static ts-w: - npx tsc-watch --onSuccess "node target/scripts/main.mjs" + NODE_ENV=develop npx tsc-watch --onSuccess "node target/scripts/main.mjs" clean: rm -rf target diff --git a/src/components/layout.mts b/src/components/layout.mts index 58cb213..dbd164f 100644 --- a/src/components/layout.mts +++ b/src/components/layout.mts @@ -1,4 +1,5 @@ import { AnyNode, E, Ea, Elem } from "ren"; +import { config } from "../config.mjs"; import { div } from "../utils.mjs"; export function Layout(page: AnyNode): Elem { @@ -15,15 +16,16 @@ export function Layout(page: AnyNode): Elem { }), E("title", "hello world"), ]), - E("body", [ - div({ id: "root" }, page), - E( - "script", - `const ws = new WebSocket("ws://localhost:30001"); - ws.addEventListener("message", (m) => { - if (m.data === "RELOAD") location.reload(); - });` - ), - ]), + E("body", [div({ id: "root" }, page), config.isDev && HotReloadScript()]), ]); } + +function HotReloadScript(): Elem { + return E( + "script", + `const ws = new WebSocket("ws://localhost:30001"); + ws.addEventListener("message", (m) => { + if (m.data === "RELOAD") location.reload(); + });` + ); +} diff --git a/src/components/page_layout.mts b/src/components/page_layout.mts index 9eac452..1bc3e9c 100644 --- a/src/components/page_layout.mts +++ b/src/components/page_layout.mts @@ -1,27 +1,34 @@ -import { AnyNode, E, Ea, Elem } from "ren"; +import { AnyNode, Ea, Elem } from "ren"; +import { Context } from "../context.mjs"; import { div } from "../utils.mjs"; -export function PageLayout(...children: AnyNode[]): Elem { +export function PageLayout(ctx: Context, ...children: AnyNode[]): Elem { return Ea("div", { id: "main" }, [ - Header(), + Header(ctx.locPath), Ea("div", { class: "content" }, children), - Footer(), + // Footer(), ]); } -export function Header(): Elem { +export function Header(locPath: string): Elem { return Ea("header", { class: "header" }, [ - div({ class: "content-width" }, HeaderNav()), + div({ class: "content-width" }, HeaderNav(locPath)), ]); } -export function HeaderNav(): Elem { - return E("nav", [ - Ea("a", { href: "/" }, "Обо мне"), - Ea("a", { href: "/works" }, "Работы"), +export function HeaderNav(locPath: string): Elem { + return Ea("nav", { class: "main-menu" }, [ + NavLink(locPath, "/", "Обо мне"), + NavLink(locPath, "/works", "Работы"), ]); } +export function NavLink(locPath: string, href: string, text: string): Elem { + const attrs = { href }; + if (locPath === href) attrs["aria-current"] = "true"; + return Ea("a", attrs, text); +} + export function Footer(): Elem { return Ea("footer", { class: "footer" }, "footer"); } diff --git a/src/config.mts b/src/config.mts index b660db8..4314470 100644 --- a/src/config.mts +++ b/src/config.mts @@ -1,8 +1,14 @@ +export const config = createConfig(); + export function createConfig(): Config { - return { server: { port: 30000 } }; + return { + isDev: process.env.NODE_ENV === "develop", + server: { port: 30000 }, + }; } export interface Config { + isDev: boolean; server: ServerConfig; } diff --git a/src/context.mts b/src/context.mts new file mode 100644 index 0000000..96a571b --- /dev/null +++ b/src/context.mts @@ -0,0 +1,3 @@ +export interface Context { + locPath: string; +} diff --git a/src/main.mts b/src/main.mts index 586973c..4fb396c 100644 --- a/src/main.mts +++ b/src/main.mts @@ -1,9 +1,7 @@ -import { createConfig } from "./config.mjs"; import { createServer } from "./server.mjs"; main(); function main(): void { - const config = createConfig(); - createServer(config.server); + createServer(); } diff --git a/src/server.mts b/src/server.mts index 46d23ae..be03308 100644 --- a/src/server.mts +++ b/src/server.mts @@ -2,17 +2,21 @@ import * as http from "http"; import * as fs from "fs/promises"; import * as path from "path"; import { Layout } from "./components/layout.mjs"; -import { ServerConfig } from "./config.mjs"; +import { config } from "./config.mjs"; import { debug, info } from "./log.mjs"; import { StrRenderer } from "ren"; import { AboutPage } from "./views/about.mjs"; import { E404 } from "./views/e404.mjs"; import { WorksPage } from "./views/works.mjs"; +import { Context } from "./context.mjs"; -export function createServer(cfg: ServerConfig): void { +export function createServer(): void { const server = http.createServer(handleHttpReq); - server.listen(cfg.port, () => { - info("[server]", `Server listening at http://localhost:${cfg.port}`); + server.listen(config.server.port, () => { + info( + "[server]", + `Server listening at http://localhost:${config.server.port}` + ); }); } @@ -39,19 +43,20 @@ async function handleHttpReq( httpRes.writeHead(404).end("Not found"); } } else { + const ctx: Context = { locPath: req.url }; const ren = new StrRenderer(); if (/^[/](?:about[/]?)?$/.test(req.url)) { httpRes .writeHead(200, { "content-type": "text/html" }) - .end(ren.render(Layout(AboutPage()))); + .end(ren.render(Layout(AboutPage(ctx)))); } else if (/^[/]works[/]?$/.test(req.url)) { httpRes .writeHead(200, { "content-type": "text/html" }) - .end(ren.render(Layout(WorksPage()))); + .end(ren.render(Layout(WorksPage(ctx)))); } else { httpRes .writeHead(404, { "content-type": "text/html" }) - .end(ren.render(Layout(E404()))); + .end(ren.render(Layout(E404(ctx)))); } } } catch (err) { diff --git a/src/views/about.mts b/src/views/about.mts index 11df5b2..27a9815 100644 --- a/src/views/about.mts +++ b/src/views/about.mts @@ -1,9 +1,11 @@ import { PageLayout } from "../components/page_layout.mjs"; import { AnyNode } from "ren"; import { div, h3, li, p, ul } from "../utils.mjs"; +import { Context } from "../context.mjs"; -export function AboutPage(): AnyNode { +export function AboutPage(ctx: Context): AnyNode { return PageLayout( + ctx, div({ class: "content-width responsive-typography" }, [ div({}, [ p("Привет!"), diff --git a/src/views/e404.mts b/src/views/e404.mts index 471fd03..f77fce9 100644 --- a/src/views/e404.mts +++ b/src/views/e404.mts @@ -1,9 +1,11 @@ import { PageLayout } from "../components/page_layout.mjs"; import { AnyNode, Ea } from "ren"; import { div } from "../utils.mjs"; +import { Context } from "../context.mjs"; -export function E404(): AnyNode { +export function E404(ctx: Context): AnyNode { return PageLayout( + ctx, div( { class: "content-width" }, Ea("h3", { class: "font-h3" }, "Страница не найдена") diff --git a/src/views/works.mts b/src/views/works.mts index fc0905e..648e3ac 100644 --- a/src/views/works.mts +++ b/src/views/works.mts @@ -1,7 +1,8 @@ import { PageLayout } from "../components/page_layout.mjs"; import { AnyNode } from "ren"; import { div, p } from "../utils.mjs"; +import { Context } from "../context.mjs"; -export function WorksPage(): AnyNode { - return PageLayout(div({ class: "content-width" }, p("Works"))); +export function WorksPage(ctx: Context): AnyNode { + return PageLayout(ctx, div({ class: "content-width" }, p("Works"))); } diff --git a/static/styles.css b/static/styles.css index b9fe8dc..3a47f3f 100644 --- a/static/styles.css +++ b/static/styles.css @@ -2,7 +2,7 @@ --min-width: 320px; --max-width: 1024px; - --default-color-white: hsl(0, 0, 100%); + --default-color-white: #ffffff; --color-blue: #1966df; --default-font-size: 16px; @@ -61,6 +61,32 @@ ul, ol { padding-bottom: 1.5rem; } +.main-menu { + display: flex; + flex-direction: row; +} + +// anim +.main-menu > a { + transition: all .2s ease-in-out; +} + +.main-menu > a { + color: var(--color-blue); + padding: 0.5rem; + border-radius: 6px; + border: 1px solid var(--color-blue); + text-decoration: none; +} +.main-menu > a:hover, +.main-menu > a[aria-current]:not([aria-current=""]) { + color: var(--default-color-white); + background-color: var(--color-blue); +} +.main-menu > a:not(:last-child) { + margin-right: 1rem; +} + .content-width { width: 100%; max-width: var(--max-width);