diff --git a/html/html.ts b/html/html.ts index 3f8f8cd..d8130dc 100644 --- a/html/html.ts +++ b/html/html.ts @@ -83,14 +83,21 @@ function indent(str: string, amount = 4, char = " "): string { .join("\n"); } +// incomplete, obviously. +const NON_SELF_CLOSING = ["div", "p", "a"]; + function render_elem( { tag, attributes, children }: NonText, mini = false, ): string { if (children.length == 0) { - return ( - `<${tag}${render_attributes(attributes)}` + (mini ? "/>" : " />") - ); + if (!NON_SELF_CLOSING.includes(tag)) { + return ( + `<${tag}${render_attributes(attributes)}` + (mini ? "/>" : " />") + ); + } else { + return `<${tag}${render_attributes(attributes)}>`; + } } else { let inner = ""; let string_last = false; diff --git a/html/jsx/jsx-runtime.ts b/html/jsx/jsx-runtime.ts index 2755424..b8e88c4 100644 --- a/html/jsx/jsx-runtime.ts +++ b/html/jsx/jsx-runtime.ts @@ -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[]; export type Component = ( - attributes: Attributes, + props: CProps, children: Html[], ) => Html; +export type CProps = { + [key: string]: any; +}; + interface Props { [key: string]: typeof key extends "children" ? never : SadProp; children: undefined | Html | Html[]; @@ -16,12 +20,14 @@ export function create_element( props_?: Props, ): Html { const props: Props = props_ ?? { children: [] }; - const children: Html[] = [props.children ?? []].flat(); - const attributes: Attributes = {}; + const children: Html[] = [props.children ?? []].flat().filter((c) => + typeof c == "string" || typeof c == "object" + ); + const attributes: CProps = {}; for (const [key, val] of Object.entries(props)) { if ( - key == "children" || typeof val == "undefined" || typeof val == "object" + key == "children" || typeof val == "undefined" ) continue; attributes[key] = val; } diff --git a/html/ttt.tsx b/html/ttt.tsx index 3321a9c..571fa30 100644 --- a/html/ttt.tsx +++ b/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"; + +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 }) => ( +
+ {game_over(board) ? ( +
Game over!
+ ) : ( +
It's {square_of_turn(turn)}'s turn!
+ )} +
+ + + +
+
+); + +const Row: Component = ({ board, idx, turn }) => ( +
+ + + +
+); + +const Cell: Component = ({ board, idx, turn }) => { + const square = get_square(board, idx); + return square == "empty" && turn != "game over" ? ( +
+ + +
+ ) : ( +
{square != "empty" && square}
+ ); +}; + +const SuccBoard: Component = ({ board, idx, turn }) => { + const square = square_of_turn(turn); + + return ( + + ); +}; + +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();