feat: add styles for layout
This commit is contained in:
parent
bae5c0d8be
commit
9146a6ead8
7 changed files with 104 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,3 +19,4 @@
|
||||||
|
|
||||||
# sources
|
# sources
|
||||||
!/src
|
!/src
|
||||||
|
!/static
|
||||||
|
|
22
package-lock.json
generated
22
package-lock.json
generated
|
@ -5,7 +5,7 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ren": "github:pleshevskiy/ren"
|
"ren": "file:../../sandbox/ren"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^17.0.21",
|
||||||
|
@ -21,7 +21,6 @@
|
||||||
},
|
},
|
||||||
"../../sandbox/ren": {
|
"../../sandbox/ren": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"extraneous": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^17.0.21",
|
||||||
|
@ -1347,9 +1346,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ren": {
|
"node_modules/ren": {
|
||||||
"version": "0.0.1",
|
"resolved": "../../sandbox/ren",
|
||||||
"resolved": "git+ssh://git@github.com/pleshevskiy/ren.git#9a783eba321b32fdbbb385fee3277fc08e80cb92",
|
"link": true
|
||||||
"license": "MIT"
|
|
||||||
},
|
},
|
||||||
"node_modules/resolve-from": {
|
"node_modules/resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
|
@ -2622,8 +2620,18 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ren": {
|
"ren": {
|
||||||
"version": "git+ssh://git@github.com/pleshevskiy/ren.git#9a783eba321b32fdbbb385fee3277fc08e80cb92",
|
"version": "file:../../sandbox/ren",
|
||||||
"from": "ren@git+ssh://git@github.com:pleshevskiy/ren.git"
|
"requires": {
|
||||||
|
"@types/node": "^17.0.21",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||||
|
"@typescript-eslint/parser": "^5.14.0",
|
||||||
|
"eslint": "^8.10.0",
|
||||||
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"prettier": "^2.5.1",
|
||||||
|
"tsc-watch": "^4.6.0",
|
||||||
|
"typescript": "^4.6.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"resolve-from": {
|
"resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
"typescript": "^4.6.2"
|
"typescript": "^4.6.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ren": "github:pleshevskiy/ren"
|
"ren": "file:../../sandbox/ren"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,18 @@ export async function Layout(page: AnyNode): Promise<Elem> {
|
||||||
return new Elem("html")
|
return new Elem("html")
|
||||||
.withAttr("lang", "ru")
|
.withAttr("lang", "ru")
|
||||||
.withChild(
|
.withChild(
|
||||||
new Elem("head")
|
new Elem("head").withChildren([
|
||||||
.withChild(new Elem("meta").withAttr("charset", "utf-8"))
|
new Elem("meta").withAttr("charset", "utf-8"),
|
||||||
.withChild(new Elem("title").withText("hello world"))
|
new Elem("link").withAttrs({
|
||||||
|
rel: "stylesheet",
|
||||||
|
href: "/static/styles.css",
|
||||||
|
}),
|
||||||
|
new Elem("title").withText("hello world"),
|
||||||
|
])
|
||||||
)
|
)
|
||||||
.withChild(new Elem("body").withChild(page));
|
.withChild(
|
||||||
|
new Elem("body").withChild(
|
||||||
|
new Elem("div").withAttr("id", "root").withChild(page)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { AnyNode, Elem, Frag } from "ren";
|
import { AnyNode, Elem } from "ren";
|
||||||
|
|
||||||
export async function PageLayout(children: AnyNode[]): Promise<Frag> {
|
export async function PageLayout(children: AnyNode[]): Promise<Elem> {
|
||||||
return new Frag()
|
return new Elem("div")
|
||||||
.withChild(Header())
|
.withAttr("id", "main")
|
||||||
.withChild(
|
.withChildren([
|
||||||
new Elem("div").withAttr("class", "content").withChildren(children)
|
Header(),
|
||||||
)
|
new Elem("div").withAttr("class", "content").withChildren(children),
|
||||||
.withChild(Footer());
|
Footer(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Header(): Elem {
|
export function Header(): Elem {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import * as http from "http";
|
import * as http from "http";
|
||||||
|
import * as fs from "fs/promises";
|
||||||
|
import * as path from "path";
|
||||||
import { Layout } from "./components/layout.mjs";
|
import { Layout } from "./components/layout.mjs";
|
||||||
import { ServerConfig } from "./config.mjs";
|
import { ServerConfig } from "./config.mjs";
|
||||||
import { debug, info } from "./log.mjs";
|
import { debug, info } from "./log.mjs";
|
||||||
|
@ -23,6 +25,20 @@ async function handleHttpReq(
|
||||||
|
|
||||||
debug("[server]", { req });
|
debug("[server]", { req });
|
||||||
|
|
||||||
|
if (req.url.startsWith("/static")) {
|
||||||
|
const relFilePath = path.join(process.cwd(), req.url.slice(1));
|
||||||
|
const mimeType = mimeTypeByExt.get(path.extname(relFilePath));
|
||||||
|
|
||||||
|
const fileContent = await fs
|
||||||
|
.readFile(relFilePath, { encoding: "utf-8" })
|
||||||
|
.catch((_e) => null);
|
||||||
|
|
||||||
|
if (fileContent && mimeType) {
|
||||||
|
httpRes.writeHead(200, { "content-type": mimeType }).end(fileContent);
|
||||||
|
} else {
|
||||||
|
httpRes.writeHead(404).end("Not found");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const ren = new StrRenderer();
|
const ren = new StrRenderer();
|
||||||
if (/^[/](?:about[/]?)?$/.test(req.url)) {
|
if (/^[/](?:about[/]?)?$/.test(req.url)) {
|
||||||
httpRes
|
httpRes
|
||||||
|
@ -37,6 +53,7 @@ async function handleHttpReq(
|
||||||
.writeHead(404, { "content-type": "text/html" })
|
.writeHead(404, { "content-type": "text/html" })
|
||||||
.end(await ren.render(Layout(E404())));
|
.end(await ren.render(Layout(E404())));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof InvalidServerRequest) {
|
if (err instanceof InvalidServerRequest) {
|
||||||
httpRes.writeHead(400).end("Bad request");
|
httpRes.writeHead(400).end("Bad request");
|
||||||
|
@ -46,6 +63,11 @@ async function handleHttpReq(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mimeTypeByExt = new Map([
|
||||||
|
[".html", "text/html"],
|
||||||
|
[".css", "text/css"],
|
||||||
|
]);
|
||||||
|
|
||||||
export function tryIntoAppServerRequest(
|
export function tryIntoAppServerRequest(
|
||||||
req: http.IncomingMessage
|
req: http.IncomingMessage
|
||||||
): ServerRequest {
|
): ServerRequest {
|
||||||
|
|
31
static/styles.css
Normal file
31
static/styles.css
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
*, ::before, ::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
Loading…
Reference in a new issue