successfully migrate to preact!?

This commit is contained in:
mehbark 2023-07-12 14:15:53 -04:00
parent 2bb8e71a46
commit 1b5b70a832
13 changed files with 364 additions and 350 deletions

12
deno.json Normal file
View 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
View 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"
}
}

View file

@ -1,28 +1,38 @@
import { Html } from "./html.ts"; import { Attributes, ComponentChildren, VNode, toChildArray } from "preact";
import { Component } from "./jsx/jsx-runtime.ts"; import { render } from "preact-render-to-string";
import { writeText } from "copy-paste";
export const Main: Component = (attributes, children) => ( export function Main({
<div {...attributes} id="main"> children,
{...children} ...attributes
</div> }: {
); children: ComponentChildren;
attributes?: Attributes;
}) {
return (
<div {...attributes} id="main">
{...toChildArray(children)}
</div>
);
}
export const HCenter: Component = (attributes, children) => ( export const HCenter = ({
children,
...attrs
}: {
children: ComponentChildren;
attrs?: Attributes;
}) => (
<div <div
{...attributes} {...attrs}
class="hcenter" class="hcenter"
style="display: flex; justify-content: center;" style="display: flex; justify-content: center;"
> >
{...children} {...toChildArray(children)}
</div> </div>
); );
export const styles = (s: Record<string, string | number>): string => export const eggbug_emotions = {
Object.entries(s)
.map(([rule, val]) => `${rule}: ${val};`)
.join("");
export const eggbug_emotions: Record<string, Html> = {
smiling: ( smiling: (
<img <img
class="eggbug" class="eggbug"
@ -30,6 +40,13 @@ export const eggbug_emotions: Record<string, Html> = {
alt="eggbug, smiling" 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);
};

View file

@ -1,37 +1,55 @@
import { Main } from "./common.tsx"; import { Main, render_and_copy } from "./common.tsx";
import { reify_dialogue } from "./dialogue.tsx"; import { reify_dialogue } from "./dialogue.tsx";
import { debug_render } from "./html.ts"; import { ComponentChildren, toChildArray, JSX } from "preact";
import { Component } from "./jsx/jsx-runtime.ts";
const Option: Component = ({ n }, children) => ( const Option = ({
n,
children,
}: {
n: number;
children: ComponentChildren;
}) => (
<> <>
<span <span
class="number" class="number"
title={`Option #${n} (there's no actual keyboard shortcut, sorry)`} title={`Option #${n} (there's no actual keyboard shortcut, sorry)`}
>{`[${n}]`}</span>{" "} >{`[${n}]`}</span>{" "}
{...children} {...toChildArray(children)}
</> </>
); );
const WaterRitual: Component = () => ( const WaterRitual = () => (
<span class="water-ritual"> <span class="water-ritual">
[begin water ritual; <span class="one">1</span> dram of{" "} [begin water ritual; <span class="one">1</span> dram of{" "}
<span class="water">water</span>] <span class="water">water</span>]
</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"> <div style={`color: ${color};`} class="name">
{...children} {...toChildArray(children)}
</div> </div>
); );
const Speech: Component = ( const Speech = ({
{ name, name_color, portrait = <></> }, name,
children name_color,
) => ( children,
portrait = <></>,
}: {
name: string;
name_color: string;
children: ComponentChildren;
portrait: JSX.Element;
}) => (
<div class="speech"> <div class="speech">
<div class="portrait">{portrait}</div> <div class="portrait">{portrait}</div>
<Name color={name_color}>{name}</Name> <Name color={name_color}>{name}</Name>
@ -39,13 +57,19 @@ const Speech: Component = (
src="https://static.pyrope.net/coq-hr.png" src="https://static.pyrope.net/coq-hr.png"
alt="a snazzy horizontal rule with three central spikes, taken from caves of qud" 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> </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 <Speech
name="Eggbug" name="Eggbug"
name_color="#83254F" name_color="#83254F"
@ -60,7 +84,7 @@ const Eggbug: Component = ({ emotion }, children) => (
/> />
} }
> >
{...children} {...toChildArray(children)}
</Speech> </Speech>
); );
@ -250,7 +274,7 @@ const dialogue = reify_dialogue([
], ],
]); ]);
debug_render( render_and_copy(
<Main> <Main>
<div class="gradient">{dialogue}</div> <div class="gradient">{dialogue}</div>
<div class="scanlines"></div> <div class="scanlines"></div>

View file

@ -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"
}
}

View file

