successfully migrate to preact!?
This commit is contained in:
parent
2bb8e71a46
commit
1b5b70a832
13 changed files with 364 additions and 350 deletions
12
deno.json
Normal file
12
deno.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact"
|
||||
},
|
||||
"imports": {
|
||||
"copy-paste": "https://deno.land/x/copy_paste@v1.1.3/mod.ts",
|
||||
"preact": "https://esm.sh/preact@10.16.0",
|
||||
"preact/jsx-runtime": "https://esm.sh/preact@10.16.0/jsx-runtime?dts",
|
||||
"preact-render-to-string": "https://esm.sh/preact-render-to-string@5.2.0?external=preact"
|
||||
}
|
||||
}
|
122
deno.lock
Normal file
122
deno.lock
Normal file
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"version": "2",
|
||||
"remote": {
|
||||
"https://deno.land/std@0.149.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
|
||||
"https://deno.land/std@0.149.0/bytes/bytes_list.ts": "aba5e2369e77d426b10af1de0dcc4531acecec27f9b9056f4f7bfbf8ac147ab4",
|
||||
"https://deno.land/std@0.149.0/bytes/equals.ts": "3c3558c3ae85526f84510aa2b48ab2ad7bdd899e2e0f5b7a8ffc85acb3a6043a",
|
||||
"https://deno.land/std@0.149.0/bytes/mod.ts": "763f97d33051cc3f28af1a688dfe2830841192a9fea0cbaa55f927b49d49d0bf",
|
||||
"https://deno.land/std@0.149.0/fmt/colors.ts": "6f9340b7fb8cc25a993a99e5efc56fe81bb5af284ff412129dd06df06f53c0b4",
|
||||
"https://deno.land/std@0.149.0/io/buffer.ts": "bd0c4bf53db4b4be916ca5963e454bddfd3fcd45039041ea161dbf826817822b",
|
||||
"https://deno.land/std@0.149.0/streams/conversion.ts": "fc3db02026183da795fa32ac7549868e9f19c75ba029d4b4c3739af62b48517a",
|
||||
"https://deno.land/std@0.149.0/testing/_diff.ts": "029a00560b0d534bc0046f1bce4bd36b3b41ada3f2a3178c85686eb2ff5f1413",
|
||||
"https://deno.land/std@0.149.0/testing/_format.ts": "0d8dc79eab15b67cdc532826213bbe05bccfd276ca473a50a3fc7bbfb7260642",
|
||||
"https://deno.land/std@0.149.0/testing/asserts.ts": "0ee58a557ac764e762c62bb21f00e7d897e3919e71be38b2d574fb441d721005",
|
||||
"https://deno.land/std@0.176.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462",
|
||||
"https://deno.land/std@0.176.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3",
|
||||
"https://deno.land/std@0.176.0/encoding/hex.ts": "50f8c95b52eae24395d3dfcb5ec1ced37c5fe7610ef6fffdcc8b0fdc38e3b32f",
|
||||
"https://deno.land/std@0.176.0/fmt/colors.ts": "938c5d44d889fb82eff6c358bea8baa7e85950a16c9f6dae3ec3a7a729164471",
|
||||
"https://deno.land/std@0.176.0/fs/_util.ts": "65381f341af1ff7f40198cee15c20f59951ac26e51ddc651c5293e24f9ce6f32",
|
||||
"https://deno.land/std@0.176.0/fs/copy.ts": "14214efd94fc3aa6db1e4af2b4b9578e50f7362b7f3725d5a14ad259a5df26c8",
|
||||
"https://deno.land/std@0.176.0/fs/empty_dir.ts": "c3d2da4c7352fab1cf144a1ecfef58090769e8af633678e0f3fabaef98594688",
|
||||
"https://deno.land/std@0.176.0/fs/ensure_dir.ts": "724209875497a6b4628dfb256116e5651c4f7816741368d6c44aab2531a1e603",
|
||||
"https://deno.land/std@0.176.0/fs/ensure_file.ts": "c38602670bfaf259d86ca824a94e6cb9e5eb73757fefa4ebf43a90dd017d53d9",
|
||||
"https://deno.land/std@0.176.0/fs/ensure_link.ts": "c0f5b2f0ec094ed52b9128eccb1ee23362a617457aa0f699b145d4883f5b2fb4",
|
||||
"https://deno.land/std@0.176.0/fs/ensure_symlink.ts": "2955cc8332aeca9bdfefd05d8d3976b94e282b0f353392a71684808ed2ffdd41",
|
||||
"https://deno.land/std@0.176.0/fs/eol.ts": "f1f2eb348a750c34500741987b21d65607f352cf7205f48f4319d417fff42842",
|
||||
"https://deno.land/std@0.176.0/fs/exists.ts": "b8c8a457b71e9d7f29b9d2f87aad8dba2739cbe637e8926d6ba6e92567875f8e",
|
||||
"https://deno.land/std@0.176.0/fs/expand_glob.ts": "45d17e89796a24bd6002e4354eda67b4301bb8ba67d2cac8453cdabccf1d9ab0",
|
||||
"https://deno.land/std@0.176.0/fs/mod.ts": "bc3d0acd488cc7b42627044caf47d72019846d459279544e1934418955ba4898",
|
||||
"https://deno.land/std@0.176.0/fs/move.ts": "4cb47f880e3f0582c55e71c9f8b1e5e8cfaacb5e84f7390781dd563b7298ec19",
|
||||
"https://deno.land/std@0.176.0/fs/walk.ts": "ea95ffa6500c1eda6b365be488c056edc7c883a1db41ef46ec3bf057b1c0fe32",
|
||||
"https://deno.land/std@0.176.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0",
|
||||
"https://deno.land/std@0.176.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b",
|
||||
"https://deno.land/std@0.176.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0",
|
||||
"https://deno.land/std@0.176.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000",
|
||||
"https://deno.land/std@0.176.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1",
|
||||
"https://deno.land/std@0.176.0/path/mod.ts": "4b83694ac500d7d31b0cdafc927080a53dc0c3027eb2895790fb155082b0d232",
|
||||
"https://deno.land/std@0.176.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d",
|
||||
"https://deno.land/std@0.176.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1",
|
||||
"https://deno.land/std@0.176.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba",
|
||||
"https://deno.land/std@0.186.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462",
|
||||
"https://deno.land/std@0.186.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3",
|
||||
"https://deno.land/std@0.186.0/async/deferred.ts": "42790112f36a75a57db4a96d33974a936deb7b04d25c6084a9fa8a49f135def8",
|
||||
"https://deno.land/std@0.186.0/bytes/bytes_list.ts": "31d664f4d42fa922066405d0e421c56da89d751886ee77bbe25a88bf0310c9d0",
|
||||
"https://deno.land/std@0.186.0/bytes/concat.ts": "d26d6f3d7922e6d663dacfcd357563b7bf4a380ce5b9c2bbe0c8586662f25ce2",
|
||||
"https://deno.land/std@0.186.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219",
|
||||
"https://deno.land/std@0.186.0/encoding/base64.ts": "144ae6234c1fbe5b68666c711dc15b1e9ee2aef6d42b3b4345bf9a6c91d70d0d",
|
||||
"https://deno.land/std@0.186.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e",
|
||||
"https://deno.land/std@0.186.0/io/buf_reader.ts": "06fff3337091c49e99ebd2dd790c9a90364c087a2953ea081667400fd6c6cebb",
|
||||
"https://deno.land/std@0.186.0/io/buf_writer.ts": "48c33c8f00b61dcbc7958706741cec8e59810bd307bc6a326cbd474fe8346dfd",
|
||||
"https://deno.land/std@0.186.0/io/buffer.ts": "17f4410eaaa60a8a85733e8891349a619eadfbbe42e2f319283ce2b8f29723ab",
|
||||
"https://deno.land/std@0.186.0/io/copy_n.ts": "0cc7ce07c75130f6fc18621ec1911c36e147eb9570664fee0ea12b1988167590",
|
||||
"https://deno.land/std@0.186.0/io/limited_reader.ts": "6c9a216f8eef39c1ee2a6b37a29372c8fc63455b2eeb91f06d9646f8f759fc8b",
|
||||
"https://deno.land/std@0.186.0/io/mod.ts": "2665bcccc1fd6e8627cca167c3e92aaecbd9897556b6f69e6d258070ef63fd9b",
|
||||
"https://deno.land/std@0.186.0/io/multi_reader.ts": "9c2a0a31686c44b277e16da1d97b4686a986edcee48409b84be25eedbc39b271",
|
||||
"https://deno.land/std@0.186.0/io/read_delim.ts": "c02b93cc546ae8caad8682ae270863e7ace6daec24c1eddd6faabc95a9d876a3",
|
||||
"https://deno.land/std@0.186.0/io/read_int.ts": "7cb8bcdfaf1107586c3bacc583d11c64c060196cb070bb13ae8c2061404f911f",
|
||||
"https://deno.land/std@0.186.0/io/read_lines.ts": "c526c12a20a9386dc910d500f9cdea43cba974e853397790bd146817a7eef8cc",
|
||||
"https://deno.land/std@0.186.0/io/read_long.ts": "f0aaa420e3da1261c5d33c5e729f09922f3d9fa49f046258d4ff7a00d800c71e",
|
||||
"https://deno.land/std@0.186.0/io/read_range.ts": "28152daf32e43dd9f7d41d8466852b0d18ad766cd5c4334c91fef6e1b3a74eb5",
|
||||
"https://deno.land/std@0.186.0/io/read_short.ts": "805cb329574b850b84bf14a92c052c59b5977a492cd780c41df8ad40826c1a20",
|
||||
"https://deno.land/std@0.186.0/io/read_string_delim.ts": "5dc9f53bdf78e7d4ee1e56b9b60352238ab236a71c3e3b2a713c3d78472a53ce",
|
||||
"https://deno.land/std@0.186.0/io/slice_long_to_bytes.ts": "48d9bace92684e880e46aa4a2520fc3867f9d7ce212055f76ecc11b22f9644b7",
|
||||
"https://deno.land/std@0.186.0/io/string_reader.ts": "da0f68251b3d5b5112485dfd4d1b1936135c9b4d921182a7edaf47f74c25cc8f",
|
||||
"https://deno.land/std@0.186.0/io/string_writer.ts": "8a03c5858c24965a54c6538bed15f32a7c72f5704a12bda56f83a40e28e5433e",
|
||||
"https://deno.land/std@0.186.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0",
|
||||
"https://deno.land/std@0.186.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b",
|
||||
"https://deno.land/std@0.186.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0",
|
||||
"https://deno.land/std@0.186.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000",
|
||||
"https://deno.land/std@0.186.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1",
|
||||
"https://deno.land/std@0.186.0/path/mod.ts": "ee161baec5ded6510ee1d1fb6a75a0f5e4b41f3f3301c92c716ecbdf7dae910d",
|
||||
"https://deno.land/std@0.186.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d",
|
||||
"https://deno.land/std@0.186.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1",
|
||||
"https://deno.land/std@0.186.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba",
|
||||
"https://deno.land/std@0.186.0/streams/_common.ts": "f45cba84f0d813de3326466095539602364a9ba521f804cc758f7a475cda692d",
|
||||
"https://deno.land/std@0.186.0/streams/buffer.ts": "d5b3d7d0299114e5b2ea895a8bf202a687fd915c5282f8096c7bae23b5a04407",
|
||||
"https://deno.land/std@0.186.0/streams/byte_slice_stream.ts": "225d57263a34325d7c96cb3dafeb478eec0e6fd05cd0458d678752eadd132bb4",
|
||||
"https://deno.land/std@0.186.0/streams/copy.ts": "75cbc795ff89291df22ddca5252de88b2e16d40c85d02840593386a8a1454f71",
|
||||
"https://deno.land/std@0.186.0/streams/delimiter_stream.ts": "f69e849b3d1f59f02424497273f411105a6f76a9f13da92aeeb9a2d554236814",
|
||||
"https://deno.land/std@0.186.0/streams/early_zip_readable_streams.ts": "4005fa74162b943f79899e5d7cb96adcbc0a6b867f9144974ed12d30e0a556e1",
|
||||
"https://deno.land/std@0.186.0/streams/iterate_reader.ts": "bbec1d45c2df2c0c5920bad0549351446fdc8e0886d99e95959b259dbcdb6072",
|
||||
"https://deno.land/std@0.186.0/streams/limited_bytes_transform_stream.ts": "05dc592ffaab83257494d22dd53917e56243c26e5e3129b3f13ddbbbc4785048",
|
||||
"https://deno.land/std@0.186.0/streams/limited_transform_stream.ts": "d69ab790232c1b86f53621ad41ef03c235f2abb4b7a1cd51960ad6e12ee55e38",
|
||||
"https://deno.land/std@0.186.0/streams/merge_readable_streams.ts": "5d6302888f4bb0616dafb5768771be0aec9bedc05fbae6b3d726d05ffbec5b15",
|
||||
"https://deno.land/std@0.186.0/streams/mod.ts": "c07ec010e700b9ea887dc36ca08729828bc7912f711e4054e24d33fd46282252",
|
||||
"https://deno.land/std@0.186.0/streams/read_all.ts": "ee319772fb0fd28302f97343cc48dfcf948f154fd0d755d8efe65814b70533be",
|
||||
"https://deno.land/std@0.186.0/streams/readable_stream_from_iterable.ts": "cd4bb9e9bf6dbe84c213beb1f5085c326624421671473e410cfaecad15f01865",
|
||||
"https://deno.land/std@0.186.0/streams/readable_stream_from_reader.ts": "bfc416c4576a30aac6b9af22c9dc292c20c6742141ee7c55b5e85460beb0c54e",
|
||||
"https://deno.land/std@0.186.0/streams/reader_from_iterable.ts": "55f68110dce3f8f2c87b834d95f153bc904257fc65175f9f2abe78455cb8047c",
|
||||
"https://deno.land/std@0.186.0/streams/reader_from_stream_reader.ts": "fa4971e5615a010e49492c5d1688ca1a4d17472a41e98b498ab89a64ebd7ac73",
|
||||
"https://deno.land/std@0.186.0/streams/text_delimiter_stream.ts": "20e680ab8b751390e359288ce764f9c47d164af11a263870746eeca4bc7d976b",
|
||||
"https://deno.land/std@0.186.0/streams/text_line_stream.ts": "0f2c4b33a5fdb2476f2e060974cba1347cefe99a4af33c28a57524b1a34750fa",
|
||||
"https://deno.land/std@0.186.0/streams/to_transform_stream.ts": "7f55fc0b14cf3ed0f8d10d8f41d05bdc40726e44a65c37f58705d10a615f0159",
|
||||
"https://deno.land/std@0.186.0/streams/writable_stream_from_writer.ts": "56fff5c82fb736fdd669b567cc0b2bbbe0351002cd13254eae26c366e2bed89a",
|
||||
"https://deno.land/std@0.186.0/streams/write_all.ts": "aec90152978581ea62d56bb53a5cbf487e6a89c902f87c5969681ffbdf32b998",
|
||||
"https://deno.land/std@0.186.0/streams/writer_from_stream_writer.ts": "07c7ee025151a190f37fc42cbb01ff93afc949119ebddc6e0d0df14df1bf6950",
|
||||
"https://deno.land/std@0.186.0/streams/zip_readable_streams.ts": "a9d81aa451240f79230add674809dbee038d93aabe286e2d9671e66591fc86ca",
|
||||
"https://deno.land/std@0.186.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea",
|
||||
"https://deno.land/std@0.186.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7",
|
||||
"https://deno.land/std@0.186.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f",
|
||||
"https://deno.land/x/clippy@v0.2.2/bindings/bindings.ts": "c7678a4bfa5748b77aead8f99c449c8351500783a65e2e8c0607bfe231b5b013",
|
||||
"https://deno.land/x/clippy@v0.2.2/deps.ts": "6bcfee8a6054be6c52d7a51d8cf21b37bb6bfbda3bd3b7d5eda0081dde9dd4a2",
|
||||
"https://deno.land/x/clippy@v0.2.2/mod.ts": "ff4966a3a21a59ae5a676a4e0737d044eac8006e93498cfbb6a8a4bdb24abab1",
|
||||
"https://deno.land/x/clippy@v0.2.2/platform/darwin.ts": "ed74ede39c1e5a8a4afee2dbc5507b75d71c27049fabd8f98e7e2d595886dcc8",
|
||||
"https://deno.land/x/clippy@v0.2.2/platform/helper.ts": "ba1ae4bc0905a3c21c423f83f425b654ba817fbb80341465e5338ef516ca3730",
|
||||
"https://deno.land/x/clippy@v0.2.2/platform/linux.ts": "241911a15062899e697d4f7b92c213c171429aa4ba9730a909a18ceb582fd590",
|
||||
"https://deno.land/x/clippy@v0.2.2/platform/mod.ts": "b7324415e824785bc29c3fdb90bf6a27fb6025f806c8cd516461cc58f2aba5dd",
|
||||
"https://deno.land/x/clippy@v0.2.2/platform/windows.ts": "c83adf9f54b452a9adc84eacf9498ec5a8170274ece84c26ed93d19952cd834a",
|
||||
"https://deno.land/x/copy_paste@v1.1.3/deps.ts": "89bfebe10979530b38b3be2ace3b24a7b83dbecb2a6cca7cd7b05b9a86fb1e61",
|
||||
"https://deno.land/x/copy_paste@v1.1.3/mod.ts": "3b82d6c620749acb86398bbec1f2c1f472cc39921c22ca7d7a98ab682b170f20",
|
||||
"https://deno.land/x/plug@1.0.1/deps.ts": "35ea2acd5e3e11846817a429b7ef4bec47b80f2d988f5d63797147134cbd35c2",
|
||||
"https://deno.land/x/plug@1.0.1/download.ts": "8d6a023ade0806a0653b48cd5f6f8b15fcfaa1dbf2aa1f4bc90fc5732d27b144",
|
||||
"https://deno.land/x/plug@1.0.1/mod.ts": "5dec80ee7a3a325be45c03439558531bce7707ac118f4376cebbd6740ff24bfb",
|
||||
"https://deno.land/x/plug@1.0.1/types.ts": "d8eb738fc6ed883e6abf77093442c2f0b71af9090f15c7613621d4039e410ee1",
|
||||
"https://deno.land/x/plug@1.0.1/util.ts": "5ba8127b9adc36e070b9e22971fb8106869eea1741f452a87b4861e574f13481",
|
||||
"https://esm.sh/preact-render-to-string@5.2.0?external=preact": "834df8d191aa1435e1164e430dc68b5c42a69b1f6624e103e039a96dc702c05d",
|
||||
"https://esm.sh/preact@10.16.0": "5229650cdac537f87cae81d5001e88d4e7a38cc7e77be978961d2897a733117d",
|
||||
"https://esm.sh/preact@10.16.0/jsx-runtime?dts": "9e67b64a5b48299c77d30bffc213735fdcf4b3b5d4ad8ff8d4136f246de5fa34",
|
||||
"https://esm.sh/stable/preact@10.16.0/denonext/jsx-runtime.js": "64770c709df77c4b64b79f84a4abf6189fd0c3ea461121870eca0cf2bcca87b0",
|
||||
"https://esm.sh/stable/preact@10.16.0/denonext/preact.mjs": "01dc8bdf124926c611c0711081b9c162cf2735cccad7c2bc9914766f633ddb1d",
|
||||
"https://esm.sh/v128/preact-render-to-string@5.2.0/X-ZS9wcmVhY3Q/denonext/preact-render-to-string.mjs": "b2b771d82125460bd3e5cdf20ebd662a08c4c61e34b174cd11db929dd5883966"
|
||||
}
|
||||
}
|
|
@ -1,28 +1,38 @@
|
|||
import { Html } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { Attributes, ComponentChildren, VNode, toChildArray } from "preact";
|
||||
import { render } from "preact-render-to-string";
|
||||
import { writeText } from "copy-paste";
|
||||
|
||||
export const Main: Component = (attributes, children) => (
|
||||
export function Main({
|
||||
children,
|
||||
...attributes
|
||||
}: {
|
||||
children: ComponentChildren;
|
||||
attributes?: Attributes;
|
||||
}) {
|
||||
return (
|
||||
<div {...attributes} id="main">
|
||||
{...children}
|
||||
{...toChildArray(children)}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export const HCenter: Component = (attributes, children) => (
|
||||
export const HCenter = ({
|
||||
children,
|
||||
...attrs
|
||||
}: {
|
||||
children: ComponentChildren;
|
||||
attrs?: Attributes;
|
||||
}) => (
|
||||
<div
|
||||
{...attributes}
|
||||
{...attrs}
|
||||
class="hcenter"
|
||||
style="display: flex; justify-content: center;"
|
||||
>
|
||||
{...children}
|
||||
{...toChildArray(children)}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const styles = (s: Record<string, string | number>): string =>
|
||||
Object.entries(s)
|
||||
.map(([rule, val]) => `${rule}: ${val};`)
|
||||
.join("");
|
||||
|
||||
export const eggbug_emotions: Record<string, Html> = {
|
||||
export const eggbug_emotions = {
|
||||
smiling: (
|
||||
<img
|
||||
class="eggbug"
|
||||
|
@ -30,6 +40,13 @@ export const eggbug_emotions: Record<string, Html> = {
|
|||
alt="eggbug, smiling"
|
||||
/>
|
||||
),
|
||||
};
|
||||
} as const;
|
||||
|
||||
export const EggbugImg: Component = ({ type }) => eggbug_emotions[type];
|
||||
export const EggbugImg = ({ type }: { type: keyof typeof eggbug_emotions }) =>
|
||||
eggbug_emotions[type];
|
||||
|
||||
export const render_and_copy = (elem: VNode) => {
|
||||
const rendered = render(elem);
|
||||
writeText(rendered);
|
||||
console.log(rendered);
|
||||
};
|
||||
|
|
60
html/coq.tsx
60
html/coq.tsx
|
@ -1,37 +1,55 @@
|
|||
import { Main } from "./common.tsx";
|
||||
import { Main, render_and_copy } from "./common.tsx";
|
||||
import { reify_dialogue } from "./dialogue.tsx";
|
||||
import { debug_render } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { ComponentChildren, toChildArray, JSX } from "preact";
|
||||
|
||||
const Option: Component = ({ n }, children) => (
|
||||
const Option = ({
|
||||
n,
|
||||
children,
|
||||
}: {
|
||||
n: number;
|
||||
children: ComponentChildren;
|
||||
}) => (
|
||||
<>
|
||||
<span
|
||||
class="number"
|
||||
title={`Option #${n} (there's no actual keyboard shortcut, sorry)`}
|
||||
>{`[${n}]`}</span>{" "}
|
||||
{...children}
|
||||
{...toChildArray(children)}
|
||||
</>
|
||||
);
|
||||
|
||||
const WaterRitual: Component = () => (
|
||||
const WaterRitual = () => (
|
||||
<span class="water-ritual">
|
||||
[begin water ritual; <span class="one">1</span> dram of{" "}
|
||||
<span class="water">water</span>]
|
||||
</span>
|
||||
);
|
||||
|
||||
const End: Component = () => <span class="end">[End]</span>;
|
||||
const End = () => <span class="end">[End]</span>;
|
||||
|
||||
const Name: Component = ({ color }, children) => (
|
||||
const Name = ({
|
||||
color,
|
||||
children,
|
||||
}: {
|
||||
color: string;
|
||||
children: ComponentChildren;
|
||||
}) => (
|
||||
<div style={`color: ${color};`} class="name">
|
||||
{...children}
|
||||
{...toChildArray(children)}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Speech: Component = (
|
||||
{ name, name_color, portrait = <></> },
|
||||
children
|
||||
) => (
|
||||
const Speech = ({
|
||||
name,
|
||||
name_color,
|
||||
children,
|
||||
portrait = <></>,
|
||||
}: {
|
||||
name: string;
|
||||
name_color: string;
|
||||
children: ComponentChildren;
|
||||
portrait: JSX.Element;
|
||||
}) => (
|
||||
<div class="speech">
|
||||
<div class="portrait">{portrait}</div>
|
||||
<Name color={name_color}>{name}</Name>
|
||||
|
@ -39,13 +57,19 @@ const Speech: Component = (
|
|||
src="https://static.pyrope.net/coq-hr.png"
|
||||
alt="a snazzy horizontal rule with three central spikes, taken from caves of qud"
|
||||
/>
|
||||
<div class="text">{...children}</div>
|
||||
<div class="text">{...toChildArray(children)}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Website: Component = () => <span class="website">website</span>;
|
||||
const Website = () => <span class="website">website</span>;
|
||||
|
||||
const Eggbug: Component = ({ emotion }, children) => (
|
||||
const Eggbug = ({
|
||||
emotion,
|
||||
children,
|
||||
}: {
|
||||
emotion?: "angry";
|
||||
children: ComponentChildren;
|
||||
}) => (
|
||||
<Speech
|
||||
name="Eggbug"
|
||||
name_color="#83254F"
|
||||
|
@ -60,7 +84,7 @@ const Eggbug: Component = ({ emotion }, children) => (
|
|||
/>
|
||||
}
|
||||
>
|
||||
{...children}
|
||||
{...toChildArray(children)}
|
||||
</Speech>
|
||||
);
|
||||
|
||||
|
@ -250,7 +274,7 @@ const dialogue = reify_dialogue([
|
|||
],
|
||||
]);
|
||||
|
||||
debug_render(
|
||||
render_and_copy(
|
||||
<Main>
|
||||
<div class="gradient">{dialogue}</div>
|
||||
<div class="scanlines"></div>
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxFactory": "create_element",
|
||||
"jsxFragmentFactory": "create_fragment",
|
||||
"jsxImportSource": "./jsx"
|
||||
},
|
||||
"imports": {
|
||||
"html": "./html.ts",
|
||||
"./jsx/jsx-runtime": "./jsx/jsx-runtime.ts"
|
||||
}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
import { Html } from "./html.ts";
|
||||
import { JSX } from "preact";
|
||||
|
||||
type DOption = [Html, Dialogue];
|
||||
type Dialogue = Html | [Html, ...DOption[]];
|
||||
type DNode = JSX.Element | string;
|
||||
type DOption = [DNode, Dialogue];
|
||||
type Dialogue = DNode | [DNode, ...DOption[]];
|
||||
|
||||
function not_empty<T>(arr: T[]): arr is [T, ...T[]] {
|
||||
return arr.length > 0;
|
||||
}
|
||||
|
||||
export function reify_dialogue(d: Dialogue): Html {
|
||||
export function reify_dialogue(d: Dialogue): JSX.Element | string {
|
||||
if (!Array.isArray(d)) return d;
|
||||
|
||||
const [r, ...rest] = d;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { HCenter, Main, styles } from "./common.tsx";
|
||||
import { debug_render } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { EggbugImg, HCenter, Main, render_and_copy } from "./common.tsx";
|
||||
|
||||
const Eggbug: Component = () => (
|
||||
const Eggbug = () => (
|
||||
<HCenter>
|
||||
<Eggbug type="smiling" />
|
||||
<EggbugImg type="smiling" />
|
||||
</HCenter>
|
||||
);
|
||||
|
||||
|
@ -13,15 +11,23 @@ function health_style(current: number, last: number, max: number) {
|
|||
const dhealth = last - current;
|
||||
console.log(inc_width, dhealth);
|
||||
|
||||
return styles({
|
||||
return {
|
||||
transform: `translateX(${-(inc_width * dhealth)}%)`,
|
||||
width: `${last * inc_width}%`,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// could be generalized
|
||||
// might be worthwhile later since <progress> is BAN
|
||||
const Health: Component = ({ current, last, max }) => (
|
||||
const Health = ({
|
||||
current,
|
||||
last,
|
||||
max,
|
||||
}: {
|
||||
current: number;
|
||||
last: number;
|
||||
max: number;
|
||||
}) => (
|
||||
console.log({ current, last, max }),
|
||||
(
|
||||
<div class="health">
|
||||
|
@ -31,7 +37,7 @@ const Health: Component = ({ current, last, max }) => (
|
|||
style={health_style(current, last, max)}
|
||||
></div>
|
||||
</div>
|
||||
<HCenter class="health-numeric">
|
||||
<HCenter /*class="health-numeric"*/>
|
||||
<span class="health-current">
|
||||
{Math.floor(current).toString()}
|
||||
</span>
|
||||
|
@ -42,14 +48,28 @@ const Health: Component = ({ current, last, max }) => (
|
|||
);
|
||||
// one-time animations of hit numbers of health flying off the screen
|
||||
|
||||
const BattleFrame: Component = ({ health, last_health, max_health, msg }) => (
|
||||
const BattleFrame = ({
|
||||
health,
|
||||
last_health,
|
||||
max_health,
|
||||
}: {
|
||||
health: number;
|
||||
last_health: number;
|
||||
max_health: number;
|
||||
}) => (
|
||||
<div class="battle-frame">
|
||||
<Eggbug />
|
||||
<Health current={health} last={last_health} max={max_health} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const Defeated: Component = ({ last_health, max_health }) => (
|
||||
const Defeated = ({
|
||||
last_health,
|
||||
max_health,
|
||||
}: {
|
||||
last_health: number;
|
||||
max_health: number;
|
||||
}) => (
|
||||
<div class="defeated">
|
||||
<Eggbug />
|
||||
<Health current={0} last={0} max={max_health} />
|
||||
|
@ -64,35 +84,41 @@ const Defeated: Component = ({ last_health, max_health }) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const DamageNumber: Component = ({ n }) => (
|
||||
const DamageNumber = ({ n }: { n: number }) => (
|
||||
<div
|
||||
class="damage-number"
|
||||
// changing this to use this much nicer styles thing helped me notice the bug awesome
|
||||
// i still should really, really switch to react
|
||||
// or preact!
|
||||
// anything with *actual typing*
|
||||
style={styles({
|
||||
style={{
|
||||
top: `calc(${100 * Math.random()}px + 15%)`,
|
||||
left: `calc(${100 * Math.random()}px + 25%)`,
|
||||
// tried some exponential stuff but it was too unwieldy
|
||||
// i think this still accomplishes that punch
|
||||
"font-size": `calc(${n / 200} * 2rem + 0.5rem)`,
|
||||
})}
|
||||
fontSize: `calc(${n / 200} * 2rem + 0.5rem)`,
|
||||
}}
|
||||
>
|
||||
<div class="sway">{Math.round(n).toString()}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Battle: Component = ({
|
||||
const Battle = ({
|
||||
max_health = 100,
|
||||
health = max_health,
|
||||
last_health = health,
|
||||
damage_multiplier = 10,
|
||||
damage_bonus = 1,
|
||||
...rest
|
||||
}) =>
|
||||
}: // ...rest
|
||||
Partial<{
|
||||
max_health: number;
|
||||
health: number;
|
||||
last_health: number;
|
||||
damage_multiplier: number;
|
||||
damage_bonus: number;
|
||||
}>) =>
|
||||
health > 0 ? (
|
||||
<details class="battle" {...rest}>
|
||||
<details class="battle" /*{...rest}*/>
|
||||
<summary>
|
||||
<BattleFrame
|
||||
health={health}
|
||||
|
@ -117,25 +143,10 @@ const Battle: Component = ({
|
|||
<Defeated last_health={last_health} max_health={max_health} />
|
||||
);
|
||||
|
||||
const Timer: Component = () => (
|
||||
<details class="timer">
|
||||
<summary>
|
||||
click this when done (HONOR SYSTEM) (EVEN AMONG EGGBUGS THERE CAN BE
|
||||
HONOR)
|
||||
<div class="timer-scroll">
|
||||
{[
|
||||
...new Array(601).fill(undefined).map((_, i) => `${i}s`),
|
||||
"∞s",
|
||||
]}
|
||||
</div>
|
||||
</summary>
|
||||
</details>
|
||||
);
|
||||
|
||||
// a timer would be flippin rad
|
||||
// (it would look like an actual scrolling clock thingie)
|
||||
// (because it would have to)
|
||||
debug_render(
|
||||
render_and_copy(
|
||||
<Main>
|
||||
<Battle max_health={10_000} damage_multiplier={200} damage_bonus={10} />
|
||||
{/* <Timer /> */}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Main } from "./common.tsx";
|
||||
import { Html, debug_render, render } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { JSX } from "preact";
|
||||
import { Main, render_and_copy } from "./common.tsx";
|
||||
|
||||
const peopleify = (...people: string[]): string[] =>
|
||||
// non-breaking space v
|
||||
|
@ -13,12 +12,15 @@ const wheel_style = (
|
|||
width?: number,
|
||||
shl?: number,
|
||||
n?: number
|
||||
): string =>
|
||||
`transform: translateY(calc(2rem * -${num_items})); animation: ${animation_length(
|
||||
): JSX.CSSProperties => ({
|
||||
transform: `translateY(calc(2rem * -${num_items}))`,
|
||||
animation: `${animation_length(
|
||||
num_items
|
||||
)}s ease-in-out reverse none running spin; ${
|
||||
width ? `width: ${width * 100}%;` : ""
|
||||
} ${shl && n ? `margin-left: -${shl * (n + 1)}px;` : ""}`;
|
||||
)}s ease-in-out reverse none running spin`,
|
||||
|
||||
width: width ? `width: ${width * 100}%` : undefined,
|
||||
marginLeft: shl && n ? `-${shl * (n + 1)}px` : undefined,
|
||||
});
|
||||
|
||||
const get_delays = (...lengths: number[]): number[] => {
|
||||
let out = [0];
|
||||
|
@ -28,7 +30,21 @@ const get_delays = (...lengths: number[]): number[] => {
|
|||
return out;
|
||||
};
|
||||
|
||||
const Wheel: Component = ({ items, width, calc_width, shl, n, classes }, _) => (
|
||||
const Wheel = ({
|
||||
items,
|
||||
width,
|
||||
calc_width,
|
||||
shl,
|
||||
n,
|
||||
classes,
|
||||
}: {
|
||||
items: string[];
|
||||
width?: number;
|
||||
calc_width?: number;
|
||||
shl?: number;
|
||||
n?: number;
|
||||
classes: string[];
|
||||
}) => (
|
||||
<details class="wheel" style={width ? `width: ${width * 100}%;` : ""}>
|
||||
<summary class={classes ? classes.join(" ") : ""}>
|
||||
{/* {...items.map((i: string) => <div class="wheel-item">{i}</div>)} */}
|
||||
|
@ -38,7 +54,7 @@ const Wheel: Component = ({ items, width, calc_width, shl, n, classes }, _) => (
|
|||
style={wheel_style(items.length, width)}
|
||||
>
|
||||
{/* <div class="wheel-item empty"></div> */}
|
||||
{...items.map((item: string, i: number) => (
|
||||
{...items.map((item, i) => (
|
||||
<div
|
||||
class={`wheel-item ${i + 1 == items.length ? "last" : ""}`}
|
||||
style={
|
||||
|
@ -63,7 +79,17 @@ function weird_slices<T>(arr: T[]): T[][] {
|
|||
return arr.map(item => [...arr.filter(t => t != item), item]);
|
||||
}
|
||||
|
||||
const MultiWheel: Component = ({ items, calc_width, shl, type }, _) => (
|
||||
const MultiWheel = ({
|
||||
items,
|
||||
calc_width,
|
||||
shl,
|
||||
type,
|
||||
}: {
|
||||
items: string[];
|
||||
calc_width?: number;
|
||||
shl?: number;
|
||||
type: string;
|
||||
}) => (
|
||||
<span class={`multiwheel ${type ? type : ""}`}>
|
||||
{...weird_slices(items).map((sliced_items, n) => (
|
||||
<Wheel
|
||||
|
@ -72,17 +98,25 @@ const MultiWheel: Component = ({ items, calc_width, shl, type }, _) => (
|
|||
calc_width={calc_width}
|
||||
shl={shl}
|
||||
n={n}
|
||||
summary_classes={[type]}
|
||||
classes={[type]}
|
||||
/>
|
||||
))}
|
||||
<Wheel items={items} classes={["invisible"]} summary_classes={[type]} />
|
||||
<Wheel items={items} classes={["invisible", type]} />
|
||||
</span>
|
||||
);
|
||||
|
||||
// i'll probably just hardcode the delays... lame but w/e
|
||||
// nope
|
||||
// it would be possible to have it so the final text is actually properyly selectable maybe but eh
|
||||
const Take: Component = ({ subjects, objects, adjectives }, _) => (
|
||||
const Take = ({
|
||||
subjects,
|
||||
objects,
|
||||
adjectives,
|
||||
}: {
|
||||
subjects: string[];
|
||||
objects: string[];
|
||||
adjectives: string[];
|
||||
}) => (
|
||||
<div class="take">
|
||||
<MultiWheel
|
||||
calc_width={11.4333}
|
||||
|
@ -97,7 +131,7 @@ const Take: Component = ({ subjects, objects, adjectives }, _) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const Checkmark: Component = () => (
|
||||
const Checkmark = () => (
|
||||
<img
|
||||
class="checkmark"
|
||||
src="https://static.pyrope.net/white-twitter-checkmark.png"
|
||||
|
@ -105,7 +139,7 @@ const Checkmark: Component = () => (
|
|||
/>
|
||||
);
|
||||
|
||||
const Author: Component = () => (
|
||||
const Author = () => (
|
||||
<div class="author">
|
||||
<img
|
||||
class="pfp"
|
||||
|
@ -121,7 +155,7 @@ const Author: Component = () => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const Info: Component = () => (
|
||||
const Info = () => (
|
||||
<div class="info">
|
||||
<span class="time">10:02 PM</span> ·{" "}
|
||||
<span class="date">Feb 20, 2021</span> ·{" "}
|
||||
|
@ -129,7 +163,7 @@ const Info: Component = () => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const Stats: Component = () => (
|
||||
const Stats = () => (
|
||||
<div class="stats">
|
||||
<span class="retweets">
|
||||
<span class="stat">3,228</span> Retweets
|
||||
|
@ -145,7 +179,7 @@ const Stats: Component = () => (
|
|||
|
||||
// might want to have the final item be seperate
|
||||
// turned out to be unnecessary
|
||||
debug_render(
|
||||
render_and_copy(
|
||||
<Main>
|
||||
<Author />
|
||||
<Take
|
||||
|
|
164
html/html.ts
164
html/html.ts
|
@ -1,164 +0,0 @@
|
|||
import { writeText } from "https://deno.land/x/copy_paste@v1.1.3/mod.ts";
|
||||
|
||||
export type Prop = string | number | boolean;
|
||||
export type Attributes = Record<string, Prop>;
|
||||
export type Html = string | NonText;
|
||||
export type NonText = {
|
||||
tag: string;
|
||||
attributes: Attributes;
|
||||
children: Html[];
|
||||
};
|
||||
|
||||
export const Fragment = "Fragment";
|
||||
|
||||
function is_string(elem: Html): elem is string {
|
||||
return typeof elem == "string";
|
||||
}
|
||||
|
||||
export function fr(...children: Html[]): Html {
|
||||
return { tag: Fragment, attributes: {}, children };
|
||||
}
|
||||
|
||||
function div(...children: Html[]): Html {
|
||||
return { tag: "div", attributes: {}, children };
|
||||
}
|
||||
|
||||
function expand_fragments_in_list(children: Html[]): Html[] {
|
||||
let out = [];
|
||||
|
||||
for (const child of children) {
|
||||
if (is_string(child)) {
|
||||
out.push(child);
|
||||
} else if (child.tag == Fragment) {
|
||||
out.push(...child.children.map(expand_fragments));
|
||||
} else {
|
||||
out.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// NOTE: if you pass a fragment to this, it won't be expanded (which makes sense if you think about it)
|
||||
function expand_fragments(elem: Html): Html {
|
||||
if (is_string(elem)) {
|
||||
return elem;
|
||||
} else {
|
||||
const children = expand_fragments_in_list(elem.children ?? []);
|
||||
return { ...elem, children };
|
||||
}
|
||||
}
|
||||
|
||||
const attr = (attrs: Attributes) => (elem: Html): Html => {
|
||||
if (is_string(elem)) {
|
||||
return elem;
|
||||
} else {
|
||||
const { tag, attributes, children } = elem;
|
||||
return { tag, attributes: { ...attributes, ...attrs }, children };
|
||||
}
|
||||
};
|
||||
|
||||
const escape = (unsafe: string): string =>
|
||||
unsafe
|
||||
.replaceAll("&", "&")
|
||||
.replaceAll("<", "<")
|
||||
.replaceAll(">", ">")
|
||||
.replaceAll('"', """)
|
||||
.replaceAll("'", "'");
|
||||
|
||||
function render_attributes(attrs: Attributes): string {
|
||||
return (
|
||||
(Object.keys(attrs).length > 0 ? " " : "") +
|
||||
Object.entries(attrs)
|
||||
.filter(([_attr, val]) => typeof val != "undefined")
|
||||
.map(([attr, val]) => `${attr}="${escape((val ?? "").toString())}"`)
|
||||
.join(" ")
|
||||
);
|
||||
}
|
||||
|
||||
function indent(str: string, amount = 4, char = " "): string {
|
||||
const ind = char.repeat(amount);
|
||||
return str
|
||||
.split("\n")
|
||||
.map((l) => ind + l)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
// incomplete, obviously
|
||||
// i hate html
|
||||
const NON_SELF_CLOSING = ["div", "p", "a", "summary"];
|
||||
|
||||
function render_elem(
|
||||
{ tag, attributes, children }: NonText,
|
||||
mini = false,
|
||||
): string {
|
||||
if (children.length == 0) {
|
||||
if (NON_SELF_CLOSING.includes(tag)) {
|
||||
return `<${tag}${render_attributes(attributes)}></${tag}>`;
|
||||
} else {
|
||||
return (
|
||||
`<${tag}${render_attributes(attributes)}` + (mini ? "/>" : " />")
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let inner = "";
|
||||
let string_last = false;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
const rendered = render(child, mini ? "mini" : undefined);
|
||||
|
||||
if (is_string(child)) {
|
||||
mini && string_last && (inner += " ");
|
||||
inner += rendered;
|
||||
|
||||
string_last = true;
|
||||
} else {
|
||||
inner += rendered;
|
||||
string_last = false;
|
||||
}
|
||||
|
||||
if (!mini && i + 1 < children.length) inner += "\n";
|
||||
}
|
||||
|
||||
return [
|
||||
`<${tag}${render_attributes(attributes)}>`,
|
||||
mini ? inner : indent(inner),
|
||||
`</${tag}>`,
|
||||
].join(mini ? "" : "\n");
|
||||
}
|
||||
}
|
||||
// old:
|
||||
// joining with " " is inefficient, but necessary for correct string behavior
|
||||
// i've decided that joining with "" is worth the size savings
|
||||
// THIS MEANS MINIFICATION IS SEMANTICALLY DIFFERENT
|
||||
// JK I DID IT THE HARD WAY :]
|
||||
|
||||
export function render(elem: Html, mini?: "mini"): string {
|
||||
if (is_string(elem)) {
|
||||
return escape(elem);
|
||||
} else if (elem.tag == Fragment) {
|
||||
// mimics react's behavior with fragments, ehhh nvm different aims
|
||||
return elem.children.map((elem) => render(elem, mini)).join("\n");
|
||||
} else {
|
||||
const { tag, attributes } = elem;
|
||||
const expanded = expand_fragments(elem);
|
||||
|
||||
if (is_string(expanded)) {
|
||||
throw "impossible";
|
||||
}
|
||||
|
||||
return render_elem(
|
||||
{ tag, attributes, children: expanded.children },
|
||||
mini == "mini",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function debug_render(elem: Html) {
|
||||
console.log(elem);
|
||||
console.log(render(elem));
|
||||
const mini_render = render(elem, "mini");
|
||||
console.log(mini_render);
|
||||
|
||||
writeText(mini_render);
|
||||
}
|
7
html/jsx/index.d.ts
vendored
7
html/jsx/index.d.ts
vendored
|
@ -1,7 +0,0 @@
|
|||
declare namespace JSX {
|
||||
export interface IntrinsicElements {
|
||||
[elemName: string]: any;
|
||||
}
|
||||
}
|
||||
|
||||
declare var React: never;
|
|
@ -1,50 +0,0 @@
|
|||
import { fr, Html, Prop } from "../html.ts";
|
||||
|
||||
type SadProp = Prop | undefined | Html | Html[];
|
||||
export type Component = (
|
||||
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[];
|
||||
}
|
||||
|
||||
export function create_element(
|
||||
type: Component | string,
|
||||
props_?: Props,
|
||||
): Html {
|
||||
const props: Props = props_ ?? { children: [] };
|
||||
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"
|
||||
) continue;
|
||||
attributes[key] = val;
|
||||
}
|
||||
|
||||
if (typeof type == "string") {
|
||||
return { tag: type, attributes, children };
|
||||
} else {
|
||||
return type(attributes, children);
|
||||
}
|
||||
}
|
||||
|
||||
export function Fragment(
|
||||
_: Record<string | number | symbol, never>,
|
||||
children: Html[],
|
||||
) {
|
||||
return fr(...children);
|
||||
}
|
||||
|
||||
export const jsx = create_element;
|
||||
export const jsxs = create_element;
|
|
@ -1,7 +1,6 @@
|
|||
import { debug_render } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { render_and_copy } from "./common.tsx";
|
||||
|
||||
const Spinny: Component = ({ depth }) => (
|
||||
const Spinny = ({ depth }: { depth: number }) => (
|
||||
<div class="main">
|
||||
<Square depth={depth} num_squares={depth} />
|
||||
</div>
|
||||
|
@ -45,7 +44,13 @@ function color(depth: number, num_squares: number): string {
|
|||
//TODO: MAYBE: try to get a backup pulse animation for preferes-reduced motion
|
||||
// low priority because it already turns off the animation thankfully
|
||||
// ${depth % 2 == 0 ? "cw" : "ccw"}
|
||||
const Square: Component = ({ depth, num_squares }) =>
|
||||
const Square = ({
|
||||
depth,
|
||||
num_squares,
|
||||
}: {
|
||||
depth: number;
|
||||
num_squares: number;
|
||||
}) =>
|
||||
depth == 0 ? (
|
||||
<></>
|
||||
) : (
|
||||
|
@ -57,4 +62,4 @@ const Square: Component = ({ depth, num_squares }) =>
|
|||
</div>
|
||||
);
|
||||
|
||||
debug_render(<Spinny depth={14} />);
|
||||
render_and_copy(<Spinny depth={14} />);
|
||||
|
|
57
html/ttt.tsx
57
html/ttt.tsx
|
@ -1,5 +1,4 @@
|
|||
import { Html, debug_render } from "./html.ts";
|
||||
import { Component } from "./jsx/jsx-runtime.ts";
|
||||
import { render_and_copy } from "./common.tsx";
|
||||
|
||||
type Square = "x" | "o" | "empty";
|
||||
type Row = [Square, Square, Square];
|
||||
|
@ -16,7 +15,7 @@ function game_over([[s1, s2, s3], [s4, s5, s6], [s7, s8, s9]]: Board): boolean {
|
|||
}
|
||||
|
||||
// TODO: strike out and such
|
||||
const Board: Component = ({ board, turn = 0 }) => (
|
||||
const Board = ({ board, turn = 0 }: { board: Board; turn?: number }) => (
|
||||
<div class="state">
|
||||
{game_over(board) ? (
|
||||
<div class="whose-turn game-over">Game over!</div>
|
||||
|
@ -31,35 +30,57 @@ const Board: Component = ({ board, turn = 0 }) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const Row: Component = ({ board, idx, turn }) => (
|
||||
const Row = ({
|
||||
board,
|
||||
idx,
|
||||
turn,
|
||||
}: {
|
||||
board: Board;
|
||||
idx: number;
|
||||
turn: number;
|
||||
}) => (
|
||||
<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} />
|
||||
<Cell board={board} idx={(idx + 0) as SquareIdx} turn={turn} />
|
||||
<Cell board={board} idx={(idx + 1) as SquareIdx} turn={turn} />
|
||||
<Cell board={board} idx={(idx + 2) as SquareIdx} turn={turn} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const Cell: Component = ({ board, idx, turn }) => {
|
||||
const Cell = ({
|
||||
board,
|
||||
idx,
|
||||
turn,
|
||||
}: {
|
||||
board: Board;
|
||||
idx: SquareIdx;
|
||||
turn: number | "game over";
|
||||
}) => {
|
||||
if (turn == "game over") {
|
||||
return <div class="cell empty"></div>;
|
||||
}
|
||||
const square = get_square(board, idx);
|
||||
return square == "empty" && turn != "game over" ? (
|
||||
return square == "empty" ? (
|
||||
<details class="cell empty">
|
||||
<summary></summary>
|
||||
<SuccBoard board={board} idx={idx} turn={turn} />
|
||||
</details>
|
||||
) : (
|
||||
<div class={`cell ${square}`}>{square != "empty" && square}</div>
|
||||
<div class={`cell ${square}`}>{square}</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SuccBoard: Component = ({ board, idx, turn }) => {
|
||||
const SuccBoard = ({
|
||||
board,
|
||||
idx,
|
||||
turn,
|
||||
}: {
|
||||
board: Board;
|
||||
idx: SquareIdx;
|
||||
turn: number;
|
||||
}) => {
|
||||
const square = square_of_turn(turn);
|
||||
|
||||
return (
|
||||
<Board
|
||||
board={set_square(board, idx, square)}
|
||||
turn={game_over(board) ? "game over" : turn + 1}
|
||||
/>
|
||||
);
|
||||
return <Board board={set_square(board, idx, square)} turn={turn + 1} />;
|
||||
};
|
||||
|
||||
function get_square(board: Board, idx: SquareIdx): Square {
|
||||
|
@ -74,4 +95,4 @@ function set_square(board: Board, idx: SquareIdx, to: Square): Board {
|
|||
return new_board;
|
||||
}
|
||||
|
||||
debug_render(<Board board={set_square(empty_board, 4, "x")} />);
|
||||
render_and_copy(<Board board={set_square(empty_board, 4, "x")} />);
|
||||
|
|
Loading…
Reference in a new issue