diff --git a/README.md b/README.md
deleted file mode 100644
index 2271a22..0000000
--- a/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-Run in an empty directory to setup basic files:
-```
-deno run -Ar https://gitea.hptrow.me/SethTrowbridge/gale/raw/branch/master/scripts/scaffold.ts
-```
-
-- `deno task work` starts the dev server
-- `deno task scan` scans the deno.json for type declaration files (be sure to then restart the Deno language server)
-- `deno task html` creates an index.html for use when static file hosting (the dev serve will create its own index.html if none exists in the file system)
-
-`entry` in the import map points to the starting file
\ No newline at end of file
diff --git a/app.js b/app.js
deleted file mode 100644
index ea3e7e5..0000000
--- a/app.js
+++ /dev/null
@@ -1,45 +0,0 @@
-const {DOM, Tag, Div} = Gale({
- Button: {
- padding: "20px",
- background: "orange",
- ".Inner": {
- fontSize: "10rem"
- }
- },
- Outline: {
- border: "2px solid orange"
- },
- Window:{
- height: "100vh",
- border: "2px solid black",
- display: "flex",
- flexDirection: "row",
- alignItems: "end",
- justifyContent: "center",
- gap: "10px"
- },
- Ability:{
- width: "50px",
- height: "50px",
- background: "red",
- transition: "all 0.4s",
- ":hover":{
- transform:"scale(1.1)"
- }
- },
- Orange:{
- background:"orange"
- }
-});
-
-const UI =()=>
-{
- return Div.Window(
- Div.Ability({class:Tag("Ability", "Orange")}),
- Div.Ability(),
- Div.Ability(),
- Div.Ability.Orange(),
- )
-}
-
-van.add(document.body, UI());
\ No newline at end of file
diff --git a/app.tsx b/app.tsx
new file mode 100644
index 0000000..7ed9a1e
--- /dev/null
+++ b/app.tsx
@@ -0,0 +1,9 @@
+import * as React from ">/npm:react";
+
+export function App(){
+ return <>
+
lol hey!
+ >
+}
+
+export default "lol"
\ No newline at end of file
diff --git a/deno.json b/deno.json
index 02b9813..e508a14 100644
--- a/deno.json
+++ b/deno.json
@@ -1,19 +1,13 @@
{
- "compilerOptions":
- {
- "checkJs": true,
- "lib": ["deno.window", "DOM"],
- "types": ["GALE@HOST/types.d.ts"]
- },
- "tasks":
- {
- "work": "deno run -Ar GALE@HOST/scripts/dev_server.ts",
- "scan": "deno run -Ar GALE@HOST/scripts/refresh_types.ts",
- "html": "deno run -Ar GALE@HOST/scripts/scaffold.ts --html"
- },
- "imports":
- {
- "GALE@HOST/":"./",
- "GALE@ENTRY":"./app.js"
- }
-}
\ No newline at end of file
+ "tasks": {
+ "dev": "deno -A --unstable-bundle --watch server.ts"
+ },
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "react"
+ },
+ "imports": {
+ "@std/assert": "jsr:@std/assert@1",
+ "react":"npm:react"
+ }
+}
diff --git a/deno.lock b/deno.lock
index 9b82683..e6de917 100644
--- a/deno.lock
+++ b/deno.lock
@@ -1,111 +1,26 @@
{
"version": "5",
"specifiers": {
- "jsr:@std/media-types@*": "1.1.0",
- "npm:vanjs-core@*": "1.5.5",
- "npm:vanjs-core@^1.5.5": "1.5.5",
- "npm:vanjs-ext@~0.6.3": "0.6.3"
- },
- "jsr": {
- "@std/media-types@1.1.0": {
- "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4"
- }
+ "npm:react@*": "19.2.0"
},
"npm": {
- "vanjs-core@1.5.5": {
- "integrity": "sha512-BC9MjbXYIRqnwncXfacT6upJpVmIKyrV2MjZi8NuCK+yc9RP0hfdghTpmEuYswXOfkLarDPPcYK4X6q68T9e+g=="
- },
- "vanjs-ext@0.6.3": {
- "integrity": "sha512-Jmaeqx9nCjelwDVSQEaRtt7R4Y/Kj/zJBG3bZSiIPj8Wtr8nEFRsJX9K5qcGl1o3cGEEFBE9suyoSqs/6tiOBg==",
- "dependencies": [
- "vanjs-core"
- ]
+ "react@19.2.0": {
+ "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="
}
},
"redirects": {
- "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts"
+ "https://esm.sh/type-detect@^4.0.0?target=denonext": "https://esm.sh/type-detect@4.1.0?target=denonext"
},
"remote": {
- "https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834",
- "https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917",
- "https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8",
- "https://deno.land/std@0.224.0/path/_common/basename.ts": "569744855bc8445f3a56087fd2aed56bdad39da971a8d92b138c9913aecc5fa2",
- "https://deno.land/std@0.224.0/path/_common/common.ts": "ef73c2860694775fe8ffcbcdd387f9f97c7a656febf0daa8c73b56f4d8a7bd4c",
- "https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c",
- "https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
- "https://deno.land/std@0.224.0/path/_common/format.ts": "92500e91ea5de21c97f5fe91e178bae62af524b72d5fcd246d6d60ae4bcada8b",
- "https://deno.land/std@0.224.0/path/_common/from_file_url.ts": "d672bdeebc11bf80e99bf266f886c70963107bdd31134c4e249eef51133ceccf",
- "https://deno.land/std@0.224.0/path/_common/glob_to_reg_exp.ts": "6cac16d5c2dc23af7d66348a7ce430e5de4e70b0eede074bdbcf4903f4374d8d",
- "https://deno.land/std@0.224.0/path/_common/normalize.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
- "https://deno.land/std@0.224.0/path/_common/normalize_string.ts": "33edef773c2a8e242761f731adeb2bd6d683e9c69e4e3d0092985bede74f4ac3",
- "https://deno.land/std@0.224.0/path/_common/relative.ts": "faa2753d9b32320ed4ada0733261e3357c186e5705678d9dd08b97527deae607",
- "https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a",
- "https://deno.land/std@0.224.0/path/_common/to_file_url.ts": "7f76adbc83ece1bba173e6e98a27c647712cab773d3f8cbe0398b74afc817883",
- "https://deno.land/std@0.224.0/path/_interface.ts": "8dfeb930ca4a772c458a8c7bbe1e33216fe91c253411338ad80c5b6fa93ddba0",
- "https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15",
- "https://deno.land/std@0.224.0/path/basename.ts": "7ee495c2d1ee516ffff48fb9a93267ba928b5a3486b550be73071bc14f8cc63e",
- "https://deno.land/std@0.224.0/path/common.ts": "03e52e22882402c986fe97ca3b5bb4263c2aa811c515ce84584b23bac4cc2643",
- "https://deno.land/std@0.224.0/path/constants.ts": "0c206169ca104938ede9da48ac952de288f23343304a1c3cb6ec7625e7325f36",
- "https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c",
- "https://deno.land/std@0.224.0/path/extname.ts": "593303db8ae8c865cbd9ceec6e55d4b9ac5410c1e276bfd3131916591b954441",
- "https://deno.land/std@0.224.0/path/format.ts": "6ce1779b0980296cf2bc20d66436b12792102b831fd281ab9eb08fa8a3e6f6ac",
- "https://deno.land/std@0.224.0/path/from_file_url.ts": "911833ae4fd10a1c84f6271f36151ab785955849117dc48c6e43b929504ee069",
- "https://deno.land/std@0.224.0/path/glob_to_regexp.ts": "7f30f0a21439cadfdae1be1bf370880b415e676097fda584a63ce319053b5972",
- "https://deno.land/std@0.224.0/path/is_absolute.ts": "4791afc8bfd0c87f0526eaa616b0d16e7b3ab6a65b62942e50eac68de4ef67d7",
- "https://deno.land/std@0.224.0/path/is_glob.ts": "a65f6195d3058c3050ab905705891b412ff942a292bcbaa1a807a74439a14141",
- "https://deno.land/std@0.224.0/path/join.ts": "ae2ec5ca44c7e84a235fd532e4a0116bfb1f2368b394db1c4fb75e3c0f26a33a",
- "https://deno.land/std@0.224.0/path/join_globs.ts": "5b3bf248b93247194f94fa6947b612ab9d3abd571ca8386cf7789038545e54a0",
- "https://deno.land/std@0.224.0/path/mod.ts": "f6bd79cb08be0e604201bc9de41ac9248582699d1b2ee0ab6bc9190d472cf9cd",
- "https://deno.land/std@0.224.0/path/normalize.ts": "4155743ccceeed319b350c1e62e931600272fad8ad00c417b91df093867a8352",
- "https://deno.land/std@0.224.0/path/normalize_glob.ts": "cc89a77a7d3b1d01053b9dcd59462b75482b11e9068ae6c754b5cf5d794b374f",
- "https://deno.land/std@0.224.0/path/parse.ts": "77ad91dcb235a66c6f504df83087ce2a5471e67d79c402014f6e847389108d5a",
- "https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d",
- "https://deno.land/std@0.224.0/path/posix/basename.ts": "d2fa5fbbb1c5a3ab8b9326458a8d4ceac77580961b3739cd5bfd1d3541a3e5f0",
- "https://deno.land/std@0.224.0/path/posix/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4",
- "https://deno.land/std@0.224.0/path/posix/constants.ts": "93481efb98cdffa4c719c22a0182b994e5a6aed3047e1962f6c2c75b7592bef1",
- "https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00",
- "https://deno.land/std@0.224.0/path/posix/extname.ts": "e398c1d9d1908d3756a7ed94199fcd169e79466dd88feffd2f47ce0abf9d61d2",
- "https://deno.land/std@0.224.0/path/posix/format.ts": "185e9ee2091a42dd39e2a3b8e4925370ee8407572cee1ae52838aed96310c5c1",
- "https://deno.land/std@0.224.0/path/posix/from_file_url.ts": "951aee3a2c46fd0ed488899d024c6352b59154c70552e90885ed0c2ab699bc40",
- "https://deno.land/std@0.224.0/path/posix/glob_to_regexp.ts": "76f012fcdb22c04b633f536c0b9644d100861bea36e9da56a94b9c589a742e8f",
- "https://deno.land/std@0.224.0/path/posix/is_absolute.ts": "cebe561ad0ae294f0ce0365a1879dcfca8abd872821519b4fcc8d8967f888ede",
- "https://deno.land/std@0.224.0/path/posix/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9",
- "https://deno.land/std@0.224.0/path/posix/join.ts": "7fc2cb3716aa1b863e990baf30b101d768db479e70b7313b4866a088db016f63",
- "https://deno.land/std@0.224.0/path/posix/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
- "https://deno.land/std@0.224.0/path/posix/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604",
- "https://deno.land/std@0.224.0/path/posix/normalize.ts": "baeb49816a8299f90a0237d214cef46f00ba3e95c0d2ceb74205a6a584b58a91",
- "https://deno.land/std@0.224.0/path/posix/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
- "https://deno.land/std@0.224.0/path/posix/parse.ts": "09dfad0cae530f93627202f28c1befa78ea6e751f92f478ca2cc3b56be2cbb6a",
- "https://deno.land/std@0.224.0/path/posix/relative.ts": "3907d6eda41f0ff723d336125a1ad4349112cd4d48f693859980314d5b9da31c",
- "https://deno.land/std@0.224.0/path/posix/resolve.ts": "08b699cfeee10cb6857ccab38fa4b2ec703b0ea33e8e69964f29d02a2d5257cf",
- "https://deno.land/std@0.224.0/path/posix/to_file_url.ts": "7aa752ba66a35049e0e4a4be5a0a31ac6b645257d2e031142abb1854de250aaf",
- "https://deno.land/std@0.224.0/path/posix/to_namespaced_path.ts": "28b216b3c76f892a4dca9734ff1cc0045d135532bfd9c435ae4858bfa5a2ebf0",
- "https://deno.land/std@0.224.0/path/relative.ts": "ab739d727180ed8727e34ed71d976912461d98e2b76de3d3de834c1066667add",
- "https://deno.land/std@0.224.0/path/resolve.ts": "a6f977bdb4272e79d8d0ed4333e3d71367cc3926acf15ac271f1d059c8494d8d",
- "https://deno.land/std@0.224.0/path/to_file_url.ts": "88f049b769bce411e2d2db5bd9e6fd9a185a5fbd6b9f5ad8f52bef517c4ece1b",
- "https://deno.land/std@0.224.0/path/to_namespaced_path.ts": "b706a4103b104cfadc09600a5f838c2ba94dbcdb642344557122dda444526e40",
- "https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808",
- "https://deno.land/std@0.224.0/path/windows/basename.ts": "6bbc57bac9df2cec43288c8c5334919418d784243a00bc10de67d392ab36d660",
- "https://deno.land/std@0.224.0/path/windows/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4",
- "https://deno.land/std@0.224.0/path/windows/constants.ts": "5afaac0a1f67b68b0a380a4ef391bf59feb55856aa8c60dfc01bd3b6abb813f5",
- "https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9",
- "https://deno.land/std@0.224.0/path/windows/extname.ts": "165a61b00d781257fda1e9606a48c78b06815385e7d703232548dbfc95346bef",
- "https://deno.land/std@0.224.0/path/windows/format.ts": "bbb5ecf379305b472b1082cd2fdc010e44a0020030414974d6029be9ad52aeb6",
- "https://deno.land/std@0.224.0/path/windows/from_file_url.ts": "ced2d587b6dff18f963f269d745c4a599cf82b0c4007356bd957cb4cb52efc01",
- "https://deno.land/std@0.224.0/path/windows/glob_to_regexp.ts": "e45f1f89bf3fc36f94ab7b3b9d0026729829fabc486c77f414caebef3b7304f8",
- "https://deno.land/std@0.224.0/path/windows/is_absolute.ts": "4a8f6853f8598cf91a835f41abed42112cebab09478b072e4beb00ec81f8ca8a",
- "https://deno.land/std@0.224.0/path/windows/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9",
- "https://deno.land/std@0.224.0/path/windows/join.ts": "8d03530ab89195185103b7da9dfc6327af13eabdcd44c7c63e42e27808f50ecf",
- "https://deno.land/std@0.224.0/path/windows/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
- "https://deno.land/std@0.224.0/path/windows/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604",
- "https://deno.land/std@0.224.0/path/windows/normalize.ts": "78126170ab917f0ca355a9af9e65ad6bfa5be14d574c5fb09bb1920f52577780",
- "https://deno.land/std@0.224.0/path/windows/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
- "https://deno.land/std@0.224.0/path/windows/parse.ts": "08804327b0484d18ab4d6781742bf374976de662f8642e62a67e93346e759707",
- "https://deno.land/std@0.224.0/path/windows/relative.ts": "3e1abc7977ee6cc0db2730d1f9cb38be87b0ce4806759d271a70e4997fc638d7",
- "https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972",
- "https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e",
- "https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c",
- "https://vanjs.org/code/van-1.5.5.nomodule.min.js": "32403d4dd6203a46513f000fd64b18e4eaef0823bf757ca0092e70130d059aa3",
- "https://vanjs.org/code/van-x-0.6.3.nomodule.min.js": "e4b7de89bf2f84c22669ce7bcef592fb398d9dcf8b8a36f4562b8ac6354b1f2f"
+ "https://esm.sh/deep-eql@4.1.3": "324a95b802d9f87b5ed66afdf079a0c47cd1cac3db59e9face0969be8eb980f7",
+ "https://esm.sh/deep-eql@4.1.3/denonext/deep-eql.mjs": "53319cc47b4be171d3a1aeeef9f3160a818e08b35baf9018cd14093f79e2910c",
+ "https://esm.sh/type-detect@4.1.0/denonext/type-detect.mjs": "ea850c5962bd47b0157c7e4cf38376cb7fb9fb3ad2438be0a724dbbadda5b94e",
+ "https://esm.sh/type-detect@4.1.0?target=denonext": "7257f955377cabc9a54bfa18f3bd16e12e40a090f25bf238299325d562e92fca"
+ },
+ "workspace": {
+ "dependencies": [
+ "jsr:@std/assert@1",
+ "npm:react@*"
+ ]
}
}
diff --git a/dist/bundle_entry.js b/dist/bundle_entry.js
deleted file mode 100644
index 085ad67..0000000
--- a/dist/bundle_entry.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var ue=Object.defineProperty;var _e=(e,t)=>{for(var r in t)ue(e,r,{get:t[r],enumerable:!0})};var u=Object.getPrototypeOf,b,L,S,A,Q={isConnected:1},me=1e3,O,we={},Se=u(Q),U=u(u),_,Y=(e,t,r,l)=>(e??(setTimeout(r,l),new Set)).add(t),Z=(e,t,r)=>{let l=S;S=t;try{return e(r)}catch(n){return console.error(n),r}finally{S=l}},D=e=>e.filter(t=>t._dom?.isConnected),q=e=>O=Y(O,e,()=>{for(let t of O)t._bindings=D(t._bindings),t._listeners=D(t._listeners);O=_},me),$={get val(){return S?._getters?.add(this),this.rawVal},get oldVal(){return S?._getters?.add(this),this._oldVal},set val(e){S?._setters?.add(this),e!==this.rawVal&&(this.rawVal=e,this._bindings.length+this._listeners.length?(L?.add(this),b=Y(b,this,ve)):this._oldVal=e)}},j=e=>({__proto__:$,rawVal:e,_oldVal:e,_bindings:[],_listeners:[]}),V=(e,t)=>{let r={_getters:new Set,_setters:new Set},l={f:e},n=A;A=[];let a=Z(e,r,t);a=(a??document).nodeType?a:new Text(a);for(let o of r._getters)r._setters.has(o)||(q(o),o._bindings.push(l));for(let o of A)o._dom=a;return A=n,l._dom=a},M=(e,t=j(),r)=>{let l={_getters:new Set,_setters:new Set},n={f:e,s:t};n._dom=r??A?.push(n)??Q,t.val=Z(e,l,t.rawVal);for(let a of l._getters)l._setters.has(a)||(q(a),a._listeners.push(n));return t},ee=(e,...t)=>{for(let r of t.flat(1/0)){let l=u(r??0),n=l===$?V(()=>r.val):l===U?V(r):r;n!=_&&e.append(n)}return e},te=(e,t,...r)=>{let[{is:l,...n},...a]=u(r[0]??0)===Se?r:[{},...r],o=e?document.createElementNS(e,t,{is:l}):document.createElement(t,{is:l});for(let[d,h]of Object.entries(n)){let y=p=>p?Object.getOwnPropertyDescriptor(p,d)??y(u(p)):_,P=t+","+d,c=we[P]??=y(u(o))?.set??0,i=d.startsWith("on")?(p,g)=>{let f=d.slice(2);o.removeEventListener(f,g),o.addEventListener(f,p)}:c?c.bind(o):o.setAttribute.bind(o,d),s=u(h??0);d.startsWith("on")||s===U&&(h=M(h),s=$),s===$?V(()=>(i(h.val,h._oldVal),o)):i(h)}return ee(o,a)},z=e=>({get:(t,r)=>te.bind(_,e,r)}),re=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),ve=()=>{let e=0,t=[...b].filter(l=>l.rawVal!==l._oldVal);do{L=new Set;for(let l of new Set(t.flatMap(n=>n._listeners=D(n._listeners))))M(l.f,l.s,l._dom),l._dom=_}while(++e<100&&(t=[...L]).length);let r=[...b].filter(l=>l.rawVal!==l._oldVal);b=_;for(let l of new Set(r.flatMap(n=>n._bindings=D(n._bindings))))re(l._dom,V(l.f,l._dom)),l._dom=_;for(let l of r)l._oldVal=l.rawVal},x={tags:new Proxy(e=>new Proxy(te,z(e)),z()),hydrate:(e,t)=>re(e,V(t,e)),add:ee,state:j,derive:M};var R={};_e(R,{calc:()=>De,compact:()=>B,list:()=>Fe,noreactive:()=>xe,raw:()=>ce,reactive:()=>K,replace:()=>ge,stateFields:()=>Ne});var{fromEntries:ne,entries:T,keys:k,hasOwn:X,getPrototypeOf:I,create:Ae,assign:be}=Object,{get:oe,set:le,deleteProperty:Ve,ownKeys:Ce}=Reflect,{state:E,derive:Te,add:Pe}=x,N,Oe=1e3,J,W,w=Symbol(),ae=Symbol(),G=Symbol(),m=Symbol(),C=Symbol(),ie=Symbol(),De=e=>(e[ae]=1,e),v=e=>e instanceof Object&&!(e instanceof Function)&&!e[ie],se=e=>{if(e?.[ae]){let t=E();return Te(()=>{let r=e();v(t.rawVal)&&v(r)?ge(t.rawVal,r):t.val=K(r)}),t}else return E(K(e))},$e=e=>{let t=Array.isArray(e)?[]:{__proto__:I(e)};for(let[r,l]of T(e))t[r]=se(l);return t[G]=[],t[m]=E(1),t},de={get:(e,t,r)=>t===w?e:X(e,t)?Array.isArray(e)&&t==="length"?(e[m].val,e.length):e[t].val:oe(e,t,r),set:(e,t,r,l)=>X(e,t)?Array.isArray(e)&&t==="length"?(r!==e.length&&++e[m].val,e.length=r,1):(e[t].val=K(r),1):t in e?le(e,t,r,l):le(e,t,se(r))&&(++e[m].val,F(e).forEach(fe.bind(J,l,t,e[t],W)),1),deleteProperty:(e,t)=>(Ve(e,t)&&Ke(e,t),++e[m].val),ownKeys:e=>(e[m].val,Ce(e))},K=e=>!v(e)||e[w]?e:new Proxy($e(e),de),xe=e=>(e[ie]=1,e),Ne=e=>e[w],Ee=I(E()),Ge=e=>new Proxy(e,{get:(t,r,l)=>I(t[r]??0)===Ee?{val:ce(t[r].rawVal)}:oe(t,r,l)}),ce=e=>e?.[w]?new Proxy(Ge(e[w]),de):e,F=e=>e[G]=e[G].filter(t=>t._containerDom.isConnected),fe=(e,t,r,l,{_containerDom:n,f:a})=>{let o=Array.isArray(e),d=o?Number(t):t;Pe(n,()=>n[C][t]=a(r,()=>delete e[t],d)),o&&!l&&d!==e.length-1&&n.insertBefore(n.lastChild,n[C][k(e).find(h=>Number(h)>d)])},Ke=(e,t)=>{for(let r of F(e)){let l=r._containerDom[C];l[t]?.remove(),delete l[t]}},Ie=e=>(N??(N=(setTimeout(()=>(N.forEach(F),N=J),Oe),new Set))).add(e),Fe=(e,t,r)=>{let l={_containerDom:e instanceof Function?e():e,f:r},n=t[w];l._containerDom[C]={},n[G].push(l),Ie(n);for(let[a,o]of T(n))fe(t,a,o,1,l);return l._containerDom},he=(e,t)=>{for(let[n,a]of T(t)){let o=e[n];v(o)&&v(a)?he(o,a):e[n]=a}for(let n in e)X(t,n)||delete e[n];let r=k(t),l=Array.isArray(e);if(l||k(e).some((n,a)=>n!==r[a])){let n=e[w];if(l)e.length=t.length;else{++n[m].val;let a={...n};for(let o of r)delete n[o];for(let o of r)n[o]=a[o]}for(let{_containerDom:a}of F(n)){let{firstChild:o,[C]:d}=a;for(let h of r)o===d[h]?o=o.nextSibling:a.insertBefore(d[h],o)}}return e},ge=(e,t)=>{W=1;try{return he(e,t instanceof Function?Array.isArray(e)?t(e.filter(r=>1)):ne(t(T(e))):t)}finally{W=J}},B=e=>Array.isArray(e)?e.filter(t=>1).map(B):v(e)?be(Ae(I(e)),ne(T(e).map(([t,r])=>[t,B(r)]))):e;var ye=(e,t="")=>{let r="@",l=":",n=".",a="^",o=(c,i,s)=>{let p=Object.keys(i).map(g=>{let f=i[g];switch(g[0]){case r:return o(`@media(max-width:${g.substring(r.length)})`,f,s);case l:return o(`&${g}`,f,s);case n:return o(`${g}${s}`,f,s);case a:return o(`&:hover .${g.substring(a.length)}${s}`,f,s)}return`${g.replace(/([a-z])([A-Z])/g,"$1-$2")}: ${f};`});return`${c}{${p.join(`
-`)}}`},d=(c,i)=>{let s=i.lastIndexOf(c)+c.length;return s?i.substring(s):i},h=c=>{let i=van.tags[c],s=[],p=new Proxy((...g)=>{let f=i(...g);return f.className=s.join(y+" ")+y+" "+f.className,s=[],f},{get(g,f){return s.push(f.substring(f.lastIndexOf(".")+1)),p}});return p},y=t?"_"+t:"",P=Object.keys(e).map(c=>o("."+c+y,e[c],y)).join(`
-`);return globalThis.document?.head.insertAdjacentHTML("beforeend",``),{Tag(...c){return c.map(i=>d(a,d(n,i))).join(y+" ")+y},CSS:P,DOM:new Proxy({},{get(c,i){return h(i)}}),Div:new Proxy({},{get(c,i){return h("div")[i]}})}};globalThis.van=x;globalThis.vanX=R;globalThis.Gale=ye;var H=new URL(import.meta.url).searchParams;vanX.Store=(e,t)=>{let r=localStorage.getItem(t),l=vanX.reactive(r?JSON.parse(r):e);return van.derive(()=>localStorage.setItem(t,JSON.stringify(vanX.compact(l)))),l};H.has("hmr")&&await import("/proxy/src/hmr.js");var pe=H.get("root")||"/";fetch(pe+"deno.json").then(e=>e.json()).then(e=>{let t=(l,n)=>{let a=document.createElement("script");return a.type=l,a.textContent=n,document.head.appendChild(a),a},r=e.imports;for(let l in r){let n=r[l];n.startsWith("./")&&(r[l]=pe+n.substring(2))}H.has("map")&&t("importmap",JSON.stringify({imports:r})),t("module","").src=r["GALE@ENTRY"]});
diff --git a/hmr/hmr-listen.tsx b/hmr/hmr-listen.tsx
new file mode 100644
index 0000000..cd029b3
--- /dev/null
+++ b/hmr/hmr-listen.tsx
@@ -0,0 +1,31 @@
+import { HMR } from "./hmr-react.tsx";
+import { GroupSignal, GroupSignalHook } from "./hmr-signal.tsx";
+
+const FileListeners = new Map() as Mapvoid>>;
+export const FileListen =(inPath:string, inHandler:()=>void)=>
+{
+ const members = FileListeners.get(inPath)??[];
+ members.push(inHandler);
+ FileListeners.set(inPath, members);
+};
+
+const Socket:WebSocket = new WebSocket("ws://"+document.location.host);
+Socket.addEventListener('message', async(event:{data:string})=>
+{
+ // When a file changes, dynamically re-import it to get the updated members
+ // send the updated members to any listeners for that file
+
+ GroupSignal.reset();
+
+ const reImport = await import(document.location.origin+event.data+"?reload="+Math.random());
+ FileListeners.get(event.data)?.forEach(reExport=>reExport(reImport));
+
+ GroupSignal.swap();
+
+ GroupSignalHook.reset();
+ HMR.update();
+ GroupSignalHook.reset();
+
+});
+Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HMR socket lost")})
+const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000);
\ No newline at end of file
diff --git a/hmr/hmr-react.tsx b/hmr/hmr-react.tsx
new file mode 100644
index 0000000..9f1f6a9
--- /dev/null
+++ b/hmr/hmr-react.tsx
@@ -0,0 +1,176 @@
+import * as ReactParts from "react-original";
+
+/*
+
+Each custom component is secretly modified to have an extra state and id.
+When there is an HMR update, this state is changed, forcing it to re-render.
+
+Each *user-created* React.useState is secretly modified and accompanied by an ID.
+Every time its state is set, the HMR.statesNew map for this ID is set to contain the new state and updater.
+When a component is removed, any of it's states in HMR.statesNew are also removed.
+(HMR.statesNew is the "running total" of all states currently at play).
+
+---
+
+When a state is interacted with:
+- statesNew for this id is set
+- the internal state is also set in the traditional way
+
+When there is an HMR update:
+- All custom components are re-rendered...
+ for each useState(value) call that then happens in the re-render:
+ - if there is a "statesOld" value for this state, use that and ignore the passed value, otherwise use the passed value
+ - if this state has not been interacted with since the last reload (statesNew is empty at this id), set statesNew with whatever is in statesOld
+- statesNew is moved into *statesOld*
+- statesNew is cleared.
+
+*/
+export const HMR =
+{
+ reloads:1,
+ RegisteredComponents: new Map() as Mapvoid>,
+ statesNew: new Map() as Map,
+ statesOld: new Map() as Map,
+ wireframe: false,
+ RegisterComponent(reactID:string, value:()=>void):void
+ {
+ this.RegisteredComponents.set(reactID, value);
+ },
+ update()
+ {
+ this.reloads++;
+ this.RegisteredComponents.forEach(handler=>handler());
+ this.RegisteredComponents.clear();
+ this.statesOld = this.statesNew;
+ this.statesNew = new Map();
+ }
+};
+
+
+export type StateType = boolean|number|string|Record
+export type StateCapture = {state:StateType, set:ReactParts.StateUpdater, reload:number};
+type FuncArgs = [element:keyof ReactParts.JSX.IntrinsicElements, props:Record, children:ReactParts.JSX.Element[]];
+
+
+const H = ReactParts.createElement;
+const MapIndex =(inMap:Map, inIndex:number)=>
+{
+ let index = 0;
+ for(const kvp of inMap)
+ {
+ if(index == inIndex)
+ {
+ return kvp;
+ }
+ index++;
+ }
+ return false;
+};
+
+const ProxyCreate =(...args:FuncArgs)=> (typeof args[0] == "string") ? H(...args) : H(ProxyElement, {__args:args, ...args[1]});
+
+const ProxyElement = (props:{__args:FuncArgs})=>
+{
+ const [stateGet, stateSet] = ReactParts.useState(0);
+ const id = ReactParts.useId();
+ HMR.RegisterComponent(id, ()=>stateSet(stateGet+1));
+
+ const child = H(...props.__args);
+
+ if(HMR.wireframe)
+ {
+ return H("div", {style:{padding:"10px", border:"2px solid red"}},
+ H("p", null, stateGet),
+ child
+ );
+ }
+ else
+ {
+ return child;
+ }
+};
+
+const ProxyState =(argNew:StateType)=>
+{
+ // does statesOld have an entry for this state? use that instead of the passed arg
+ const check = MapIndex(HMR.statesOld, HMR.statesNew.size);
+ const argOld = check ? check[1].state : argNew;
+
+ const id = ReactParts.useId();
+ const [stateGet, stateSet] = ReactParts.useState(argOld);
+
+ // state updates due to clicks, interactivity, etc. since the last reload may already be in statesNew for this slot.
+ // DONT overwrite it.
+ if(!HMR.statesNew.get(id))
+ {
+ HMR.statesNew.set(id, {state:stateGet, set:stateSet, reload:HMR.reloads});
+ }
+
+ const lastKnowReloads = HMR.reloads;
+ ReactParts.useEffect(()=>{
+ return ()=>{
+ if(HMR.reloads == lastKnowReloads)/*i have no idea what this does. this may have to be re-introduced when routing is added*/
+ {
+ // this is a switch/ui change, not a HMR reload change
+ const oldState = MapIndex(HMR.statesOld, HMR.statesNew.size-1);
+ oldState && HMR.statesOld.set(oldState[0], {...oldState[1], state:argNew});
+ }
+
+ HMR.statesNew.delete(id);
+ }
+ }, []);
+
+
+ // do we need to account for the function set?
+ function proxySetter ( inArg:StateType|((old:StateType)=>StateType) )
+ {
+ const stateUser = {state:inArg as StateType, set:stateSet, reload:HMR.reloads};
+ if(typeof inArg == "function")
+ {
+ //const passedFunction = inArg;
+ stateSet((oldState:StateType)=>
+ {
+ const output = inArg(oldState);
+ stateUser.state = output;
+ HMR.statesNew.set(id, stateUser);
+ return output;
+ });
+ }
+ else
+ {
+ HMR.statesNew.set(id, stateUser);
+ stateSet(inArg);
+ }
+ }
+ return [stateGet, proxySetter];
+
+};
+
+type Storelike = Record
+const ProxyReducer =(inReducer:(inState:Storelike, inAction:string)=>Storelike, inState:Storelike, inInit?:(inState:Storelike)=>Storelike)=>
+{
+ const check = MapIndex(HMR.statesOld, HMR.statesNew.size);
+ const argOld = check ? check[1].state : (inInit ? inInit(inState) : inState);
+
+ const intercept =(inInterceptState:Storelike, inInterceptAction:string)=>
+ {
+ const capture = inReducer(inInterceptState, inInterceptAction);
+ const stateUser = {state:capture, set:()=>{}, reload:HMR.reloads};
+ HMR.statesNew.set(id, stateUser);
+ return capture;
+ };
+
+ const id = ReactParts.useId();
+ const [state, dispatch] = ReactParts.useReducer(intercept, argOld as Storelike);
+
+ if(!HMR.statesNew.get(id))
+ {
+ HMR.statesNew.set(id, {state:state, set:()=>{}, reload:HMR.reloads});
+ }
+
+ return [state, dispatch];
+};
+
+export * from "react-original";
+export {ProxyCreate as createElement, ProxyState as useState, ProxyReducer as useReducer };
+export default {...ReactParts, createElement:ProxyCreate, useState:ProxyState, useReducer:ProxyReducer};
\ No newline at end of file
diff --git a/hmr/hmr-signal.tsx b/hmr/hmr-signal.tsx
new file mode 100644
index 0000000..b37f696
--- /dev/null
+++ b/hmr/hmr-signal.tsx
@@ -0,0 +1,47 @@
+import * as SignalsParts from "signals-original";
+import DeepEqual from "https://esm.sh/deep-eql@4.1.3";
+
+type Entry = [signal:SignalsParts.Signal, initArg:T];
+
+function ProxyGroup(inFunc:(initArg:T)=>SignalsParts.Signal)
+{
+ let recordEntry:Entry[] = [];
+ let recordEntryNew:Entry[] = [];
+ let recordIndex = 0;
+ const reset =()=> recordIndex = 0;
+ const swap =()=>
+ {
+ recordEntry = recordEntryNew;
+ recordEntryNew = [] as Entry[];
+ };
+ const proxy =(arg:T)=>
+ {
+ const lookupOld = recordEntry[recordIndex];
+ if(lookupOld && DeepEqual(lookupOld[1], arg))
+ {
+ recordEntryNew[recordIndex] = lookupOld;
+ recordIndex++;
+ return lookupOld[0];
+ }
+ else
+ {
+ const sig = inFunc(arg);
+ recordEntryNew[recordIndex] = [sig, arg];
+ recordEntry[recordIndex] = [sig, arg];
+ recordIndex++;
+ return sig;
+ }
+ };
+ return {reset, swap, proxy};
+}
+
+export const GroupSignal = ProxyGroup(SignalsParts.signal);
+export const GroupSignalHook = ProxyGroup(SignalsParts.useSignal);
+
+
+const proxySignal = GroupSignal.proxy;
+const proxySignalHook = GroupSignalHook.proxy;
+
+export * from "signals-original";
+export { proxySignal as signal, proxySignalHook as useSignal };
+export default {...SignalsParts, signal:proxySignal, useSignal:proxySignalHook};
\ No newline at end of file
diff --git a/hmr/hmr-static.tsx b/hmr/hmr-static.tsx
new file mode 100644
index 0000000..bc4882c
--- /dev/null
+++ b/hmr/hmr-static.tsx
@@ -0,0 +1,144 @@
+type GlyphCheck = (inGlyph:string)=>boolean
+const isAlphaLike:GlyphCheck =(inGlyph:string)=>
+{
+ const inCode = inGlyph.charCodeAt(0);
+
+ if(inCode >= 97 && inCode <= 122)
+ {
+ return true;
+ }
+
+ if(inCode >= 65 && inCode <= 90)
+ {
+ return true;
+ }
+
+ return `$_.`.includes(inGlyph);
+}
+const isWhiteSpace:GlyphCheck =(inGlyph:string)=> `\n\r\t `.includes(inGlyph);
+const isQuote:GlyphCheck =(inGlyph:string)=>`"'\``.includes(inGlyph)
+const isNot =(inCheck:GlyphCheck)=> (inGlyph:string)=>!inCheck(inGlyph);
+const contiguous =(inText:string, inStart:number, inTest:GlyphCheck):number=>
+{
+ let ok = true;
+ let index = inStart;
+ let count = 0;
+ while(ok && count < inText.length)
+ {
+ count++;
+ ok = inTest(inText.charAt(index++));
+ }
+ return index-1;
+}
+
+const findNextExport =(inFile:string, inIndex=0, inLocal:Array, inForeign:Array)=>
+{
+ const pos = inFile.indexOf("export", inIndex);
+ if(pos !== -1)
+ {
+ if(!isAlphaLike(inFile.charAt(pos-1)) || !isAlphaLike(inFile.charAt(pos+6)))
+ {
+
+ const nextCharInd = contiguous(inFile, pos+6, isWhiteSpace);
+ const nextChar = inFile[nextCharInd];
+
+ //console.log(inFile.substring(pos, nextCharInd+1), `>>${nextChar}<<`)
+
+ if(nextChar === "*")
+ {
+ const firstQuoteInd = contiguous(inFile, nextCharInd+1, isNot(isQuote) );
+ const secondQuoteInd = contiguous(inFile, firstQuoteInd+1, isNot(isQuote) );
+ //console.log("ASTERISK:", inFile.substring(pos, secondQuoteInd+1));
+ inForeign.push(inFile.substring(nextCharInd, secondQuoteInd+1));
+ }
+ else if(nextChar == "{")
+ {
+ const endBracketInd = contiguous(inFile, nextCharInd, (inGlyph:string)=>inGlyph!=="}");
+ const nextLetterInd = contiguous(inFile, endBracketInd+1, isWhiteSpace);
+ if(inFile.substring(nextLetterInd, nextLetterInd+4) == "from")
+ {
+ const firstQuoteInd = contiguous(inFile, nextLetterInd+4, isNot(isQuote) );
+ const secondQuoteInd = contiguous(inFile, firstQuoteInd+1, isNot(isQuote) );
+ //console.log(`BRACKET foreign: >>${inFile.substring(nextCharInd, secondQuoteInd+1)}<<`);
+ inForeign.push(inFile.substring(nextCharInd, secondQuoteInd+1));
+ }
+ else
+ {
+ const members = inFile.substring(nextCharInd+1, endBracketInd).replace(/\s/g, '');
+ members.split(",").forEach(part=>
+ {
+ const renamed = part.split(" as ");
+ inLocal.push(renamed[1] || renamed[0]);
+ });
+ }
+
+ }
+ else if(isAlphaLike(nextChar))
+ {
+ const keywordEndInd = contiguous(inFile, nextCharInd, isAlphaLike);
+ const keyword = inFile.substring(nextCharInd, keywordEndInd);
+ if(keyword === "default")
+ {
+ inLocal.push(keyword);
+ //console.log(`MEMBER: >>${keyword})}<<`);
+ }
+ else if(["const", "let", "var", "function", "class"].includes(keyword))
+ {
+ const varStartInd = contiguous(inFile, keywordEndInd+1, isWhiteSpace);
+ const varEndInd = contiguous(inFile, varStartInd+1, isAlphaLike);
+ //console.log(`MEMBER: >>${inFile.substring(varStartInd, varEndInd)}<<`);
+ inLocal.push(inFile.substring(varStartInd, varEndInd))
+ }
+ }
+ }
+
+ return pos + 7;
+ }
+ else
+ {
+ return false;
+ }
+};
+
+export const ModuleShape =(inText:string)=>
+{
+ let match = 0 as number|false;
+ let count = 0;
+ const local = [] as string[];
+ const foreign = [] as string[];
+ while(match !== false && count <200)
+ {
+ count++;
+ match = findNextExport(inText, match, local, foreign);
+ }
+ return[local, foreign] as [local:string[], foreign:string[]];
+};
+
+export const ModuleProxy =(inText:string, inPath:string)=>
+{
+ const [local, foreign] = ModuleShape(inText);
+ console.log("shape local", local);
+ return `
+import {FileListen} from ">/hmr/hmr-listen.tsx";
+import * as Import from "${inPath}?reload=${new Date().getTime()}";
+${ local.map(m=>`let proxy_${m} = Import.${m}; export { proxy_${m} as ${m} };`).join("\n") }
+FileListen("${inPath}", (updatedModule)=>
+{
+ ${ local.map(m=>`proxy_${m} = updatedModule.${m};`).join("\n") }
+});
+${ foreign.join(";\n") }`;
+};
+
+
+// ///////////////////////////////////////////////
+// const [local, global] = Exports(`
+// // export in comment
+// export * from "react";
+// const fakeexport =()=>{};
+// export{ thing1 as remapped, thing2}
+// export { thing1 as remapped, thing2} from 'React';
+// export
+// export const func=()=>{};
+// `);
+//
+// console.log(local, global);
\ No newline at end of file
diff --git a/index.html b/index.html
index 5fcd8a4..a82cdde 100644
--- a/index.html
+++ b/index.html
@@ -1,8 +1,12 @@
-
-
-
-
-
-
+
+
+
+ Document
+
+
+
+
\ No newline at end of file
diff --git a/scripts/assemble_files.ts b/scripts/assemble_files.ts
deleted file mode 100644
index f0c2388..0000000
--- a/scripts/assemble_files.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export const Root = import.meta.resolve("../");
-export const Load =async(file:string)=> await fetch(Root + file).then(resp=>resp.text());
-export const Save =async(text:string, name:string)=> await Deno.writeTextFile(name, text);
-
-const index = await Load("index.html");
-
-export const HTML = index.replace(
-``,
-`
-
-
-`);
-
diff --git a/scripts/bundle.ts b/scripts/bundle.ts
deleted file mode 100644
index 4379ab3..0000000
--- a/scripts/bundle.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-export interface DenoBundleOptions {
- entry: string;
- output?: string;
- outdir?: string;
- check?: boolean | "all";
- noCheck?: boolean | "remote";
- frozen?: boolean;
- importMap?: string;
- lock?: string;
- noLock?: boolean;
- noNpm?: boolean;
- noRemote?: boolean;
- nodeModulesDir?: boolean;
- reload?: boolean | string[];
- vendor?: boolean;
- allowImport?: string[];
- allowScripts?: string[];
- cert?: string;
- codeSplitting?: boolean;
- conditions?: string[];
- config?: string;
- denyImport?: string[];
- inlineImports?: boolean;
- minify?: boolean;
- noConfig?: boolean;
- packages?: "bundle" | "external";
- platform?: "browser" | "deno";
- preload?: string[];
- sourcemap?: "linked" | "inline" | "external";
- watch?: boolean;
-}
-
-export default (options: DenoBundleOptions):{ out: string; err: string; }=>
-{
- const argify =(str: string)=> "--"+str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
- const args: string[] = ["bundle"];
- const { entry, ...rest } = options;
-
- for (const [key, value] of Object.entries(rest))
- {
- let flag = argify(key);
- if (value !== true)
- {
- if(!value)
- {
- continue;
- }
- flag = flag + "=" + (Array.isArray(value) ? value.join(",") : value);
- }
- args.push(flag);
- }
- args.push(entry);
-
- console.log(args);
-
- const command = new Deno.Command("deno", {args});
- const result = command.outputSync();
- const decode = new TextDecoder("utf-8");
- const output = (str:Uint8Array)=> decode.decode(str).replace(/\x1b\[[0-9;]*m/g,"").replace(/\n+$/, "");
- return { out: output(result.stdout), err: output(result.stderr) }
-}
\ No newline at end of file
diff --git a/scripts/bundle_entry.ts b/scripts/bundle_entry.ts
deleted file mode 100644
index 7e7c1a8..0000000
--- a/scripts/bundle_entry.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import Van from "npm:vanjs-core@^1.5.5";
-globalThis.van = Van;
-
-import * as VanX from "npm:vanjs-ext@^0.6.3";
-globalThis.vanX = VanX;
-
-import Gale from "../src/gale.js";
-globalThis.Gale = Gale;
-
-const args = new URL(import.meta.url).searchParams;
-
-//Store
-vanX.Store=(e,t)=>{const a=localStorage.getItem(t),r=vanX.reactive(a?JSON.parse(a):e);return van.derive((()=>localStorage.setItem(t,JSON.stringify(vanX.compact(r))))),r};
-
-if(args.has("hmr"))
-{
- const path = "/proxy/"+"src/hmr.js";
- await import(path);
-}
-
-const root = args.get("root")||"/";
-fetch(root+"deno.json")
-.then(text=>text.json())
-.then(json=>{
- const Script=(t,e)=>{let n=document.createElement("script"); n.type=t; n.textContent=e; document.head.appendChild(n); return n;};
- const imports = json.imports;
- for(let n in imports)
- {
- const path=imports[n];
- path.startsWith("./")&&(imports[n]=root+path.substring(2))
- }
- args.has("map") && Script("importmap",JSON.stringify({imports}));
- Script("module", "").src=imports["GALE@ENTRY"];
-});
\ No newline at end of file
diff --git a/scripts/bundle_subprocess.ts b/scripts/bundle_subprocess.ts
deleted file mode 100644
index 7711e3f..0000000
--- a/scripts/bundle_subprocess.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import Bundler from "./bundle.ts";
-
-const result = Bundler({
- entry: "scripts/bundle_entry.ts",
- outdir: "dist",
- inlineImports: true,
- minify: true,
- codeSplitting: true,
- platform: "browser",
- noLock: true,
-});
-
-console.log(result);
\ No newline at end of file
diff --git a/scripts/dev_server.ts b/scripts/dev_server.ts
deleted file mode 100644
index 41319b1..0000000
--- a/scripts/dev_server.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { contentType } from "jsr:@std/media-types";
-import {HTML, Root} from "./assemble_files.ts";
-
-// Parse the port from the command-line arguments, defaulting to 8000
-const port = parseInt(Deno.args[0] || "8000", 10);
-const sockets: WebSocket[] = [];
-
-function extension(path: string): string {
- // Remove trailing slash if it exists
- const normalizedPath = path.endsWith("/") ? path.slice(0, -1) : path;
- // Get the last part of the path
- const lastPart = normalizedPath.split("/").pop() || "";
- // Check if the last part contains a "."
- return lastPart.split(".")[1] || "";
-}
-
-// Start the HTTP server using Deno.serve
-Deno.serve({ port }, async (req: Request) => {
- const path = new URL(req.url).pathname;
-
- // Handle WebSocket connections
- if (path === "/ws") {
- const { socket, response } = Deno.upgradeWebSocket(req);
- sockets.push(socket);
- return response;
- }
-
- // Serve static files or the predefined HTML for non-file routes
- const ext = extension(path);
-
- // Serve the predefined HTML for non-file routes
- if (!ext) {
- return new Response(HTML, {
- headers: { "Content-Type": "text/html" },
- });
- }
-
-
-
- try
- {
- const proxyPrefix = "/proxy/";
- let streamable;
- if(path.startsWith(proxyPrefix))
- {
- const file = await fetch(Root + path.slice(proxyPrefix.length));
- streamable = file.body;
- }
- else
- {
- const file = await Deno.open("." + path, { read: true });
- streamable = file.readable;
- }
-
- return new Response(streamable, {
- headers: { "Content-Type": contentType(ext) || "application/javascript" },
- });
- }
- catch (err)
- {
- if (err instanceof Deno.errors.NotFound) {
- return new Response("File not found", { status: 404 });
- } else {
- return new Response("Internal server error", { status: 500 });
- }
- }
-});
-
-// Start watching for file changes
-const watcher = Deno.watchFs(".");
-for await (const event of watcher) {
- if (event.kind === "modify") {
- for (const ws of sockets) {
- if (ws.readyState === WebSocket.OPEN) {
- ws.send("reload");
- continue;
- }
- }
- }
-}
diff --git a/scripts/refresh_types.ts b/scripts/refresh_types.ts
deleted file mode 100644
index 35ddd96..0000000
--- a/scripts/refresh_types.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { resolve, toFileUrl } from "https://deno.land/std/path/mod.ts";
-
-async function main()
-{
- // Read and parse the deno.json file
- const denoJson = JSON.parse(await Deno.readTextFile("./deno.json"));
-
- // Check if compilerOptions and types are defined
- if (denoJson.compilerOptions?.types)
- {
- const types:string[] = denoJson.compilerOptions.types;
-
- // Iterate over each type file and cache it
- for (const typeFile of types)
- {
- let lookup:string = typeFile;
- console.log(`found ambient type file`, lookup);
-
- if(typeFile.startsWith("."))
- {
- lookup = toFileUrl(resolve(Deno.cwd(), typeFile)).href;
- }
- console.log(`Scan found types: ${lookup}`);
- await import(lookup); // This will cache the file
- }
-
- console.log("Scan complete; be sure to restart the Deno Language Server!!");
-
- } else {
- console.log("No types found in compilerOptions.");
- }
-}
-
-main().catch((error) => {
- console.error("Error:", error);
- Deno.exit(1);
-});
\ No newline at end of file
diff --git a/scripts/scaffold.ts b/scripts/scaffold.ts
deleted file mode 100644
index d56f9cf..0000000
--- a/scripts/scaffold.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { parseArgs } from "jsr:@std/cli/parse-args";
-import {HTML, Save, Load, Root} from "./assemble_files.ts";
-
-const args = parseArgs(Deno.args);
-if(args.html)
-{
- Save(HTML, "index.html");
-}
-else
-{
- const config = await Load("deno.json");
- const json = JSON.parse(config);
- json.imports["GALE@HOST/"] = Root;
- Save(JSON.stringify(json, null, "\t"), "deno.json");
- Save(await Load("app.js"), "app.js");
-}
diff --git a/server.ts b/server.ts
new file mode 100644
index 0000000..b08b57f
--- /dev/null
+++ b/server.ts
@@ -0,0 +1,140 @@
+import { ModuleProxy } from "./hmr/hmr-static.tsx";
+
+const keyProxy = encodeURI(">");
+const keyAdjacent = "^";
+const keyReload = "reload";
+const keysRemote = ["npm:", "jsr:", "http"];
+const keysExtension = ["ts", "tsx"];
+const extractExtension =(path)=>
+{
+ return path.substring(path.lastIndexOf(".")+1);
+}
+
+const RootRunning = new URL(`file://${Deno.cwd()}`).toString();
+const RootSiblings = import.meta.resolve("./");
+
+console.log(RootRunning);
+console.log(RootSiblings);
+
+const bakeConfigPackage:Deno.bundle.Options =
+{
+ entrypoints:[""],
+ platform: "browser",
+ write: false,
+ minify: true,
+}
+const bakeConfigLocal:Deno.bundle.Options = {...bakeConfigPackage, minify:false, sourcemap:"inline", inlineImports:false };
+async function BakeForce(path:string, type?:"package")
+{
+ console.log("baking", path);
+ const config = type ? bakeConfigPackage : bakeConfigLocal;
+ config.entrypoints[0] = type ? path : RootRunning+path;
+ const result = await Deno.bundle(config);
+
+ if(result.outputFiles)
+ {
+ const body = result.outputFiles.map(file=>file.text()).join("\n");
+ const save:CachedTranspile = [body, type ? "" : ModuleProxy(body, path)];
+ BakeCache[path] = save;
+ return save;
+ }
+ return undefined;
+};
+async function BakeCheck(path:string, type?:"package")
+{
+ const lookup:CachedTranspile = await BakeCache[path];
+ if(!lookup)
+ {
+ return BakeForce(path, type);
+ }
+ return lookup;
+}
+type CachedTranspile = [file:string, profile:string]
+const BakeCache:Record = {}
+
+
+const JSResponse =(body:string)=>new Response(body, {headers:{"content-type":"application/javascript"}});
+
+Deno.serve(async(req:Request)=>
+{
+ const url = new URL(req.url);
+ const parts = url.pathname.split("/").filter(part=>part);
+
+ const lastPart = parts.at(-1);
+ const extension = extractExtension(lastPart);
+
+ console.log("REQUEST:", parts, extension);
+
+ if(parts[0] == keyProxy)
+ {
+ const proxiedPath = parts.slice(1).join("/");
+ console.log("PROXIED:", proxiedPath);
+ const transpiled = await BakeCheck(proxiedPath, "package");
+ return JSResponse(transpiled[0]);
+ }
+ if(keysExtension.includes(extension))
+ {
+ const transpiled = await BakeCheck(url.pathname);
+ return JSResponse(transpiled[url.searchParams.has(keyReload) ? 0 : 1]);
+ }
+
+ if(req.headers.get("upgrade") == "websocket")
+ {
+ try
+ {
+ const { response, socket } = Deno.upgradeWebSocket(req);
+ socket.onopen = () => SocketsLive.add(socket);
+ socket.onclose = () => SocketsLive.delete(socket);
+ socket.onmessage = () => {};
+ socket.onerror = (e) => console.log("Socket errored:", e);
+ return response;
+ }
+ catch(e){ console.log("Socket errored:", e); }
+ }
+
+ return new Response();
+});
+
+const SocketsLive:Set = new Set();
+const SocketsSend =(inData:string)=>{ for (const socket of SocketsLive){ socket.send(inData); } }
+
+const Watcher =async()=>
+{
+ let blocking = false;
+ const filesChanged:Map = new Map();
+ for await (const event of Deno.watchFs(Deno.cwd()))
+ {
+ event.paths.forEach( path => filesChanged.set(path, event.kind) );
+ if(!blocking)
+ {
+ blocking = true;
+ setTimeout(async()=>
+ {
+ for await (const [path, action] of filesChanged)
+ {
+ const extension = extractExtension(path);
+
+ if(keysExtension.includes(extension))
+ {
+ console.log("File change", path);
+ const key = path.substring(Deno.cwd().length).replaceAll("\\", "/");
+ if(action != "remove")
+ {
+ BakeForce(path);
+ SocketsSend(key);
+ }
+ else
+ {
+ delete BakeCache[key];
+ }
+ }
+ }
+ filesChanged.clear();
+ blocking = false;
+ }
+ , 1000);
+ }
+ }
+}
+
+Watcher();
\ No newline at end of file
diff --git a/shadow.html b/shadow.html
deleted file mode 100644
index 37f2ad2..0000000
--- a/shadow.html
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
- Shadow DOM Example
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/gale-2.js b/src/gale-2.js
deleted file mode 100644
index a88df10..0000000
--- a/src/gale-2.js
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-Sheet({
- fontSize:`12px`
-},{
- 1024:
- {
- fontSize:`14px`
- }
-})
-
-function Prox()
-{
- const obj = new Proxy({}, {
- get(target, propName, receiver)
- {
- console.log("get:", propName)
- return obj;
- },
- set(target, propName, value, receiver)
- {
- console.log("set:", propName)
- return true;
- }
- })
- return obj;
-}
-
-
-
-//
-// const sheet = {};
-//
-// sheet
-// .Font.size`8px`.color`#aabbcc`
-// [512]
-// .Font.size`10px`
-// [1024]
-// .Font.size`12px`
-//
-//
-// sheet(1024,
-// Font.size`12px`.color`#aabbcc`
-// )(512,
-// Font.size`10px`);
-//
-
-
-const p1 = Prox();
-
-p1.read
-
-p1.write = 123;
-
diff --git a/src/gale.js b/src/gale.js
deleted file mode 100644
index 6b5471a..0000000
--- a/src/gale.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/** @type {Gale.CreateSheet} */
-export default (sheet, hash="")=>
-{
- const KeyQuery = "@";
- const KeyState = ":";
- const KeyChild = ".";
- const KeyGroup = "^";
-
- /** @type {Gale.Tier} */
- const Tier=(selector, obj, suffix)=>
- {
- const styles = Object.keys(obj).map((key)=>
- {
- const value = obj[key];
- switch(key[0])
- {
- case KeyQuery :
- return Tier(`@media(max-width:${key.substring(KeyQuery.length)})`, value, suffix);
- case KeyState :
- return Tier(`&${key}`, value, suffix);
- case KeyChild :
- return Tier(`${key}${suffix}`, value, suffix);
- case KeyGroup :
- return Tier(`&:hover .${key.substring(KeyGroup.length)}${suffix}`, value, suffix);
- }
- return `${ key.replace(/([a-z])([A-Z])/g, '$1-$2') }: ${value};`
- });
-
- return `${selector}{${styles.join("\n")}}`;
- }
-
- /** @type {(needle:string, str:string)=>string} */
- const extractLast =(needle, str)=>{
- const ind = str.lastIndexOf(needle)+needle.length;
- return ind ? str.substring(ind) : str;
- }
-
- const collect =(tagName)=>
- {
- const pending = van.tags[tagName];
- let mentioned = [];
- const collector = new Proxy(
- (...args)=>
- {
- const element = pending(...args);
- element.className = mentioned.join(id+" ")+id + " " + element.className;
- mentioned = [];
- return element;
- },
- {
- get(_, prop)
- {
- mentioned.push(prop.substring(prop.lastIndexOf(".")+1));
- return collector;
- }
- }
- );
- return collector;
- }
-
- const id = hash ? "_"+hash : "";
- const css = Object.keys(sheet).map(key=>Tier("."+key+id, sheet[key], id)).join(`\n`);
- globalThis.document?.head.insertAdjacentHTML("beforeend", ``);
-
- return {
- Tag(...args){
- return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id;
- },
- CSS: css,
- DOM: new Proxy(
- {},
- {
- get(_, prop)
- {
- return collect(prop)
- }
- }
- ),
- Div: new Proxy(
- {},
- {
- get(_, prop)
- {
- return collect("div")[prop]
- }
- }
- )
- }
-}
\ No newline at end of file
diff --git a/src/hmr.js b/src/hmr.js
deleted file mode 100644
index b5735da..0000000
--- a/src/hmr.js
+++ /dev/null
@@ -1,118 +0,0 @@
-
-let Time = 0;
-/** @type {Record} */
-let Temp = {};
-function Tick()
-{
- for(const k in Temp)
- {
- sessionStorage.setItem(k, Temp[k]);
- }
- Temp = {};
- Time = 0;
-}
-
-/** @type {(key:string, value:string)=>void} */
-function Save(key, value)
-{
- Temp[key] = value;
- if(!Time)
- {
- Time = setTimeout(Tick, 500);
- }
-};
-
-/** @type {(key:string)=>string|null} */
-function Load(key)
-{
- const value = sessionStorage.getItem(key);
- return value;
-}
-
-/** @type {string|undefined} */
-let _ID = undefined;
-let _index = 0;
-
-/** @type {(id:string|undefined = undefined)=>void} */
-function StartID(id)
-{
- _index = 0;
- _ID = id;
-}
-
-function NextID()
-{
- return _ID ? _ID + "_" + (_index++) + "_" : "";
-}
-
-
-//bind Van
-const origninalState = globalThis.van.state;
-globalThis.van.state =(value, key="")=>
-{
- const type = typeof value;
- let reader =d=>d;
- let writer =d=>d?.toString() || null;
-
- switch(type)
- {
- case "boolean" :
- reader =(data)=> data === "true"; break;
- case "number" :
- reader = parseFloat; break;
- case "object" :
- reader = JSON.parse;
- writer = JSON.stringify;
- break;
- }
-
- const fullKey = "HMR_" + NextID() + key;
- const stringValue = Load(fullKey);
- const signal = origninalState((stringValue ? reader(stringValue) : value));
- van.derive(()=>Save(fullKey, writer(signal.val)));
-
- return signal;
-};
-
-//bind VanX
-const originalReactive = globalThis.vanX.reactive;
-globalThis.vanX = {...globalThis.VanX, reactive:(obj, id)=>
-{
- StartID(id);
- const state = originalReactive(obj);
- StartID();
- return state;
-}};
-
-// added in devmode to index.html
-new WebSocket('ws://'+window.location.host+'/ws').addEventListener('message',e=>e.data==='reload'&&window.location.reload());
-
-vanX.Store =(obj, key)=>
-{
- let checkInit = JSON.stringify(obj);
- let checkStore = localStorage.getItem(key+"check");
- localStorage.setItem(key+"check", checkInit);
-
- let recallJSON;
- if(checkInit == checkStore)
- {
- let recallText = localStorage.getItem(key);
- try
- {
- recallJSON = JSON.parse(recallText) || obj;
- }
- catch(e)
- {
- recallJSON = obj;
- }
- }
- else
- {
-
- recallJSON = obj;
- }
-
- const store = vanX.reactive( recallJSON );
- van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store))));
- return store;
-}
diff --git a/types.d.ts b/types.d.ts
deleted file mode 100644
index c1f0b78..0000000
--- a/types.d.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import type * as VAN from "https://vanjs.org/code/van-1.5.5.d.ts";
-import type * as VANX from "https://vanjs.org/code/van-x-0.6.3.d.ts";
-type Replace = Omit & { readonly [P in K]: R };
-declare module "vanjs-core" { export type State = VAN.State }
-declare global
-{
- namespace Van { export type * from "https://vanjs.org/code/van-1.5.5.d.ts"; }
- namespace VanX { export type * from "https://vanjs.org/code/van-x-0.6.3.d.ts"; }
- const van: Replace(arg:T, HMRKey?:string)=>VAN.State>
- const vanX: Replace(obj: T, HMRKey?:string) => T> & {Store:(obj:T, key:string)=>T}
-}
-
-declare global {
-
- namespace Gale {
- type KeyQuery = "@";
- type KeyState = ":";
- type KeyChild = ".";
- type KeyGroup = "^";
- type UserStyles = Partial & {[key: `${KeyQuery|KeyState|KeyChild|KeyGroup}${string}`]: UserStyles }
- type UserSheet = Record
- type CollectKeys = {[Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj]
- type FilterKeys = Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never
- type CrossMultiply = A extends string ? B extends string ? `${A}${B}` : never : never
- type CrossMultiplyRecord = keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec]
- type Tier = (selector:string, obj:UserStyles, suffix:string)=>string;
- type CreateSheet = (sheet:UserSheet&T, hash?:string)=>{
- Tag:(...args:CrossMultiplyRecord[])=>string,
- CSS:string,
- DOM:Elemental>,
- Div:Circular, Van.TagFunc>
- }
-
-
- type Elemental = {[K in keyof HTMLElementTagNameMap]: Van.TagFunc&Circular>}
-
- type Circular = {
- [K in Keys]: Circular&Func
- };
- }
-
- const Gale:Gale.CreateSheet
-
-}
-
-
-declare global
-{
- namespace JSS
- {
-
- type Block = Partial>
- type Responsive = Record
- type Unit = "px" | "em" | "rem" | "%" | "vh" | "vw" | "vmin" | "vmax" | "cm" | "mm" | "in" | "pt" | "pc" | "ch" | "ex"
- type UnitValue = `${number}${Unit}` | [amount:number, unit:Unit]
-
- type HexNumber = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"0"|"a"|"b"|"c"|"d"|"e"|"f"
- type HexTriplet = `#${HexNumber}${HexNumber}${HexNumber}`
- type HexColor = `#${HexNumber}${HexNumber}${HexNumber}${HexNumber}${HexNumber}${HexNumber}`
-
- type Rules = {
- fontSize: UnitValue,
- letterSpacing: UnitValue
- }
-
- type SheetGen =(mobile:Block, conditions?:Responsive)=> void
- }
-
- const Sheet:JSS.SheetGen
-}
-