@ -1,13 +1,14 @@
import { Html } from "./html.ts"; import { JSX } from "preact";
type DOption = [Html, Dialogue]; type DNode = JSX.Element | string;
type Dialogue = Html | [Html, ...DOption[]]; type DOption = [DNode, Dialogue];
type Dialogue = DNode | [DNode, ...DOption[]];
function not_empty<T>(arr: T[]): arr is [T, ...T[]] { function not_empty<T>(arr: T[]): arr is [T, ...T[]] {
return arr.length > 0; 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; if (!Array.isArray(d)) return d;
const [r, ...rest] = d; const [r, ...rest] = d;

View file

@ -1,10 +1,8 @@
import { HCenter, Main, styles } from "./common.tsx"; import { EggbugImg, HCenter, Main, render_and_copy } from "./common.tsx";
import { debug_render } from "./html.ts";
import { Component } from "./jsx/jsx-runtime.ts";
const Eggbug: Component = () => ( const Eggbug = () => (
<HCenter> <HCenter>
<Eggbug type="smiling" /> <EggbugImg type="smiling" />
</HCenter> </HCenter>
); );
@ -13,15 +11,23 @@ function health_style(current: number, last: number, max: number) {
const dhealth = last - current; const dhealth = last - current;
console.log(inc_width, dhealth); console.log(inc_width, dhealth);
return styles({ return {
transform: `translateX(${-(inc_width * dhealth)}%)`, transform: `translateX(${-(inc_width * dhealth)}%)`,
width: `${last * inc_width}%`, width: `${last * inc_width}%`,
}); };
} }
// could be generalized // could be generalized
// might be worthwhile later since <progress> is BAN // 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 }), console.log({ current, last, max }),
( (
<div class="health"> <div class="health">
@ -31,7 +37,7 @@ const Health: Component = ({ current, last, max }) => (
style={health_style(current, last, max)} style={health_style(current, last, max)}
></div> ></div>
</div> </div>
<HCenter class="health-numeric"> <HCenter /*class="health-numeric"*/>
<span class="health-current"> <span class="health-current">
{Math.floor(current).toString()} {Math.floor(current).toString()}
</span> </span>
@ -42,14 +48,28 @@ const Health: Component = ({ current, last, max }) => (
); );
// one-time animations of hit numbers of health flying off the screen // 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"> <div class="battle-frame">
<Eggbug /> <Eggbug />
<Health current={health} last={last_health} max={max_health} /> <Health current={health} last={last_health} max={max_health} />
</div> </div>
); );
const Defeated: Component = ({ last_health, max_health }) => ( const Defeated = ({
last_health,
max_health,
}: {
last_health: number;
max_health: number;
}) => (
<div class="defeated"> <div class="defeated">
<Eggbug /> <Eggbug />
<Health current={0} last={0} max={max_health} /> <Health current={0} last={0} max={max_health} />
@ -64,35 +84,41 @@ const Defeated: Component = ({ last_health, max_health }) => (
</div> </div>
); );
const DamageNumber: Component = ({ n }) => ( const DamageNumber = ({ n }: { n: number }) => (
<div <div
class="damage-number" class="damage-number"
// changing this to use this much nicer styles thing helped me notice the bug awesome // changing this to use this much nicer styles thing helped me notice the bug awesome
// i still should really, really switch to react // i still should really, really switch to react
// or preact! // or preact!
// anything with *actual typing* // anything with *actual typing*
style={styles({ style={{
top: `calc(${100 * Math.random()}px + 15%)`, top: `calc(${100 * Math.random()}px + 15%)`,
left: `calc(${100 * Math.random()}px + 25%)`, left: `calc(${100 * Math.random()}px + 25%)`,
// tried some exponential stuff but it was too unwieldy // tried some exponential stuff but it was too unwieldy
// i think this still accomplishes that punch // 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 class="sway">{Math.round(n).toString()}</div>
</div> </div>
); );
const Battle: Component = ({ const Battle = ({
max_health = 100, max_health = 100,
health = max_health, health = max_health,
last_health = health, last_health = health,
damage_multiplier = 10, damage_multiplier = 10,
damage_bonus = 1, damage_bonus = 1,
...rest }: // ...rest
}) => Partial<{
max_health: number;
health: number;
last_health: number;
damage_multiplier: number;
damage_bonus: number;
}>) =>
health > 0 ? ( health > 0 ? (
<details class="battle" {...rest}> <details class="battle" /*{...rest}*/>
<summary> <summary>
<BattleFrame <BattleFrame
health={health} health={health}
@ -117,25 +143,10 @@ const Battle: Component = ({
<Defeated last_health={last_health} max_health={max_health} /> <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 // a timer would be flippin rad
// (it would look like an actual scrolling clock thingie) // (it would look like an actual scrolling clock thingie)
// (because it would have to) // (because it would have to)
debug_render( render_and_copy(
<Main> <Main>
<Battle max_health={10_000} damage_multiplier={200} damage_bonus={10} /> <Battle max_health={10_000} damage_multiplier={200} damage_bonus={10} />
{/* <Timer /> */} {/* <Timer /> */}

View file

@ -1,6 +1,5 @@
import { Main } from "./common.tsx"; import { JSX } from "preact";
import { Html, debug_render, render } from "./html.ts"; import { Main, render_and_copy } from "./common.tsx";
import { Component } from "./jsx/jsx-runtime.ts";
const peopleify = (...people: string[]): string[] => const peopleify = (...people: string[]): string[] =>
// non-breaking space v // non-breaking space v
@ -13,12 +12,15 @@ const wheel_style = (
width?: number, width?: number,
shl?: number, shl?: number,
n?: number n?: number
): string => ): JSX.CSSProperties => ({
`transform: translateY(calc(2rem * -${num_items})); animation: ${animation_length( transform: `translateY(calc(2rem * -${num_items}))`,
animation: `${animation_length(
num_items num_items
)}s ease-in-out reverse none running spin; ${ )}s ease-in-out reverse none running spin`,
width ? `width: ${width * 100}%;` : ""
} ${shl && n ? `margin-left: -${shl * (n + 1)}px;` : ""}`; width: width ? `width: ${width * 100}%` : undefined,
marginLeft: shl && n ? `-${shl * (n + 1)}px` : undefined,
});
const get_delays = (...lengths: number[]): number[] => { const get_delays = (...lengths: number[]): number[] => {
let out = [0]; let out = [0];
@ -28,7 +30,21 @@ const get_delays = (...lengths: number[]): number[] => {
return out; 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}%;` : ""}> <details class="wheel" style={width ? `width: ${width * 100}%;` : ""}>
<summary class={classes ? classes.join(" ") : ""}> <summary class={classes ? classes.join(" ") : ""}>
{/* {...items.map((i: string) => <div class="wheel-item">{i}</div>)} */} {/* {...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)} style={wheel_style(items.length, width)}
> >
{/* <div class="wheel-item empty"></div> */} {/* <div class="wheel-item empty"></div> */}
{...items.map((item: string, i: number) => ( {...items.map((item, i) => (
<div <div
class={`wheel-item ${i + 1 == items.length ? "last" : ""}`} class={`wheel-item ${i + 1 == items.length ? "last" : ""}`}
style={ style={
@ -63,7 +79,17 @@ function weird_slices<T>(arr: T[]): T[][] {
return arr.map(item => [...arr.filter(t => t != item), item]); 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 : ""}`}> <span class={`multiwheel ${type ? type : ""}`}>
{...weird_slices(items).map((sliced_items, n) => ( {...weird_slices(items).map((sliced_items, n) => (
<Wheel <Wheel
@ -72,17 +98,25 @@ const MultiWheel: Component = ({ items, calc_width, shl, type }, _) => (
calc_width={calc_width} calc_width={calc_width}
shl={shl} shl={shl}
n={n} n={n}
summary_classes={[type]} classes={[type]}
/> />
))} ))}
<Wheel items={items} classes={["invisible"]} summary_classes={[type]} /> <Wheel items={items} classes={["invisible", type]} />
</span> </span>
); );
// i'll probably just hardcode the delays... lame but w/e // i'll probably just hardcode the delays... lame but w/e
// nope // nope
// it would be possible to have it so the final text is actually properyly selectable maybe but eh // 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"> <div class="take">
<MultiWheel <MultiWheel
calc_width={11.4333} calc_width={11.4333}
@ -97,7 +131,7 @@ const Take: Component = ({ subjects, objects, adjectives }, _) => (
</div> </div>
); );
const Checkmark: Component = () => ( const Checkmark = () => (
<img <img
class="checkmark" class="checkmark"
src="https://static.pyrope.net/white-twitter-checkmark.png" src="https://static.pyrope.net/white-twitter-checkmark.png"
@ -105,7 +139,7 @@ const Checkmark: Component = () => (
/> />
); );
const Author: Component = () => ( const Author = () => (
<div class="author"> <div class="author">
<img <img
class="pfp" class="pfp"
@ -121,7 +155,7 @@ const Author: Component = () => (
</div> </div>
); );
const Info: Component = () => ( const Info = () => (
<div class="info"> <div class="info">
<span class="time">10:02 PM</span> ·{" "} <span class="time">10:02 PM</span> ·{" "}
<span class="date">Feb 20, 2021</span> ·{" "} <span class="date">Feb 20, 2021</span> ·{" "}
@ -129,7 +163,7 @@ const Info: Component = () => (
</div> </div>
); );
const Stats: Component = () => ( const Stats = () => (
<div class="stats"> <div class="stats">
<span class="retweets"> <span class="retweets">
<span class="stat">3,228</span> Retweets <span class="stat">3,228</span> Retweets
@ -145,7 +179,7 @@ const Stats: Component = () => (
// might want to have the final item be seperate // might want to have the final item be seperate
// turned out to be unnecessary // turned out to be unnecessary
debug_render( render_and_copy(
<Main> <Main>
<Author /> <Author />
<Take <Take

View file

@ -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("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#039;");
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
View file

@ -1,7 +0,0 @@
declare namespace JSX {
export interface IntrinsicElements {
[elemName: string]: any;
}
}
declare var React: never;

View file

@ -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;

View file

@ -1,7 +1,6 @@
import { debug_render } from "./html.ts"; import { render_and_copy } from "./common.tsx";
import { Component } from "./jsx/jsx-runtime.ts";
const Spinny: Component = ({ depth }) => ( const Spinny = ({ depth }: { depth: number }) => (
<div class="main"> <div class="main">
<Square depth={depth} num_squares={depth} /> <Square depth={depth} num_squares={depth} />
</div> </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 //TODO: MAYBE: try to get a backup pulse animation for preferes-reduced motion
// low priority because it already turns off the animation thankfully // low priority because it already turns off the animation thankfully
// ${depth % 2 == 0 ? "cw" : "ccw"} // ${depth % 2 == 0 ? "cw" : "ccw"}
const Square: Component = ({ depth, num_squares }) => const Square = ({
depth,
num_squares,
}: {
depth: number;
num_squares: number;
}) =>
depth == 0 ? ( depth == 0 ? (
<></> <></>
) : ( ) : (
@ -57,4 +62,4 @@ const Square: Component = ({ depth, num_squares }) =>
</div> </div>
); );
debug_render(<Spinny depth={14} />); render_and_copy(<Spinny depth={14} />);

View file

@ -1,5 +1,4 @@
import { Html, debug_render } from "./html.ts"; import { render_and_copy } from "./common.tsx";
import { Component } from "./jsx/jsx-runtime.ts";
type Square = "x" | "o" | "empty"; type Square = "x" | "o" | "empty";
type Row = [Square, Square, Square]; 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 // TODO: strike out and such
const Board: Component = ({ board, turn = 0 }) => ( const Board = ({ board, turn = 0 }: { board: Board; turn?: number }) => (
<div class="state"> <div class="state">
{game_over(board) ? ( {game_over(board) ? (
<div class="whose-turn game-over">Game over!</div> <div class="whose-turn game-over">Game over!</div>
@ -31,35 +30,57 @@ const Board: Component = ({ board, turn = 0 }) => (
</div> </div>
); );
const Row: Component = ({ board, idx, turn }) => ( const Row = ({
board,
idx,
turn,
}: {
board: Board;
idx: number;
turn: number;
}) => (
<div class="row"> <div class="row">
<Cell board={board} idx={idx + 0} turn={turn} /> <Cell board={board} idx={(idx + 0) as SquareIdx} turn={turn} />
<Cell board={board} idx={idx + 1} turn={turn} /> <Cell board={board} idx={(idx + 1) as SquareIdx} turn={turn} />
<Cell board={board} idx={idx + 2} turn={turn} /> <Cell board={board} idx={(idx + 2) as SquareIdx} turn={turn} />
</div> </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); const square = get_square(board, idx);
return square == "empty" && turn != "game over" ? ( return square == "empty" ? (
<details class="cell empty"> <details class="cell empty">
<summary></summary> <summary></summary>
<SuccBoard board={board} idx={idx} turn={turn} /> <SuccBoard board={board} idx={idx} turn={turn} />
</details> </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); const square = square_of_turn(turn);
return ( return <Board board={set_square(board, idx, square)} turn={turn + 1} />;
<Board
board={set_square(board, idx, square)}
turn={game_over(board) ? "game over" : turn + 1}
/>
);
}; };
function get_square(board: Board, idx: SquareIdx): Square { 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; return new_board;
} }
debug_render(<Board board={set_square(empty_board, 4, "x")} />); render_and_copy(<Board board={set_square(empty_board, 4, "x")} />);