abstract art created
This commit is contained in:
parent
d1ec92f4fd
commit
a8216d1226
3 changed files with 97 additions and 9 deletions
13
html/html.ts
13
html/html.ts
|
@ -83,14 +83,21 @@ function indent(str: string, amount = 4, char = " "): string {
|
||||||
.join("\n");
|
.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// incomplete, obviously.
|
||||||
|
const NON_SELF_CLOSING = ["div", "p", "a"];
|
||||||
|
|
||||||
function render_elem(
|
function render_elem(
|
||||||
{ tag, attributes, children }: NonText,
|
{ tag, attributes, children }: NonText,
|
||||||
mini = false,
|
mini = false,
|
||||||
): string {
|
): string {
|
||||||
if (children.length == 0) {
|
if (children.length == 0) {
|
||||||
return (
|
if (!NON_SELF_CLOSING.includes(tag)) {
|
||||||
`<${tag}${render_attributes(attributes)}` + (mini ? "/>" : " />")
|
return (
|
||||||
);
|
`<${tag}${render_attributes(attributes)}` + (mini ? "/>" : " />")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return `<${tag}${render_attributes(attributes)}></${tag}>`;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let inner = "";
|
let inner = "";
|
||||||
let string_last = false;
|
let string_last = false;
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { Attributes, fr, Html, Prop } from "../html.ts";
|
import { fr, Html, Prop } from "../html.ts";
|
||||||
|
|
||||||
type SadProp = Prop | undefined | Html | Html[];
|
type SadProp = Prop | undefined | Html | Html[];
|
||||||
export type Component = (
|
export type Component = (
|
||||||
attributes: Attributes,
|
props: CProps,
|
||||||
children: Html[],
|
children: Html[],
|
||||||
) => Html;
|
) => Html;
|
||||||
|
|
||||||
|
export type CProps = {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
[key: string]: typeof key extends "children" ? never : SadProp;
|
[key: string]: typeof key extends "children" ? never : SadProp;
|
||||||
children: undefined | Html | Html[];
|
children: undefined | Html | Html[];
|
||||||
|
@ -16,12 +20,14 @@ export function create_element(
|
||||||
props_?: Props,
|
props_?: Props,
|
||||||
): Html {
|
): Html {
|
||||||
const props: Props = props_ ?? { children: [] };
|
const props: Props = props_ ?? { children: [] };
|
||||||
const children: Html[] = [props.children ?? []].flat();
|
const children: Html[] = [props.children ?? []].flat().filter((c) =>
|
||||||
const attributes: Attributes = {};
|
typeof c == "string" || typeof c == "object"
|
||||||
|
);
|
||||||
|
const attributes: CProps = {};
|
||||||
|
|
||||||
for (const [key, val] of Object.entries(props)) {
|
for (const [key, val] of Object.entries(props)) {
|
||||||
if (
|
if (
|
||||||
key == "children" || typeof val == "undefined" || typeof val == "object"
|
key == "children" || typeof val == "undefined"
|
||||||
) continue;
|
) continue;
|
||||||
attributes[key] = val;
|
attributes[key] = val;
|
||||||
}
|
}
|
||||||
|
|
77
html/ttt.tsx
77
html/ttt.tsx
|
@ -1,2 +1,77 @@
|
||||||
import { Html, render } from "./html.ts";
|
import { Html, debug_render } from "./html.ts";
|
||||||
import { Component } from "./jsx/jsx-runtime.ts";
|
import { Component } from "./jsx/jsx-runtime.ts";
|
||||||
|
|
||||||
|
type Square = "x" | "o" | "empty";
|
||||||
|
type Row = [Square, Square, Square];
|
||||||
|
type Board = [Row, Row, Row];
|
||||||
|
type SquareIdx = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||||||
|
|
||||||
|
const empty_row: Row = ["empty", "empty", "empty"];
|
||||||
|
const empty_board: Board = [empty_row, empty_row, empty_row];
|
||||||
|
//{ board: [r1, r2, r3] }
|
||||||
|
|
||||||
|
const square_of_turn = (turn: number): Square => (turn % 2 == 0 ? "x" : "o");
|
||||||
|
function game_over([[s1, s2, s3], [s4, s5, s6], [s7, s8, s9]]: Board): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: strike out and such
|
||||||
|
const Board: Component = ({ board, turn = 0 }) => (
|
||||||
|
<div class="state">
|
||||||
|
{game_over(board) ? (
|
||||||
|
<div class="whose-turn game-over">Game over!</div>
|
||||||
|
) : (
|
||||||
|
<div class="whose-turn">It's {square_of_turn(turn)}'s turn!</div>
|
||||||
|
)}
|
||||||
|
<div class="board">
|
||||||
|
<Row board={board} idx={0} turn={turn} />
|
||||||
|
<Row board={board} idx={1} turn={turn} />
|
||||||
|
<Row board={board} idx={2} turn={turn} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Row: Component = ({ board, idx, turn }) => (
|
||||||
|
<div class="row">
|
||||||
|
<Cell board={board} idx={idx + 0} turn={turn} />
|
||||||
|
<Cell board={board} idx={idx + 1} turn={turn} />
|
||||||
|
<Cell board={board} idx={idx + 2} turn={turn} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Cell: Component = ({ board, idx, turn }) => {
|
||||||
|
const square = get_square(board, idx);
|
||||||
|
return square == "empty" && turn != "game over" ? (
|
||||||
|
<details class="cell empty">
|
||||||
|
<summary></summary>
|
||||||
|
<SuccBoard board={board} idx={idx} turn={turn} />
|
||||||
|
</details>
|
||||||
|
) : (
|
||||||
|
<div class={`cell ${square}`}>{square != "empty" && square}</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SuccBoard: Component = ({ board, idx, turn }) => {
|
||||||
|
const square = square_of_turn(turn);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Board
|
||||||
|
board={set_square(board, idx, square)}
|
||||||
|
turn={game_over(board) ? "game over" : turn + 1}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_square(board: Board, idx: SquareIdx): Square {
|
||||||
|
return board[Math.floor(idx / 3)][idx % 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_square(board: Board, idx: SquareIdx, to: Square): Board {
|
||||||
|
const new_board = JSON.parse(JSON.stringify(board)) as Board;
|
||||||
|
|
||||||
|
new_board[Math.floor(idx / 3)][idx % 3] = to;
|
||||||
|
|
||||||
|
return new_board;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_render(<Board board={set_square(empty_board, 4, "x")} />);
|
||||||
|
|
Loading…
Reference in a new issue