feat: create styles, update ren

This commit is contained in:
Dmitriy Pleshevskiy 2022-03-20 23:21:38 +03:00
parent eb506f1f40
commit 1c4fb5fb44
9 changed files with 211 additions and 37 deletions

View file

@ -1,3 +1,11 @@
PAR := $(MAKE) -j 128
watch:
$(PAR) hr ts-w
hr:
deno run -A ~/sandbox/hr/server.ts target static
ts-w: ts-w:
npx tsc-watch --onSuccess "node target/scripts/main.mjs" npx tsc-watch --onSuccess "node target/scripts/main.mjs"

View file

@ -1,17 +1,29 @@
import { AnyNode, Elem } from "ren"; import { AnyNode, E, Ea, Elem } from "ren";
import { div } from "../utils.mjs";
export function Layout(page: AnyNode): Elem { export function Layout(page: AnyNode): Elem {
return new Elem("html").withAttr("lang", "ru").withChildren( return Ea("html", { lang: "ru" }, [
new Elem("head").withChildren( E("head", [
new Elem("meta").withAttr("charset", "utf-8"), Ea("meta", { charset: "utf-8" }),
new Elem("link").withAttrs({ Ea("meta", {
name: "viewport",
content: "width=device-width, initial-scale=1",
}),
Ea("link", {
rel: "stylesheet", rel: "stylesheet",
href: "/static/styles.css", href: "/static/styles.css",
}), }),
new Elem("title").withText("hello world") 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();
});`
), ),
new Elem("body").withChildren( ]),
new Elem("div").withAttr("id", "root").withChildren(page) ]);
)
);
} }

View file

@ -1,26 +1,27 @@
import { AnyNode, Elem } from "ren"; import { AnyNode, E, Ea, Elem } from "ren";
import { div } from "../utils.mjs";
export function PageLayout(...children: AnyNode[]): Elem { export function PageLayout(...children: AnyNode[]): Elem {
return new Elem("div") return Ea("div", { id: "main" }, [
.withAttr("id", "main")
.withChildren(
Header(), Header(),
new Elem("div").withAttrs({ class: "content" }).withChildren(...children), Ea("div", { class: "content" }, children),
Footer() Footer(),
); ]);
} }
export function Header(): Elem { export function Header(): Elem {
return new Elem("header").withChildren(HeaderNav()); return Ea("header", { class: "header" }, [
div({ class: "content-width" }, HeaderNav()),
]);
} }
export function HeaderNav(): Elem { export function HeaderNav(): Elem {
return new Elem("nav").withChildren( return E("nav", [
new Elem("a").withAttr("href", "/").withText("About"), Ea("a", { href: "/" }, "Обо мне"),
new Elem("a").withAttr("href", "/works").withText("Works") Ea("a", { href: "/works" }, "Работы"),
); ]);
} }
export function Footer(): Elem { export function Footer(): Elem {
return new Elem("footer").withAttr("class", "footer").withText("footer"); return Ea("footer", { class: "footer" }, "footer");
} }

View file

@ -44,7 +44,7 @@ async function handleHttpReq(
httpRes httpRes
.writeHead(200, { "content-type": "text/html" }) .writeHead(200, { "content-type": "text/html" })
.end(ren.render(Layout(AboutPage()))); .end(ren.render(Layout(AboutPage())));
} else if (/^[/]works[/]?/.test(req.url)) { } else if (/^[/]works[/]?$/.test(req.url)) {
httpRes httpRes
.writeHead(200, { "content-type": "text/html" }) .writeHead(200, { "content-type": "text/html" })
.end(ren.render(Layout(WorksPage()))); .end(ren.render(Layout(WorksPage())));

9
src/utils.mts Normal file
View file

@ -0,0 +1,9 @@
import { E, Ea, Et } from "ren";
export const p = Et.bind(null, "p");
export const h2 = Et.bind(null, "h2");
export const h3 = Et.bind(null, "h3");
export const div = Ea.bind(null, "div");
export const ul = E.bind(null, "ul");
export const li = E.bind(null, "li");

View file

@ -1,6 +1,48 @@
import { PageLayout } from "../components/page_layout.mjs"; import { PageLayout } from "../components/page_layout.mjs";
import { AnyNode, Elem } from "ren"; import { AnyNode } from "ren";
import { div, h3, li, p, ul } from "../utils.mjs";
export function AboutPage(): AnyNode { export function AboutPage(): AnyNode {
return PageLayout(new Elem("p").withText("Привет мир")); return PageLayout(
div({ class: "content-width responsive-typography" }, [
div({}, [
p("Привет!"),
p("Меня зовут Дмитрий Плешевский."),
p(
"Я ведущий разработчик программного обеспечения, архитектор,",
"руководитель команды, а так же ментор."
),
p(
"Open-source проекты моя страсть! Придумываю, экспериментирую,",
"воплощаю, улучшаю проекты в свое свободное время"
),
p(
"Помимо программирования я люблю готовить и проводить время со своей",
"любимой семьей!"
),
]),
div({}, [
h3("Языки программирования"),
p("Предпочитаю: Rust, TS"),
p("Огромный опыт: Rust, TS, JS, Python"),
p("Ограниченный опыт: Haskell, Java, C#"),
]),
div({}, [
h3("Базы данных"),
p("Предпочитаю: Postgres"),
p("Огромный опыт: Postgres, MySQL, Sqlite, mongo"),
]),
div({}, [
h3("Создание приложений"),
ul([
li("Традиционное (SSR + Forms)"),
li("API (REST/GraphQL/WebSocket/EventSource)"),
li("Динамическое (SPA)"),
li("Гибридное (SSR + SPA)"),
li("Консольные"),
li("Кроссплатформенные"),
]),
]),
])
);
} }

View file

@ -1,6 +1,12 @@
import { PageLayout } from "../components/page_layout.mjs"; import { PageLayout } from "../components/page_layout.mjs";
import { AnyNode, Elem } from "ren"; import { AnyNode, Ea } from "ren";
import { div } from "../utils.mjs";
export function E404(): AnyNode { export function E404(): AnyNode {
return PageLayout(new Elem("p").withText("Page not found")); return PageLayout(
div(
{ class: "content-width" },
Ea("h3", { class: "font-h3" }, "Страница не найдена")
)
);
} }

View file

@ -1,6 +1,7 @@
import { PageLayout } from "../components/page_layout.mjs"; import { PageLayout } from "../components/page_layout.mjs";
import { AnyNode, Elem } from "ren"; import { AnyNode } from "ren";
import { div, p } from "../utils.mjs";
export function WorksPage(): AnyNode { export function WorksPage(): AnyNode {
return PageLayout(new Elem("p").withText("Works")); return PageLayout(div({ class: "content-width" }, p("Works")));
} }

View file

@ -1,15 +1,43 @@
*, ::before, ::after { :root {
--min-width: 320px;
--max-width: 1024px;
--default-color-white: hsl(0, 0, 100%);
--color-blue: #1966df;
--default-font-size: 16px;
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto,Oxygen-Sans, Ubuntu, Cantarell, "Segoe UI", Verdana, sans-serif;
--font-weight-regular: 400;
}
*, *::before, *::after {
box-sizing: border-box; box-sizing: border-box;
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
html { html {
background-color: #eee; background-color: var(--default-color-white);
font-size: var(--default-font-size);
line-height: 1;
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
font-weight: var(--font-weight-regular);
font-family: var(--font-family);
min-width: var(--min-width);
} }
html, body { html, body {
height: 100%; height: 100%;
width: 100%;
}
ul, ol {
list-style: none;
} }
#root { #root {
@ -17,11 +45,78 @@ html, body {
align-items: stretch; align-items: stretch;
} }
#root, #main { #root,
#main {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
#main, .content { #main,
.content {
flex: 1 0; flex: 1 0;
} }
.header {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
.content-width {
width: 100%;
max-width: var(--max-width);
margin-left: auto;
margin-right: auto;
}
.responsive-typography h3 {
font-size: 24px;
}
.responsive-typography > div,
.responsive-typography p,
.responsive-typography li {
font-size: 18px;
line-height: 1.5;
}
.responsive-typography ul,
.responsive-typography ol {
width: 100%;
}
.responsive-typography ul li,
.responsive-typography ol li {
position: relative;
width: 100%;
min-height: 1.5rem;
padding-left: 1.5rem;
}
.responsive-typography ul li::before,
.responsive-typography ol li::before {
content: '';
position: absolute;
top: 0;
left: 0;
}
.responsive-typography ul > li::before {
background-color: var(--color-blue);
border-radius: 50%;
width: 0.5rem;
height: 0.5rem;
margin-top: 0.5rem;
margin-left: 0.25rem;
}
.responsive-typography > * + * {
margin-top: 2rem;
}
.responsive-typography > div + div,
.responsive-typography p + p {
margin-top: 1rem;
}
.responsive-typography li + li {
margin-top: 0.5rem;
}