From 625d532acc60ac7b76a366a2469fcee5096a346c Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Thu, 1 Aug 2024 08:23:47 -0400 Subject: [PATCH 01/15] idk --- gale-custom.tsx | 2 +- gale.tsx | 12 +++++++++++- index.html | 21 ++++++++++++++++----- styler.tsx | 2 +- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/gale-custom.tsx b/gale-custom.tsx index 0a46831..828f76e 100644 --- a/gale-custom.tsx +++ b/gale-custom.tsx @@ -1,3 +1,3 @@ -import {config, Complex} from "./gale.tsx"; +import {config} from "./gale.tsx"; export default config({other:"lol"}); \ No newline at end of file diff --git a/gale.tsx b/gale.tsx index f02907f..e58c3c8 100644 --- a/gale.tsx +++ b/gale.tsx @@ -17,6 +17,14 @@ const responsive = { }; +let sheet = {insertRule(_:string){}} as CSSStyleSheet; +if(globalThis?.document) +{ + const sheetElement = document.createElement("style"); + document.head.setAttribute("data-gale", "true"); + document.head.appendChild(sheetElement); + sheet = sheetElement.sheet as CSSStyleSheet; +} const styles = new Map(); function Mapper>(className:string, propertyName:string, lut:T) { @@ -27,7 +35,9 @@ function Mapper>(className:string, propertyName if(!check) { const body = `{ ${propertyName}:${propertyValue}; }`; - styles.set(selector, activeQuery.val ? `{ @media(${activeQuery.val})${body}}` : body); + const rules = activeQuery.val ? `{ @media(${activeQuery.val})${body}}` : body + styles.set(selector, rules); + sheet.insertRule(selector + " " + rules); } return selector; } diff --git a/index.html b/index.html index 04e08b3..38e07e8 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,16 @@ - -

test

\ No newline at end of file + + + + +
+ + + \ No newline at end of file diff --git a/styler.tsx b/styler.tsx index b3b22e8..4528a8d 100644 --- a/styler.tsx +++ b/styler.tsx @@ -4,5 +4,5 @@ const classes = Gale.Q.lg( Gale.Face.sans, Gale.Q.md(Gale.Pad.large), Gale.Pad.s console.log(classes); -console.log(Gale.Sheet()) +console.log(Gale.Sheet()); -- 2.34.1 From f4823a6576be1a90b2b118d10349fda20cfddcfc Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 2 Aug 2024 14:45:14 -0400 Subject: [PATCH 02/15] in browser demo --- deno.json | 4 +++- deno.lock | 21 +++++++++++++++++++++ dump.html | 11 +++++++++++ gale.tsx | 4 ++-- styler.tsx | 28 +++++++++++++++++++++++++--- type-experiments-01.ts | 19 +++++++++++++++++++ type-experiments-02.ts | 22 ++++++++++++++++++++++ type-experiments-03.ts | 27 +++++++++++++++++++++++++++ type-experiments-04.ts | 30 ++++++++++++++++++++++++++++++ 9 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 deno.lock create mode 100644 dump.html create mode 100644 type-experiments-01.ts create mode 100644 type-experiments-02.ts create mode 100644 type-experiments-03.ts create mode 100644 type-experiments-04.ts diff --git a/deno.json b/deno.json index d3075e6..93ab167 100644 --- a/deno.json +++ b/deno.json @@ -1,11 +1,13 @@ { "imports": { "react": "https://esm.sh/preact@10.18.1/compat", - "react/": "https://esm.sh/preact@10.18.1/compat/" + "react/": "https://esm.sh/preact@10.18.1/compat/", + "preact-render-to-string": "https://esm.sh/preact-render-to-string@6.5.7?deps=preact@10.18.1" }, "tasks": {"go": "deno run -A styler.tsx"}, "compilerOptions": { "jsx": "react-jsx", + "jsxImportSource": "react", "lib": ["deno.window","dom","dom.asynciterable"] } } \ No newline at end of file diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..989d9df --- /dev/null +++ b/deno.lock @@ -0,0 +1,21 @@ +{ + "version": "3", + "redirects": { + "https://esm.sh/v128/@types/react@~18.3/index.d.ts": "https://esm.sh/v128/@types/react@18.2.38/index.d.ts", + "https://esm.sh/v135/@types/react-dom@~18.3/server~.d.ts": "https://esm.sh/v135/@types/react-dom@18.3.0/server~.d.ts" + }, + "remote": { + "https://esm.sh/preact-render-to-string@6.5.7?deps=preact@10.18.1": "1d9e844b000fd2bf592142f98e6a6c9c3c10953ac90bef90a67ded5e28667279", + "https://esm.sh/preact@10.18.1/compat/jsx-runtime": "d9addc942dc9b5eb507c622e7ad93d5594093f5d31e461d4125f7a1ab475f932", + "https://esm.sh/react-dom@18.3.1/server": "90e374c5323303d5315c780b19e5d6297ec5a569f9cee1df28ee1030dd23af9c", + "https://esm.sh/react@18.3.1": "52480d4c00855e4f76843caa4f2818eb001671523740cbf064cbd108721c29c8", + "https://esm.sh/stable/preact@10.18.1/denonext/compat.js": "cb1028add6b66ecea904a750ad9887f21c5a42c17303c4c317710866c290efa7", + "https://esm.sh/stable/preact@10.18.1/denonext/compat/jsx-runtime.js": "16e3c12a4942f4f3027f6f3c5a0686ef00a80d70a4fb08097b702f4ddd5d488f", + "https://esm.sh/stable/preact@10.18.1/denonext/hooks.js": "cb7e8c9973e6a224348eaa51fba21e13f239839e403f751b29894a258a6d16d0", + "https://esm.sh/stable/preact@10.18.1/denonext/jsx-runtime.js": "be3f1ff4c3c03b08ed19d69428e35bf3d90360a8e081a2e60075ddfd38fd86df", + "https://esm.sh/stable/preact@10.18.1/denonext/preact.mjs": "b2ad171554b90f2be0f30b1318f63d0df90420b2bdb727fddd97193daa177f84", + "https://esm.sh/stable/react@18.3.1/denonext/react.mjs": "fc048ffc55366baf7669519127d186761db72046e2bebf35fe8d0de3964defa3", + "https://esm.sh/v135/preact-render-to-string@6.5.7/X-ZC9wcmVhY3RAMTAuMTguMQ/denonext/preact-render-to-string.mjs": "80d81cb9eeee0b973a136113bd8ff22288b5d40d3dae15f91838dbc72356e095", + "https://esm.sh/v135/react-dom@18.3.1/denonext/server.js": "b4db56f16b45002b5e9b127a9938ab45b12f39825161dffe875920510c524878" + } +} diff --git a/dump.html b/dump.html new file mode 100644 index 0000000..6b9c8fa --- /dev/null +++ b/dump.html @@ -0,0 +1,11 @@ + + + + + + +
hello!
+ + \ No newline at end of file diff --git a/gale.tsx b/gale.tsx index e58c3c8..00db41a 100644 --- a/gale.tsx +++ b/gale.tsx @@ -1,6 +1,6 @@ const typeface = { - sans: "sans serif", + sans: "sans-serif", serif: "Times New Roman" }; const sizes = { @@ -88,7 +88,7 @@ export function config(obj:T) const rules = []; for(const [key, value] of styles.entries()) { - rules.push(key+value); + rules.push("."+key+value); } return rules.join("\n"); }, diff --git a/styler.tsx b/styler.tsx index 4528a8d..aefeadb 100644 --- a/styler.tsx +++ b/styler.tsx @@ -1,8 +1,30 @@ import Gale from "./gale-custom.tsx"; +import Render from "preact-render-to-string"; -const classes = Gale.Q.lg( Gale.Face.sans, Gale.Q.md(Gale.Pad.large), Gale.Pad.small ); -console.log(classes); +const html = Render(
+ hello! +
) -console.log(Gale.Sheet()); +const css = Gale.Sheet(); +Deno.writeTextFile( +"dump.html", +` + + + + + + ${html} + +` +) + +/* idea: +Gale.Table( + [, "md" ], { + Face:["serif", "sans" ], + Pad:["small", "large"] +}) +*/ \ No newline at end of file diff --git a/type-experiments-01.ts b/type-experiments-01.ts new file mode 100644 index 0000000..27bdf82 --- /dev/null +++ b/type-experiments-01.ts @@ -0,0 +1,19 @@ +////////////////////// +type OriginalType = { + key1: { sub1: string; sub2: string }; + key2: { subA: string; subB: string }; + }; + + type ValidKeys = keyof OriginalType; + type ValidSubKeys = keyof OriginalType[K]; + + type EnforcedRecord = { + [K in ValidKeys]: ValidSubKeys[]; + }; + + // Example usage: + const example: EnforcedRecord = { + key1: ['sub1', 'sub2'], + key2: ['subA', 'subB', "sub1"], // last is invalid + }; + diff --git a/type-experiments-02.ts b/type-experiments-02.ts new file mode 100644 index 0000000..02b0b29 --- /dev/null +++ b/type-experiments-02.ts @@ -0,0 +1,22 @@ +type OriginalType = { + key1: { sub1: string; sub2: string }; + key2: { subA: string; subB: string }; +}; + +type ValidKeys = keyof OriginalType; +type ValidSubKeys = keyof OriginalType[K]; + +type FixedLengthArray = [T, ...T[]] & { length: L }; + +type EnforcedRecord = { + [K in ValidKeys]: FixedLengthArray, L>; +}; + + +// Example usage: +const example: EnforcedRecord<2> = { + key1: ['sub1', 'sub2'], // Valid + key2: ['subA', 'subB'], // Valid + // key1: ['sub1'], // Invalid, TypeScript will give an error + // key2: ['subA', 'subB', 'subC'], // Invalid, TypeScript will give an error +}; \ No newline at end of file diff --git a/type-experiments-03.ts b/type-experiments-03.ts new file mode 100644 index 0000000..4f2e037 --- /dev/null +++ b/type-experiments-03.ts @@ -0,0 +1,27 @@ +type OriginalType = { + key1: { sub1: string; sub2: string }; + key2: { subA: string; subB: string }; +}; + +type ValidKeys = keyof OriginalType; +type ValidSubKeys = keyof OriginalType[K]; + +type FixedLengthArray = [T, ...T[]] & { length: L }; + +type EnforcedRecord = { + [K in ValidKeys]: FixedLengthArray, L>; +}; + +const createTable = ( + cols: T, + rows: EnforcedRecord +) => { + return { cols, rows }; +}; + +// Example usage: +const cols = ["a", "b", "c"] as const; +const table = createTable(cols, { + key1: ['sub1', 'sub2', 'sub1', 'sub1'], // invalid because too long + key2: ['subA', 'subB', 'sub1'], // invalid because bad key +}); diff --git a/type-experiments-04.ts b/type-experiments-04.ts new file mode 100644 index 0000000..3fb5f16 --- /dev/null +++ b/type-experiments-04.ts @@ -0,0 +1,30 @@ +type OriginalType = { + key1: { sub1: string; sub2: string }; + key2: { subA: string; subB: string }; +}; + +type ValidKeys = keyof OriginalType; +type ValidSubKeys = keyof OriginalType[K]; + +type FixedLengthArray = T[] & { length: L }; + +type EnforcedRecord = { + [K in ValidKeys]: FixedLengthArray, L>; +}; + +type FixedArr = Arr & { length: Length }; +function Func(arr1:FixedArr) +{ + return arr1.length; +} + + +const test = Func<3>(["a", "b", "c"]) + +// Example usage: +const example: EnforcedRecord<2> = { + key1: ['sub1', 'sub2', 'sub1'], // Valid + key2: ['subA', 'subB'], // Valid + // key1: ['sub1'], // Invalid, TypeScript will give an error + // key2: ['subA', 'subB', 'subC'], // Invalid, TypeScript will give an error +}; \ No newline at end of file -- 2.34.1 From a54a0676952b362afcd0e1eec171adf690e0f54d Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 9 Oct 2024 08:01:50 -0400 Subject: [PATCH 03/15] idk --- gale.tsx | 22 ++++++++++++---------- styler.tsx | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/gale.tsx b/gale.tsx index 00db41a..4995edf 100644 --- a/gale.tsx +++ b/gale.tsx @@ -16,28 +16,29 @@ const responsive = { lg: "min-width:1024px", }; - -let sheet = {insertRule(_:string){}} as CSSStyleSheet; +let SheetDOM = {insertRule(_:string){}} as CSSStyleSheet; if(globalThis?.document) { const sheetElement = document.createElement("style"); document.head.setAttribute("data-gale", "true"); document.head.appendChild(sheetElement); - sheet = sheetElement.sheet as CSSStyleSheet; + SheetDOM = sheetElement.sheet as CSSStyleSheet; } -const styles = new Map(); +const SheetMap = new Map(); + + function Mapper>(className:string, propertyName:string, lut:T) { const build =(propertyValue:string, customPropertyName?:string):string=> { const selector = `${className}-${(customPropertyName||propertyValue as string).replace(/[^a-zA-Z0-9]/g, "")}${activeQuery.val?"_"+activeQuery.key:""}`; - const check = styles.get(selector); + const check = SheetMap.get(selector); if(!check) { const body = `{ ${propertyName}:${propertyValue}; }`; const rules = activeQuery.val ? `{ @media(${activeQuery.val})${body}}` : body - styles.set(selector, rules); - sheet.insertRule(selector + " " + rules); + SheetMap.set(selector, rules); + SheetDOM.insertRule(selector + " " + rules); } return selector; } @@ -64,10 +65,11 @@ function MapperQuery>(lut:T) } -let activeQuery:ActiveQuery; type ActiveQuery = {key:string|false, val:string|false}; -const activeQueryStack:ActiveQuery[] = []; type QueryInvoker = (...args:string[])=>string + +let activeQuery:ActiveQuery; +const activeQueryStack:ActiveQuery[] = []; function Query(amount:string, key?:string):QueryInvoker { activeQuery = {key:key||amount, val:amount}; @@ -86,7 +88,7 @@ export function config(obj:T) Sheet() { const rules = []; - for(const [key, value] of styles.entries()) + for(const [key, value] of SheetMap.entries()) { rules.push("."+key+value); } diff --git a/styler.tsx b/styler.tsx index aefeadb..cdc3595 100644 --- a/styler.tsx +++ b/styler.tsx @@ -1,30 +1,40 @@ import Gale from "./gale-custom.tsx"; import Render from "preact-render-to-string"; - -const html = Render(
- hello! -
) - -const css = Gale.Sheet(); +const jsx =
+hello! +
Deno.writeTextFile( "dump.html", ` - - + + - ${html} + ${Render(jsx)} ` ) -/* idea: -Gale.Table( - [, "md" ], { - Face:["serif", "sans" ], - Pad:["small", "large"] -}) -*/ \ No newline at end of file +// idea for table: +// Gale.Table( +// [, "md" ], { +// Face:["serif", "sans" ], +// Pad:["small", "large"] +// }) + +// idea for object +//Gale({ +// lg:{ +// Face:"sans", +// Pad:"small" +// }, +// md:{ +// Pad:"large" +// } +//}) + +// idea for function +//Gale.Gen(g=>[g.md(), g.Face.Sans]) \ No newline at end of file -- 2.34.1 From 6479974994c6d367f69f944f12221bbed2ec8890 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 12 Feb 2025 08:00:45 -0500 Subject: [PATCH 04/15] simplification --- .vscode/launch.json | 12 ----- app.js | 5 ++ deno.json | 18 +++---- deno.lock | 21 --------- dump.html | 11 ----- gale-custom.tsx | 3 -- gale.js | 72 ++++++++++++++++++++++++++++ gale.tsx | 104 ----------------------------------------- index.html | 20 +++----- styler.tsx | 40 ---------------- styles.dev.js | 67 ++++++++++++++++++++++++++ type-experiments-01.ts | 19 -------- type-experiments-02.ts | 22 --------- type-experiments-03.ts | 27 ----------- type-experiments-04.ts | 30 ------------ 15 files changed, 158 insertions(+), 313 deletions(-) delete mode 100644 .vscode/launch.json create mode 100644 app.js delete mode 100644 deno.lock delete mode 100644 dump.html delete mode 100644 gale-custom.tsx create mode 100644 gale.js delete mode 100644 gale.tsx delete mode 100644 styler.tsx create mode 100644 styles.dev.js delete mode 100644 type-experiments-01.ts delete mode 100644 type-experiments-02.ts delete mode 100644 type-experiments-03.ts delete mode 100644 type-experiments-04.ts diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 130e1f5..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "configurations": [ - { - "name": "deno launch", - "request": "launch", - "type": "node", - "cwd": "${workspaceFolder}", - "runtimeExecutable": "deno", - "runtimeArgs": ["styler.tsx"], - } - ] -} \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..fa7542e --- /dev/null +++ b/app.js @@ -0,0 +1,5 @@ +import Styles from "./styles.dev.js"; +const sheet = Styles({ + Button:{padding:"20px", background:"orange"}, + Test:{fontSize:"3rem"} +}); \ No newline at end of file diff --git a/deno.json b/deno.json index 93ab167..b7a8787 100644 --- a/deno.json +++ b/deno.json @@ -1,13 +1,9 @@ { - "imports": { - "react": "https://esm.sh/preact@10.18.1/compat", - "react/": "https://esm.sh/preact@10.18.1/compat/", - "preact-render-to-string": "https://esm.sh/preact-render-to-string@6.5.7?deps=preact@10.18.1" - }, - "tasks": {"go": "deno run -A styler.tsx"}, - "compilerOptions": { - "jsx": "react-jsx", - "jsxImportSource": "react", - "lib": ["deno.window","dom","dom.asynciterable"] - } + "compilerOptions": { + "checkJs": true, + "lib": [ + "deno.window", + "DOM" + ] + } } \ No newline at end of file diff --git a/deno.lock b/deno.lock deleted file mode 100644 index 989d9df..0000000 --- a/deno.lock +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": "3", - "redirects": { - "https://esm.sh/v128/@types/react@~18.3/index.d.ts": "https://esm.sh/v128/@types/react@18.2.38/index.d.ts", - "https://esm.sh/v135/@types/react-dom@~18.3/server~.d.ts": "https://esm.sh/v135/@types/react-dom@18.3.0/server~.d.ts" - }, - "remote": { - "https://esm.sh/preact-render-to-string@6.5.7?deps=preact@10.18.1": "1d9e844b000fd2bf592142f98e6a6c9c3c10953ac90bef90a67ded5e28667279", - "https://esm.sh/preact@10.18.1/compat/jsx-runtime": "d9addc942dc9b5eb507c622e7ad93d5594093f5d31e461d4125f7a1ab475f932", - "https://esm.sh/react-dom@18.3.1/server": "90e374c5323303d5315c780b19e5d6297ec5a569f9cee1df28ee1030dd23af9c", - "https://esm.sh/react@18.3.1": "52480d4c00855e4f76843caa4f2818eb001671523740cbf064cbd108721c29c8", - "https://esm.sh/stable/preact@10.18.1/denonext/compat.js": "cb1028add6b66ecea904a750ad9887f21c5a42c17303c4c317710866c290efa7", - "https://esm.sh/stable/preact@10.18.1/denonext/compat/jsx-runtime.js": "16e3c12a4942f4f3027f6f3c5a0686ef00a80d70a4fb08097b702f4ddd5d488f", - "https://esm.sh/stable/preact@10.18.1/denonext/hooks.js": "cb7e8c9973e6a224348eaa51fba21e13f239839e403f751b29894a258a6d16d0", - "https://esm.sh/stable/preact@10.18.1/denonext/jsx-runtime.js": "be3f1ff4c3c03b08ed19d69428e35bf3d90360a8e081a2e60075ddfd38fd86df", - "https://esm.sh/stable/preact@10.18.1/denonext/preact.mjs": "b2ad171554b90f2be0f30b1318f63d0df90420b2bdb727fddd97193daa177f84", - "https://esm.sh/stable/react@18.3.1/denonext/react.mjs": "fc048ffc55366baf7669519127d186761db72046e2bebf35fe8d0de3964defa3", - "https://esm.sh/v135/preact-render-to-string@6.5.7/X-ZC9wcmVhY3RAMTAuMTguMQ/denonext/preact-render-to-string.mjs": "80d81cb9eeee0b973a136113bd8ff22288b5d40d3dae15f91838dbc72356e095", - "https://esm.sh/v135/react-dom@18.3.1/denonext/server.js": "b4db56f16b45002b5e9b127a9938ab45b12f39825161dffe875920510c524878" - } -} diff --git a/dump.html b/dump.html deleted file mode 100644 index 6b9c8fa..0000000 --- a/dump.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - -
hello!
- - \ No newline at end of file diff --git a/gale-custom.tsx b/gale-custom.tsx deleted file mode 100644 index 828f76e..0000000 --- a/gale-custom.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import {config} from "./gale.tsx"; - -export default config({other:"lol"}); \ No newline at end of file diff --git a/gale.js b/gale.js new file mode 100644 index 0000000..4646e3a --- /dev/null +++ b/gale.js @@ -0,0 +1,72 @@ +// @ts-check +const KeyQuery = "@"; +const KeyPseudo = ":"; +const KeyChild = "."; +const KeyGroup = "^"; + +/** @typedef { Partial & {[key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles } } UserStyles */ +/** @typedef {Record} UserSheet */ + + +/** + * @template Obj + * @typedef { { [Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj] } CollectKeys + */ + +/** + * @template Keys + * @typedef { Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never } FilterKeys + */ +/** + * @template A + * @template B + * @typedef {A extends string ? B extends string ? `${A}${B}` : never : never } CrossMultiply + */ + +/** + * @template Rec + * @typedef { keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] } CrossMultiplyRecord + */ + + +/** @type {(selector:string, obj:UserStyles)=>string} */ +const Tier=(selector, obj)=> +{ + 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); + case KeyPseudo : + return Tier(`&${key}`, value); + case KeyChild : + return Tier(`${key}`, value); + case KeyGroup : + return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); + } + return `${ key.replace(/([a-z])([A-Z])/g, '$1-$2') }: ${value};` + }); + return `${selector}{${styles.join("\n")}}`; +} + +let i = 0; +/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string}} */ +export default (sheet)=> +{ + const id = i ? "_"+i : ""; + i++; + const css = Object.keys(sheet).map(key=>Tier("."+key, sheet[key])).join(`\n`); + globalThis.document?.head.insertAdjacentHTML("beforeend", ``); + const classes =(...args)=>{ + /** @type {(needle:string, str:string)=>string} */ + const extractLast =(needle, str)=>{ + const ind = str.lastIndexOf(needle)+needle.length; + return ind ? str.substring(ind) : str; + } + return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; + } + classes.css = css; + return classes; +} \ No newline at end of file diff --git a/gale.tsx b/gale.tsx deleted file mode 100644 index 4995edf..0000000 --- a/gale.tsx +++ /dev/null @@ -1,104 +0,0 @@ - -const typeface = { - sans: "sans-serif", - serif: "Times New Roman" -}; -const sizes = { - small: "1rem", - large: "3rem" -}; -const colors = { - red: "#ff2200", - blue: "#0022ff" -}; -const responsive = { - md: "min-width:767px", - lg: "min-width:1024px", -}; - -let SheetDOM = {insertRule(_:string){}} as CSSStyleSheet; -if(globalThis?.document) -{ - const sheetElement = document.createElement("style"); - document.head.setAttribute("data-gale", "true"); - document.head.appendChild(sheetElement); - SheetDOM = sheetElement.sheet as CSSStyleSheet; -} -const SheetMap = new Map(); - - -function Mapper>(className:string, propertyName:string, lut:T) -{ - const build =(propertyValue:string, customPropertyName?:string):string=> - { - const selector = `${className}-${(customPropertyName||propertyValue as string).replace(/[^a-zA-Z0-9]/g, "")}${activeQuery.val?"_"+activeQuery.key:""}`; - const check = SheetMap.get(selector); - if(!check) - { - const body = `{ ${propertyName}:${propertyValue}; }`; - const rules = activeQuery.val ? `{ @media(${activeQuery.val})${body}}` : body - SheetMap.set(selector, rules); - SheetDOM.insertRule(selector + " " + rules); - } - return selector; - } - type UseCustom = (custom:string)=>string; - return new Proxy(((override:string)=>build(override)) as UseCustom, - { - get(_, prop){ - - return build(lut[prop as string], prop as string); - } - } - ) as T & UseCustom; -} -function MapperQuery>(lut:T) -{ - type UseCustom = (custom:string)=>QueryInvoker; - return new Proxy(((override:string)=>Query(override, override)) as UseCustom, - { - get(_, prop:string){ - return Query(lut[prop], prop) - } - } - ) as Record & UseCustom; -} - - -type ActiveQuery = {key:string|false, val:string|false}; -type QueryInvoker = (...args:string[])=>string - -let activeQuery:ActiveQuery; -const activeQueryStack:ActiveQuery[] = []; -function Query(amount:string, key?:string):QueryInvoker -{ - activeQuery = {key:key||amount, val:amount}; - activeQueryStack.push(activeQuery); - return (...args)=> { - - activeQueryStack.pop() - activeQuery = activeQueryStack.at(-1) || {key:false, val:false}; - return args.join(" "); - } -} - -export function config(obj:T) -{ - const CSS = { - Sheet() - { - const rules = []; - for(const [key, value] of SheetMap.entries()) - { - rules.push("."+key+value); - } - return rules.join("\n"); - }, - Face: Mapper("Face", "font-family", {...typeface, ...obj}), - Pad: Mapper("Pad", "padding", sizes), - Q: MapperQuery(responsive) - }; - return CSS; -} - -export default config({}); \ No newline at end of file diff --git a/index.html b/index.html index 38e07e8..6c1c4d7 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,10 @@ - - - + + + + + Document + -
- + \ No newline at end of file diff --git a/styler.tsx b/styler.tsx deleted file mode 100644 index cdc3595..0000000 --- a/styler.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import Gale from "./gale-custom.tsx"; -import Render from "preact-render-to-string"; - -const jsx =
-hello! -
- -Deno.writeTextFile( -"dump.html", -` - - - - - - ${Render(jsx)} - -` -) - -// idea for table: -// Gale.Table( -// [, "md" ], { -// Face:["serif", "sans" ], -// Pad:["small", "large"] -// }) - -// idea for object -//Gale({ -// lg:{ -// Face:"sans", -// Pad:"small" -// }, -// md:{ -// Pad:"large" -// } -//}) - -// idea for function -//Gale.Gen(g=>[g.md(), g.Face.Sans]) \ No newline at end of file diff --git a/styles.dev.js b/styles.dev.js new file mode 100644 index 0000000..e179198 --- /dev/null +++ b/styles.dev.js @@ -0,0 +1,67 @@ +// @ts-check +const KeyQuery = "@"; +const KeyPseudo = ":"; +const KeyChild = "."; +const KeyGroup = "^"; + +/** + * @typedef { Partial & { + * [key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles; + * } & { + * [key in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[key] | CSSStyleDeclaration[key][] + * }} UserStyles + */ + +/** @typedef {Record & { global?: UserStyles }} UserSheet */ + +/** + * @template {UserSheet} T + * @typedef {keyof T | (string & {})} ValidSelectors + */ + +/** + * @template {UserSheet} T + * @param {T} sheet + * @returns {((...selectors: (keyof T)[]) => string) & { css: string }} + */ +const createCss = (sheet) => { + let i = 0; + const id = i ? "_" + i : ""; + i++; + + const Tier = (selector, obj) => { + 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); + case KeyPseudo: + return Tier(`&${key}`, value); + case KeyChild: + return Tier(`${key}`, value); + case KeyGroup: + return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); + } + return `${key.replace(/([a-z])([A-Z])/g, '$1-$2')}: ${value};`; + }); + return `${selector}{${styles.join("\n")}}`; + }; + + const css = Object.keys(sheet).map(key => Tier("." + key, sheet[key])).join("\n"); + globalThis.document?.head.insertAdjacentHTML("beforeend", ``); + + /** @type {(...args: (keyof T)[]) => string} */ + const classes = (...args) => { + /** @type {(needle: string, str: string) => string} */ + const extractLast = (needle, str) => { + const ind = str.lastIndexOf(needle) + needle.length; + return ind ? str.substring(ind) : str; + }; + return args.map(arg => extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id + " ") + id; + }; + + classes.css = css; + return classes; +}; + +export default createCss; diff --git a/type-experiments-01.ts b/type-experiments-01.ts deleted file mode 100644 index 27bdf82..0000000 --- a/type-experiments-01.ts +++ /dev/null @@ -1,19 +0,0 @@ -////////////////////// -type OriginalType = { - key1: { sub1: string; sub2: string }; - key2: { subA: string; subB: string }; - }; - - type ValidKeys = keyof OriginalType; - type ValidSubKeys = keyof OriginalType[K]; - - type EnforcedRecord = { - [K in ValidKeys]: ValidSubKeys[]; - }; - - // Example usage: - const example: EnforcedRecord = { - key1: ['sub1', 'sub2'], - key2: ['subA', 'subB', "sub1"], // last is invalid - }; - diff --git a/type-experiments-02.ts b/type-experiments-02.ts deleted file mode 100644 index 02b0b29..0000000 --- a/type-experiments-02.ts +++ /dev/null @@ -1,22 +0,0 @@ -type OriginalType = { - key1: { sub1: string; sub2: string }; - key2: { subA: string; subB: string }; -}; - -type ValidKeys = keyof OriginalType; -type ValidSubKeys = keyof OriginalType[K]; - -type FixedLengthArray = [T, ...T[]] & { length: L }; - -type EnforcedRecord = { - [K in ValidKeys]: FixedLengthArray, L>; -}; - - -// Example usage: -const example: EnforcedRecord<2> = { - key1: ['sub1', 'sub2'], // Valid - key2: ['subA', 'subB'], // Valid - // key1: ['sub1'], // Invalid, TypeScript will give an error - // key2: ['subA', 'subB', 'subC'], // Invalid, TypeScript will give an error -}; \ No newline at end of file diff --git a/type-experiments-03.ts b/type-experiments-03.ts deleted file mode 100644 index 4f2e037..0000000 --- a/type-experiments-03.ts +++ /dev/null @@ -1,27 +0,0 @@ -type OriginalType = { - key1: { sub1: string; sub2: string }; - key2: { subA: string; subB: string }; -}; - -type ValidKeys = keyof OriginalType; -type ValidSubKeys = keyof OriginalType[K]; - -type FixedLengthArray = [T, ...T[]] & { length: L }; - -type EnforcedRecord = { - [K in ValidKeys]: FixedLengthArray, L>; -}; - -const createTable = ( - cols: T, - rows: EnforcedRecord -) => { - return { cols, rows }; -}; - -// Example usage: -const cols = ["a", "b", "c"] as const; -const table = createTable(cols, { - key1: ['sub1', 'sub2', 'sub1', 'sub1'], // invalid because too long - key2: ['subA', 'subB', 'sub1'], // invalid because bad key -}); diff --git a/type-experiments-04.ts b/type-experiments-04.ts deleted file mode 100644 index 3fb5f16..0000000 --- a/type-experiments-04.ts +++ /dev/null @@ -1,30 +0,0 @@ -type OriginalType = { - key1: { sub1: string; sub2: string }; - key2: { subA: string; subB: string }; -}; - -type ValidKeys = keyof OriginalType; -type ValidSubKeys = keyof OriginalType[K]; - -type FixedLengthArray = T[] & { length: L }; - -type EnforcedRecord = { - [K in ValidKeys]: FixedLengthArray, L>; -}; - -type FixedArr = Arr & { length: Length }; -function Func(arr1:FixedArr) -{ - return arr1.length; -} - - -const test = Func<3>(["a", "b", "c"]) - -// Example usage: -const example: EnforcedRecord<2> = { - key1: ['sub1', 'sub2', 'sub1'], // Valid - key2: ['subA', 'subB'], // Valid - // key1: ['sub1'], // Invalid, TypeScript will give an error - // key2: ['subA', 'subB', 'subC'], // Invalid, TypeScript will give an error -}; \ No newline at end of file -- 2.34.1 From 1610f490e23c401b544393db209f406fbc3012d8 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 12 Feb 2025 16:09:59 -0500 Subject: [PATCH 05/15] drilling --- app.js | 16 ++++-- deno.json | 3 +- drill.d.ts | 12 +++++ styles.dev.js | 143 +++++++++++++++++++++++++++++++------------------- types.d.ts | 87 ++++++++++++++++++++++++++++++ 5 files changed, 202 insertions(+), 59 deletions(-) create mode 100644 drill.d.ts create mode 100644 types.d.ts diff --git a/app.js b/app.js index fa7542e..e2d3cff 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,15 @@ import Styles from "./styles.dev.js"; + + const sheet = Styles({ - Button:{padding:"20px", background:"orange"}, - Test:{fontSize:"3rem"} -}); \ No newline at end of file + Button:{ + padding:"20px", + background:"orange", + ".Inner":{ + fontSize:"10rem" + } + }, + Outline:{border:"2px solid orange"} +}); + +const el = sheet.dom.div.Button.Outline(); \ No newline at end of file diff --git a/deno.json b/deno.json index b7a8787..64c4916 100644 --- a/deno.json +++ b/deno.json @@ -4,6 +4,7 @@ "lib": [ "deno.window", "DOM" - ] + ], + "types": ["./drill.d.ts"] } } \ No newline at end of file diff --git a/drill.d.ts b/drill.d.ts new file mode 100644 index 0000000..d42b16a --- /dev/null +++ b/drill.d.ts @@ -0,0 +1,12 @@ + +export {} +declare global { + namespace Gale + { + type Invoker =()=>HTMLElement + type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} + type Circular = { + [K in Keys]: Circular&Invoker; + }; + } +} \ No newline at end of file diff --git a/styles.dev.js b/styles.dev.js index e179198..f934bf7 100644 --- a/styles.dev.js +++ b/styles.dev.js @@ -1,67 +1,100 @@ -// @ts-check const KeyQuery = "@"; const KeyPseudo = ":"; const KeyChild = "."; const KeyGroup = "^"; -/** - * @typedef { Partial & { - * [key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles; - * } & { - * [key in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[key] | CSSStyleDeclaration[key][] - * }} UserStyles - */ +/** @typedef { Partial & {[key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles } } UserStyles */ +/** @typedef {Record} UserSheet */ -/** @typedef {Record & { global?: UserStyles }} UserSheet */ -/** - * @template {UserSheet} T - * @typedef {keyof T | (string & {})} ValidSelectors +/** + * @template Obj + * @typedef { { [Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj] } CollectKeys */ /** - * @template {UserSheet} T - * @param {T} sheet - * @returns {((...selectors: (keyof T)[]) => string) & { css: string }} + * @template Keys + * @typedef { Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never } FilterKeys + */ +/** + * @template A + * @template B + * @typedef {A extends string ? B extends string ? `${A}${B}` : never : never } CrossMultiply */ -const createCss = (sheet) => { - let i = 0; - const id = i ? "_" + i : ""; - i++; - - const Tier = (selector, obj) => { - 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); - case KeyPseudo: - return Tier(`&${key}`, value); - case KeyChild: - return Tier(`${key}`, value); - case KeyGroup: - return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); - } - return `${key.replace(/([a-z])([A-Z])/g, '$1-$2')}: ${value};`; - }); - return `${selector}{${styles.join("\n")}}`; - }; - - const css = Object.keys(sheet).map(key => Tier("." + key, sheet[key])).join("\n"); - globalThis.document?.head.insertAdjacentHTML("beforeend", ``); - - /** @type {(...args: (keyof T)[]) => string} */ - const classes = (...args) => { - /** @type {(needle: string, str: string) => string} */ - const extractLast = (needle, str) => { - const ind = str.lastIndexOf(needle) + needle.length; - return ind ? str.substring(ind) : str; - }; - return args.map(arg => extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id + " ") + id; - }; - - classes.css = css; - return classes; -}; -export default createCss; +/** + * @template Rec + * @typedef { keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] } CrossMultiplyRecord + */ + + +/** @type {(selector:string, obj:UserStyles)=>string} */ +const Tier=(selector, obj)=> +{ + 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); + case KeyPseudo : + return Tier(`&${key}`, value); + case KeyChild : + return Tier(`${key}`, value); + case KeyGroup : + return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); + } + return `${ key.replace(/([a-z])([A-Z])/g, '$1-$2') }: ${value};` + }); + return `${selector}{${styles.join("\n")}}`; +} + + +/** @type {(ref:T)=>Gale.Elemental>} */ +function MakeElemental(ref) +{ + let pending = false; + let classes = []; + + const collector = new Proxy(()=>{console.log("original func invoked!", pending, classes)}, + { + get(target, prop, rec) + { + classes.push(prop); + return collector; + } + } + ); + + const obj = new Proxy({}, {get(target, prop, rec) + { + pending = prop; + classes = []; + return collector; + } + }); + + return obj; +} + +let i = 0; +/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string, dom:Gale.Elemental>} } */ +export default (sheet)=> +{ + const id = i ? "_"+i : ""; + i++; + const css = Object.keys(sheet).map(key=>Tier("."+key, sheet[key])).join(`\n`); + globalThis.document?.head.insertAdjacentHTML("beforeend", ``); + const classes =(...args)=>{ + /** @type {(needle:string, str:string)=>string} */ + const extractLast =(needle, str)=>{ + const ind = str.lastIndexOf(needle)+needle.length; + return ind ? str.substring(ind) : str; + } + return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; + } + classes.css = css; + classes.dom = MakeElemental(sheet); + return classes; +} \ No newline at end of file diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 0000000..f29e88b --- /dev/null +++ b/types.d.ts @@ -0,0 +1,87 @@ +export {} +declare global +{ + namespace Van { + + interface State { + val: T + readonly oldVal: T + readonly rawVal: T + } + + // Defining readonly view of State for covariance. + // Basically we want StateView to implement StateView + type StateView = Readonly> + + type Val = State | T + + type Primitive = string | number | boolean | bigint + + // deno-lint-ignore no-explicit-any + type PropValue = Primitive | ((e: any) => void) | null + + type PropValueOrDerived = PropValue | StateView | (() => PropValue) + + type Props = Record & { class?: PropValueOrDerived; is?: string } + + type PropsWithKnownKeys = Partial<{[K in keyof ElementType]: PropValueOrDerived}> + + type ValidChildDomValue = Primitive | Node | null | undefined + + type BindingFunc = ((dom?: Node) => ValidChildDomValue) | ((dom?: Element) => Element) + + type ChildDom = ValidChildDomValue | StateView | BindingFunc | readonly ChildDom[] + + type TagFunc = (first?: Props & PropsWithKnownKeys | ChildDom, ...rest: readonly ChildDom[]) => Result + + type Tags = Readonly>> & { + [K in keyof HTMLElementTagNameMap]: TagFunc + } + } + const van:{ + readonly state: (initVal: T, HMRKey?:string)=> Van.State + readonly derive: (f: () => T) => Van.State + readonly add: (dom: Element, ...children: readonly Van.ChildDom[]) => Element + readonly tags: Van.Tags & ((namespaceURI: string) => Readonly>>) + readonly hydrate: (dom: T, f: (dom: T) => T | null | undefined) => T + }; + + + namespace VanX + { + type StateOf = { readonly [K in keyof T]: Van.State } + type ValueType = T extends (infer V)[] ? V : T[keyof T] + type KeyType = T extends unknown[] ? number : string + type ReplacementFunc = + T extends (infer V)[] ? (items: V[]) => readonly V[] : + (items: [string, T[keyof T]][]) => readonly [string, T[keyof T]][] + } + const vanX:{ + readonly calc: (f: () => R) => R + readonly reactive: (obj: T, HMRKey?:string) => T + readonly noreactive: (obj: T) => T + readonly stateFields: (obj: T) => VanX.StateOf + readonly raw: (obj: T) => T + readonly list: (container: (() => ElementType) | ElementType, items: T,itemFunc: (v: Van.State>, deleter: () => void, k: VanX.KeyType) => Node) => ElementType + readonly replace: (obj: T, replacement: VanX.ReplacementFunc | T) => T + readonly compact: (obj: T) => T + }; + + namespace Gale { + type KeyQuery = "@"; + type KeyPseudo = ":"; + type KeyChild = "."; + type KeyGroup = "^"; + type UserStyles = Partial & {[key: `${KeyQuery|KeyPseudo|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)=>string; + type CreateSheet = (sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string} + } + + const Gale:Gale.CreateSheet + +} \ No newline at end of file -- 2.34.1 From a009f334eb5be0d1e3f6e696f4f7127d98a3201e Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 12 Feb 2025 16:57:41 -0500 Subject: [PATCH 06/15] element builder working with Van --- app.js | 6 +++++- deno.json | 2 +- drill.d.ts | 7 +++---- index.html | 1 + styles.dev.js | 7 ++++++- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app.js b/app.js index e2d3cff..c5a91ce 100644 --- a/app.js +++ b/app.js @@ -12,4 +12,8 @@ const sheet = Styles({ Outline:{border:"2px solid orange"} }); -const el = sheet.dom.div.Button.Outline(); \ No newline at end of file +const el = sheet.dom.a.Button.Outline({onclick(){console.log("clicked!")}}, "Click!"); +console.log(el); + + +van.add(document.body, el, sheet.dom.p.Outline("paragraph!")); \ No newline at end of file diff --git a/deno.json b/deno.json index 64c4916..bee32bd 100644 --- a/deno.json +++ b/deno.json @@ -5,6 +5,6 @@ "deno.window", "DOM" ], - "types": ["./drill.d.ts"] + "types": ["./drill.d.ts", "./types.d.ts"] } } \ No newline at end of file diff --git a/drill.d.ts b/drill.d.ts index d42b16a..eb905e5 100644 --- a/drill.d.ts +++ b/drill.d.ts @@ -3,10 +3,9 @@ export {} declare global { namespace Gale { - type Invoker =()=>HTMLElement - type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} - type Circular = { - [K in Keys]: Circular&Invoker; + type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} + type Circular = { + [K in Keys]: Circular&Van.TagFunc; }; } } \ No newline at end of file diff --git a/index.html b/index.html index 6c1c4d7..0b78f94 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ Document + \ No newline at end of file diff --git a/styles.dev.js b/styles.dev.js index f934bf7..a26253d 100644 --- a/styles.dev.js +++ b/styles.dev.js @@ -57,7 +57,12 @@ function MakeElemental(ref) let pending = false; let classes = []; - const collector = new Proxy(()=>{console.log("original func invoked!", pending, classes)}, + const collector = new Proxy((...args)=>{ + console.log("original func invoked!", pending, classes); + const element = van.tags[pending](...args); + element.className = classes.join(" "); + return element + }, { get(target, prop, rec) { -- 2.34.1 From 04c0b789ebc1bc6a61e618818ca781b0cbd261da Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 12 Feb 2025 17:09:58 -0500 Subject: [PATCH 07/15] reduce --- app.js | 2 +- deno.json | 2 +- drill.d.ts | 11 ------ gale.js | 37 +++++++++++++++++- styles.dev.js | 105 -------------------------------------------------- types.d.ts | 6 +++ 6 files changed, 43 insertions(+), 120 deletions(-) delete mode 100644 drill.d.ts delete mode 100644 styles.dev.js diff --git a/app.js b/app.js index c5a91ce..a112139 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -import Styles from "./styles.dev.js"; +import Styles from "./gale.js"; const sheet = Styles({ diff --git a/deno.json b/deno.json index bee32bd..e1aa6b8 100644 --- a/deno.json +++ b/deno.json @@ -5,6 +5,6 @@ "deno.window", "DOM" ], - "types": ["./drill.d.ts", "./types.d.ts"] + "types": ["./types.d.ts"] } } \ No newline at end of file diff --git a/drill.d.ts b/drill.d.ts deleted file mode 100644 index eb905e5..0000000 --- a/drill.d.ts +++ /dev/null @@ -1,11 +0,0 @@ - -export {} -declare global { - namespace Gale - { - type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} - type Circular = { - [K in Keys]: Circular&Van.TagFunc; - }; - } -} \ No newline at end of file diff --git a/gale.js b/gale.js index 4646e3a..a26253d 100644 --- a/gale.js +++ b/gale.js @@ -1,4 +1,3 @@ -// @ts-check const KeyQuery = "@"; const KeyPseudo = ":"; const KeyChild = "."; @@ -51,8 +50,41 @@ const Tier=(selector, obj)=> return `${selector}{${styles.join("\n")}}`; } + +/** @type {(ref:T)=>Gale.Elemental>} */ +function MakeElemental(ref) +{ + let pending = false; + let classes = []; + + const collector = new Proxy((...args)=>{ + console.log("original func invoked!", pending, classes); + const element = van.tags[pending](...args); + element.className = classes.join(" "); + return element + }, + { + get(target, prop, rec) + { + classes.push(prop); + return collector; + } + } + ); + + const obj = new Proxy({}, {get(target, prop, rec) + { + pending = prop; + classes = []; + return collector; + } + }); + + return obj; +} + let i = 0; -/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string}} */ +/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string, dom:Gale.Elemental>} } */ export default (sheet)=> { const id = i ? "_"+i : ""; @@ -68,5 +100,6 @@ export default (sheet)=> return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; } classes.css = css; + classes.dom = MakeElemental(sheet); return classes; } \ No newline at end of file diff --git a/styles.dev.js b/styles.dev.js deleted file mode 100644 index a26253d..0000000 --- a/styles.dev.js +++ /dev/null @@ -1,105 +0,0 @@ -const KeyQuery = "@"; -const KeyPseudo = ":"; -const KeyChild = "."; -const KeyGroup = "^"; - -/** @typedef { Partial & {[key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles } } UserStyles */ -/** @typedef {Record} UserSheet */ - - -/** - * @template Obj - * @typedef { { [Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj] } CollectKeys - */ - -/** - * @template Keys - * @typedef { Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never } FilterKeys - */ -/** - * @template A - * @template B - * @typedef {A extends string ? B extends string ? `${A}${B}` : never : never } CrossMultiply - */ - -/** - * @template Rec - * @typedef { keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] } CrossMultiplyRecord - */ - - -/** @type {(selector:string, obj:UserStyles)=>string} */ -const Tier=(selector, obj)=> -{ - 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); - case KeyPseudo : - return Tier(`&${key}`, value); - case KeyChild : - return Tier(`${key}`, value); - case KeyGroup : - return Tier(`&:hover .${key.substring(KeyGroup.length)}`, value); - } - return `${ key.replace(/([a-z])([A-Z])/g, '$1-$2') }: ${value};` - }); - return `${selector}{${styles.join("\n")}}`; -} - - -/** @type {(ref:T)=>Gale.Elemental>} */ -function MakeElemental(ref) -{ - let pending = false; - let classes = []; - - const collector = new Proxy((...args)=>{ - console.log("original func invoked!", pending, classes); - const element = van.tags[pending](...args); - element.className = classes.join(" "); - return element - }, - { - get(target, prop, rec) - { - classes.push(prop); - return collector; - } - } - ); - - const obj = new Proxy({}, {get(target, prop, rec) - { - pending = prop; - classes = []; - return collector; - } - }); - - return obj; -} - -let i = 0; -/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string, dom:Gale.Elemental>} } */ -export default (sheet)=> -{ - const id = i ? "_"+i : ""; - i++; - const css = Object.keys(sheet).map(key=>Tier("."+key, sheet[key])).join(`\n`); - globalThis.document?.head.insertAdjacentHTML("beforeend", ``); - const classes =(...args)=>{ - /** @type {(needle:string, str:string)=>string} */ - const extractLast =(needle, str)=>{ - const ind = str.lastIndexOf(needle)+needle.length; - return ind ? str.substring(ind) : str; - } - return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; - } - classes.css = css; - classes.dom = MakeElemental(sheet); - return classes; -} \ No newline at end of file diff --git a/types.d.ts b/types.d.ts index f29e88b..8926512 100644 --- a/types.d.ts +++ b/types.d.ts @@ -80,6 +80,12 @@ declare global type CrossMultiplyRecord = keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] type Tier = (selector:string, obj:UserStyles)=>string; type CreateSheet = (sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string} + + type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} + type Circular = { + [K in Keys]: Circular&Van.TagFunc; + }; + } const Gale:Gale.CreateSheet -- 2.34.1 From 8d82c41f81a502b4cadfe400dc4af3491b186b04 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Thu, 13 Feb 2025 14:27:41 -0500 Subject: [PATCH 08/15] move types --- app.js | 24 ++++++------- gale.js | 98 +++++++++++++++++++----------------------------------- index.html | 1 + types.d.ts | 8 ++--- 4 files changed, 51 insertions(+), 80 deletions(-) diff --git a/app.js b/app.js index a112139..025ba73 100644 --- a/app.js +++ b/app.js @@ -1,19 +1,19 @@ -import Styles from "./gale.js"; - - -const sheet = Styles({ - Button:{ - padding:"20px", - background:"orange", - ".Inner":{ - fontSize:"10rem" +const {DOM} = Gale({ + Button: { + padding: "20px", + background: "orange", + ".Inner": { + fontSize: "10rem" } }, - Outline:{border:"2px solid orange"} + Outline: { + border: "2px solid orange" + } }); -const el = sheet.dom.a.Button.Outline({onclick(){console.log("clicked!")}}, "Click!"); + +const el = DOM.a.Button.Outline({onclick(){console.log("clicked!")}}, "Click!"); console.log(el); -van.add(document.body, el, sheet.dom.p.Outline("paragraph!")); \ No newline at end of file +van.add(document.body, el, DOM.h1.Outline["Button.Inner"]("title")); \ No newline at end of file diff --git a/gale.js b/gale.js index a26253d..742b4aa 100644 --- a/gale.js +++ b/gale.js @@ -3,32 +3,7 @@ const KeyPseudo = ":"; const KeyChild = "."; const KeyGroup = "^"; -/** @typedef { Partial & {[key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles } } UserStyles */ -/** @typedef {Record} UserSheet */ - - -/** - * @template Obj - * @typedef { { [Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj] } CollectKeys - */ - -/** - * @template Keys - * @typedef { Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never } FilterKeys - */ -/** - * @template A - * @template B - * @typedef {A extends string ? B extends string ? `${A}${B}` : never : never } CrossMultiply - */ - -/** - * @template Rec - * @typedef { keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] } CrossMultiplyRecord - */ - - -/** @type {(selector:string, obj:UserStyles)=>string} */ +/** @type {Gale.Tier} */ const Tier=(selector, obj)=> { const styles = Object.keys(obj).map((key)=> @@ -50,42 +25,9 @@ const Tier=(selector, obj)=> return `${selector}{${styles.join("\n")}}`; } - -/** @type {(ref:T)=>Gale.Elemental>} */ -function MakeElemental(ref) -{ - let pending = false; - let classes = []; - - const collector = new Proxy((...args)=>{ - console.log("original func invoked!", pending, classes); - const element = van.tags[pending](...args); - element.className = classes.join(" "); - return element - }, - { - get(target, prop, rec) - { - classes.push(prop); - return collector; - } - } - ); - - const obj = new Proxy({}, {get(target, prop, rec) - { - pending = prop; - classes = []; - return collector; - } - }); - - return obj; -} - let i = 0; -/** @type {(sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string, dom:Gale.Elemental>} } */ -export default (sheet)=> +/** @type {Gale.CreateSheet} */ +const Gale = (sheet)=> { const id = i ? "_"+i : ""; i++; @@ -99,7 +41,37 @@ export default (sheet)=> } return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; } - classes.css = css; - classes.dom = MakeElemental(sheet); + + let pending = false; + let mentioned = []; + const collector = new Proxy( + (...args)=> + { + const element = van.tags[pending](...args); + element.className = mentioned.join(" "); + return element; + }, + { + get(_, prop) + { + mentioned.push(prop.substring(prop.lastIndexOf(".")+1)); + return collector; + } + } + ); + + + classes.CSS = css; + classes.DOM = new Proxy( + {}, + {get(_, prop) + { + pending = prop; + mentioned = []; + return collector; + } + } + ); + return classes; } \ No newline at end of file diff --git a/index.html b/index.html index 0b78f94..1f7546e 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,7 @@ + \ No newline at end of file diff --git a/types.d.ts b/types.d.ts index 8926512..6c8d594 100644 --- a/types.d.ts +++ b/types.d.ts @@ -79,15 +79,13 @@ declare global 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)=>string; - type CreateSheet = (sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string} + type CreateSheet = (sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{CSS:string, DOM:Elemental>} + type Elemental = {[K in keyof HTMLElementTagNameMap]: Circular} type Circular = { [K in Keys]: Circular&Van.TagFunc; }; - + } - - const Gale:Gale.CreateSheet - } \ No newline at end of file -- 2.34.1 From e089203b2f6ad99fe494cbf0fcd175a5069c6137 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Wed, 19 Feb 2025 17:01:11 -0500 Subject: [PATCH 09/15] bunch of edits --- app.js | 32 +++++++++++++++++++++++++++++--- gale.js | 2 +- index.html | 31 +++++++++++++++++++++---------- proxy.js | 32 ++++++++++++++++++++++++++++++++ proxy.test.ts | 9 +++++++++ types.d.ts | 5 ++++- 6 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 proxy.js create mode 100644 proxy.test.ts diff --git a/app.js b/app.js index 025ba73..87b4e2d 100644 --- a/app.js +++ b/app.js @@ -12,8 +12,34 @@ const {DOM} = Gale({ }); -const el = DOM.a.Button.Outline({onclick(){console.log("clicked!")}}, "Click!"); -console.log(el); +/** @typedef {{done:boolean, text:string}} Todo */ +/** @type {(obj:T, key:string)=>T} */ +const Store =(obj, key)=> { + const recall = localStorage.getItem(key); + const store = vanX.reactive(recall ? JSON.parse(recall) : obj); + van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store)))); + return store; +} -van.add(document.body, el, DOM.h1.Outline["Button.Inner"]("title")); \ No newline at end of file +const items = Store({ + pending:"", + todos:/** @type {Todo[]}*/([]) +}, "Todos?"); + +const {div, input, button, del, span, a} = van.tags; + +const TodoList = () => { + const inputDom = input({type: "text", value:()=>items.pending, oninput(){items.pending = this.value}}); + return div( + ()=>div(items.pending), + inputDom, DOM.button.Outline.Button({onclick: () => items.todos.push({text: inputDom.value, done: false})}, "Add"), + vanX.list(div, items.todos, ({val: v}, deleter) => div( + input({type: "checkbox", checked: () => v.done, onclick: e => v.done = e.target.checked}), + () => (v.done ? del : span)(v.text), + a({onclick: deleter}, "❌"), + )), + ) +} + +van.add(document.body, TodoList()); \ No newline at end of file diff --git a/gale.js b/gale.js index 742b4aa..302da8f 100644 --- a/gale.js +++ b/gale.js @@ -27,7 +27,7 @@ const Tier=(selector, obj)=> let i = 0; /** @type {Gale.CreateSheet} */ -const Gale = (sheet)=> +globalThis.Gale =sheet=> { const id = i ? "_"+i : ""; i++; diff --git a/index.html b/index.html index 1f7546e..2eeec3b 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,23 @@ - - - - Document - - - - - - + + + + Document + + + + + + + + \ No newline at end of file diff --git a/proxy.js b/proxy.js new file mode 100644 index 0000000..40d355e --- /dev/null +++ b/proxy.js @@ -0,0 +1,32 @@ +const person = van.state({name:"seth", age:41}); +console.log(Object.hasOwn(person, "rawVal")); + +/** @type {(obj:T, key:string)=>T} */ +const Deep =(obj, key)=> +{ + const proxInner =(context, key)=> new Proxy({}, { + get(_, prop) + { + const path = key+" . "+prop; + console.log(path, "accessed!"); + const value = context[key]; + + return proxInner(value, path); + } + }); + + const proxOuter = new Proxy({}, { + get(_, prop) + { + return proxInner(obj, prop); + }, + set(_, prop, val) + { + obj[prop] = val; + } + }); + + return proxOuter; +} + +export default Deep; \ No newline at end of file diff --git a/proxy.test.ts b/proxy.test.ts new file mode 100644 index 0000000..e3323f2 --- /dev/null +++ b/proxy.test.ts @@ -0,0 +1,9 @@ +import * as assert from "jsr:@std/assert"; +import Deep from "./proxy.js"; + +Deno.test("proxy", ()=>{ + + const d1 = Deep({name:"seth", age:41, tags:[]}, "p1"); + const dig = d1.name.other; + const dig2 = dig.so.deep; +}); \ No newline at end of file diff --git a/types.d.ts b/types.d.ts index 6c8d594..5440e9a 100644 --- a/types.d.ts +++ b/types.d.ts @@ -62,7 +62,10 @@ declare global readonly noreactive: (obj: T) => T readonly stateFields: (obj: T) => VanX.StateOf readonly raw: (obj: T) => T - readonly list: (container: (() => ElementType) | ElementType, items: T,itemFunc: (v: Van.State>, deleter: () => void, k: VanX.KeyType) => Node) => ElementType + readonly list: ( + container: (() => ElementType) | ElementType, + items: T,itemFunc: (v: Van.State>, deleter: () => void, k: VanX.KeyType) => Node + ) => ElementType readonly replace: (obj: T, replacement: VanX.ReplacementFunc | T) => T readonly compact: (obj: T) => T }; -- 2.34.1 From 93484f3900726cfbd9bf47ea2299029d21d22be7 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 21 Feb 2025 07:55:08 -0500 Subject: [PATCH 10/15] test fixes --- .vscode/settings.json | 4 ++++ proxy.js | 31 ++++++++++++++++++++++++------- proxy.test.ts | 5 +++-- 3 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b0c98a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "deno.cacheOnSave": true, + "deno.codeLens.test": true +} \ No newline at end of file diff --git a/proxy.js b/proxy.js index 40d355e..7da72dc 100644 --- a/proxy.js +++ b/proxy.js @@ -1,17 +1,34 @@ -const person = van.state({name:"seth", age:41}); -console.log(Object.hasOwn(person, "rawVal")); +//const person = van.state({name:"seth", age:41}); +//console.log(Object.hasOwn(person, "rawVal")); + +const isLeaf =(obj, key)=> +{ + const type = typeof arg; + if(arg == null || type == "") + { + + } +} /** @type {(obj:T, key:string)=>T} */ const Deep =(obj, key)=> { + const proxInner =(context, key)=> new Proxy({}, { get(_, prop) { - const path = key+" . "+prop; - console.log(path, "accessed!"); - const value = context[key]; - - return proxInner(value, path); + if(typeof prop === "string") + { + const path = key+" . "+prop; + console.log(path, "accessed!"); + const value = context[prop]; + + return proxInner(value, path); + } + else + { + return context[prop] + } } }); diff --git a/proxy.test.ts b/proxy.test.ts index e3323f2..a86ebae 100644 --- a/proxy.test.ts +++ b/proxy.test.ts @@ -4,6 +4,7 @@ import Deep from "./proxy.js"; Deno.test("proxy", ()=>{ const d1 = Deep({name:"seth", age:41, tags:[]}, "p1"); - const dig = d1.name.other; - const dig2 = dig.so.deep; + const dig = d1.name; + //const dig2 = dig.so.deep; + }); \ No newline at end of file -- 2.34.1 From 2451055d9f922cdfec93a21e7e0cff61fe903f41 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sat, 22 Feb 2025 09:37:11 -0500 Subject: [PATCH 11/15] fix gale nested calls --- app.js | 37 ++++++++++++++++++++++++++++++++++--- gale.js | 40 ++++++++++++++++++---------------------- index.html | 11 +---------- proxy.js | 4 ++-- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/app.js b/app.js index 87b4e2d..db0a8fc 100644 --- a/app.js +++ b/app.js @@ -8,6 +8,24 @@ const {DOM} = Gale({ }, 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)" + } } }); @@ -22,6 +40,21 @@ const Store =(obj, key)=> { return store; } + + +const UI =()=> +{ + return DOM.div.Window( + DOM.div.Ability(), + DOM.div.Ability(), + DOM.div.Ability(), + ) +} + +van.add(document.body, UI()); + + + const items = Store({ pending:"", todos:/** @type {Todo[]}*/([]) @@ -40,6 +73,4 @@ const TodoList = () => { a({onclick: deleter}, "❌"), )), ) -} - -van.add(document.body, TodoList()); \ No newline at end of file +} \ No newline at end of file diff --git a/gale.js b/gale.js index 302da8f..2ecf1d7 100644 --- a/gale.js +++ b/gale.js @@ -41,33 +41,29 @@ globalThis.Gale =sheet=> } return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id; } - - let pending = false; - let mentioned = []; - const collector = new Proxy( - (...args)=> - { - const element = van.tags[pending](...args); - element.className = mentioned.join(" "); - return element; - }, - { - get(_, prop) - { - mentioned.push(prop.substring(prop.lastIndexOf(".")+1)); - return collector; - } - } - ); - - + classes.CSS = css; classes.DOM = new Proxy( {}, {get(_, prop) { - pending = prop; - mentioned = []; + const pending = prop; + const mentioned = []; + const collector = new Proxy( + (...args)=> + { + const element = van.tags[pending](...args); + element.className = mentioned.join(" "); + return element; + }, + { + get(_, prop) + { + mentioned.push(prop.substring(prop.lastIndexOf(".")+1)); + return collector; + } + } + ); return collector; } } diff --git a/index.html b/index.html index 2eeec3b..9edf7ff 100644 --- a/index.html +++ b/index.html @@ -3,21 +3,12 @@ Document + - \ No newline at end of file diff --git a/proxy.js b/proxy.js index 40d355e..d71ecd4 100644 --- a/proxy.js +++ b/proxy.js @@ -1,5 +1,5 @@ -const person = van.state({name:"seth", age:41}); -console.log(Object.hasOwn(person, "rawVal")); +//const person = van.state({name:"seth", age:41}); +//console.log(Object.hasOwn(person, "rawVal")); /** @type {(obj:T, key:string)=>T} */ const Deep =(obj, key)=> -- 2.34.1 From 28dc00fa908afae16d95ce3683d96b9a6cc4483a Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sat, 22 Feb 2025 10:22:16 -0500 Subject: [PATCH 12/15] add deno init --- .vscode/settings.json | 4 ---- deno.json | 3 +++ index.html | 18 +++++++++++++++++- proxy.js | 40 ---------------------------------------- proxy.test.ts | 10 ---------- 5 files changed, 20 insertions(+), 55 deletions(-) delete mode 100644 .vscode/settings.json delete mode 100644 proxy.js delete mode 100644 proxy.test.ts diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index b0c98a8..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "deno.cacheOnSave": true, - "deno.codeLens.test": true -} \ No newline at end of file diff --git a/deno.json b/deno.json index e1aa6b8..bbb3e72 100644 --- a/deno.json +++ b/deno.json @@ -6,5 +6,8 @@ "DOM" ], "types": ["./types.d.ts"] + }, + "imports": { + "entry":"./app.js" } } \ No newline at end of file diff --git a/index.html b/index.html index 9edf7ff..5e6e962 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,22 @@ - + \ No newline at end of file diff --git a/proxy.js b/proxy.js deleted file mode 100644 index 60ae474..0000000 --- a/proxy.js +++ /dev/null @@ -1,40 +0,0 @@ -//const person = van.state({name:"seth", age:41}); -//console.log(Object.hasOwn(person, "rawVal")); - -/** @type {(obj:T, key:string)=>T} */ -const Deep =(obj, key)=> -{ - - const proxInner =(context, key)=> new Proxy({}, { - get(_, prop) - { - if(typeof prop === "string") - { - const path = key+" . "+prop; - console.log(path, "accessed!"); - const value = context[prop]; - - return proxInner(value, path); - } - else - { - return context[prop] - } - } - }); - - const proxOuter = new Proxy({}, { - get(_, prop) - { - return proxInner(obj, prop); - }, - set(_, prop, val) - { - obj[prop] = val; - } - }); - - return proxOuter; -} - -export default Deep; \ No newline at end of file diff --git a/proxy.test.ts b/proxy.test.ts deleted file mode 100644 index a86ebae..0000000 --- a/proxy.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as assert from "jsr:@std/assert"; -import Deep from "./proxy.js"; - -Deno.test("proxy", ()=>{ - - const d1 = Deep({name:"seth", age:41, tags:[]}, "p1"); - const dig = d1.name; - //const dig2 = dig.so.deep; - -}); \ No newline at end of file -- 2.34.1 From a9ecc4672ae5540024b680b4f3d2345049605a1b Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sat, 22 Feb 2025 16:38:11 -0500 Subject: [PATCH 13/15] deno scripts started --- index.html => _index.html | 0 app.js | 34 +++----------- types.d.ts => bundle.d.ts | 3 ++ bundle.js | 17 +++++++ deno.json | 2 +- deno.lock | 95 +++++++++++++++++++++++++++++++++++++++ dev_server.ts | 94 ++++++++++++++++++++++++++++++++++++++ refresh_types.ts | 33 ++++++++++++++ 8 files changed, 249 insertions(+), 29 deletions(-) rename index.html => _index.html (100%) rename types.d.ts => bundle.d.ts (97%) create mode 100644 bundle.js create mode 100644 deno.lock create mode 100644 dev_server.ts create mode 100644 refresh_types.ts diff --git a/index.html b/_index.html similarity index 100% rename from index.html rename to _index.html diff --git a/app.js b/app.js index db0a8fc..b6a7c6b 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ const {DOM} = Gale({ Button: { padding: "20px", - background: "orange", + background: "blue", ".Inner": { fontSize: "10rem" } @@ -31,34 +31,10 @@ const {DOM} = Gale({ /** @typedef {{done:boolean, text:string}} Todo */ - -/** @type {(obj:T, key:string)=>T} */ -const Store =(obj, key)=> { - const recall = localStorage.getItem(key); - const store = vanX.reactive(recall ? JSON.parse(recall) : obj); - van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store)))); - return store; -} - - - -const UI =()=> -{ - return DOM.div.Window( - DOM.div.Ability(), - DOM.div.Ability(), - DOM.div.Ability(), - ) -} - -van.add(document.body, UI()); - - - -const items = Store({ +const items = vanX.Store({ pending:"", todos:/** @type {Todo[]}*/([]) -}, "Todos?"); +}, "Todos"); const {div, input, button, del, span, a} = van.tags; @@ -73,4 +49,6 @@ const TodoList = () => { a({onclick: deleter}, "❌"), )), ) -} \ No newline at end of file +} + +van.add(document.body, TodoList()); \ No newline at end of file diff --git a/types.d.ts b/bundle.d.ts similarity index 97% rename from types.d.ts rename to bundle.d.ts index 5440e9a..2f14ea2 100644 --- a/types.d.ts +++ b/bundle.d.ts @@ -68,6 +68,8 @@ declare global ) => ElementType readonly replace: (obj: T, replacement: VanX.ReplacementFunc | T) => T readonly compact: (obj: T) => T + // my addition + readonly Store: (obj:T, key:string)=>T }; namespace Gale { @@ -91,4 +93,5 @@ declare global }; } + const Gale:Gale.CreateSheet } \ No newline at end of file diff --git a/bundle.js b/bundle.js new file mode 100644 index 0000000..930cf6a --- /dev/null +++ b/bundle.js @@ -0,0 +1,17 @@ +//van +{let e,t,r,o,n,l,s,i,f,h,w,a,d,u,_,c,S,g,y,b,m,v,j,x,O;s=Object.getPrototypeOf,f={},h=s(i={isConnected:1}),w=s(s),a=(e,t,r,o)=>(e??(setTimeout(r,o),new Set)).add(t),d=(e,t,o)=>{let n=r;r=t;try{return e(o)}catch(e){return console.error(e),o}finally{r=n}},u=e=>e.filter(e=>e.t?.isConnected),_=e=>n=a(n,e,()=>{for(let e of n)e.o=u(e.o),e.l=u(e.l);n=l},1e3),c={get val(){return r?.i?.add(this),this.rawVal},get oldVal(){return r?.i?.add(this),this.h},set val(o){r?.u?.add(this),o!==this.rawVal&&(this.rawVal=o,this.o.length+this.l.length?(t?.add(this),e=a(e,this,x)):this.h=o)}},S=e=>({__proto__:c,rawVal:e,h:e,o:[],l:[]}),g=(e,t)=>{let r={i:new Set,u:new Set},n={f:e},l=o;o=[];let s=d(e,r,t);s=(s??document).nodeType?s:new Text(s);for(let e of r.i)r.u.has(e)||(_(e),e.o.push(n));for(let e of o)e.t=s;return o=l,n.t=s},y=(e,t=S(),r)=>{let n={i:new Set,u:new Set},l={f:e,s:t};l.t=r??o?.push(l)??i,t.val=d(e,n,t.rawVal);for(let e of n.i)n.u.has(e)||(_(e),e.l.push(l));return t},b=(e,...t)=>{for(let r of t.flat(1/0)){let t=s(r??0),o=t===c?g(()=>r.val):t===w?g(r):r;o!=l&&e.append(o)}return e},m=(e,t,...r)=>{let[{is:o,...n},...i]=s(r[0]??0)===h?r:[{},...r],a=e?document.createElementNS(e,t,{is:o}):document.createElement(t,{is:o});for(let[e,r]of Object.entries(n)){let o=t=>t?Object.getOwnPropertyDescriptor(t,e)??o(s(t)):l,n=t+","+e,i=f[n]??=o(s(a))?.set??0,h=e.startsWith("on")?(t,r)=>{let o=e.slice(2);a.removeEventListener(o,r),a.addEventListener(o,t)}:i?i.bind(a):a.setAttribute.bind(a,e),d=s(r??0);e.startsWith("on")||d===w&&(r=y(r),d=c),d===c?g(()=>(h(r.val,r.h),a)):h(r)}return b(a,i)},v=e=>({get:(t,r)=>m.bind(l,e,r)}),j=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),x=()=>{let r=0,o=[...e].filter(e=>e.rawVal!==e.h);do{t=new Set;for(let e of new Set(o.flatMap(e=>e.l=u(e.l))))y(e.f,e.s,e.t),e.t=l}while(++r<100&&(o=[...t]).length);let n=[...e].filter(e=>e.rawVal!==e.h);e=l;for(let e of new Set(n.flatMap(e=>e.o=u(e.o))))j(e.t,g(e.f,e.t)),e.t=l;for(let e of n)e.h=e.rawVal},O={tags:new Proxy(e=>new Proxy(m,v(e)),v()),hydrate:(e,t)=>j(e,g(t,e)),add:b,state:S,derive:y},window.van=O;} +//vanx +{let e,t,r,{fromEntries:o,entries:l,keys:n,hasOwn:f,getPrototypeOf:a}=Object,{get:i,set:y,deleteProperty:c,ownKeys:s}=Reflect,{state:m,derive:d,add:u}=van,b=1e3,w=Symbol(),A=Symbol(),S=Symbol(),_=Symbol(),g=Symbol(),p=Symbol(),P=e=>(e[A]=1,e),v=e=>e instanceof Object&&!(e instanceof Function)&&!e[p],h=e=>{if(e?.[A]){let t=m();return d(()=>{let r=e();v(t.rawVal)&&v(r)?B(t.rawVal,r):t.val=x(r)}),t}return m(x(e))},F=e=>{let t=Array.isArray(e)?[]:{__proto__:a(e)};for(let[r,o]of l(e))t[r]=h(o);return t[S]=[],t[_]=m(1),t},O={get:(e,t,r)=>t===w?e:f(e,t)?Array.isArray(e)&&"length"===t?(e[_].val,e.length):e[t].val:i(e,t,r),set:(e,o,l,n)=>f(e,o)?Array.isArray(e)&&"length"===o?(l!==e.length&&++e[_].val,e.length=l,1):(e[o].val=x(l),1):o in e?y(e,o,l,n):y(e,o,h(l))&&(++e[_].val,C(e).forEach(E.bind(t,n,o,e[o],r)),1),deleteProperty:(e,t)=>(c(e,t)&&R(e,t),++e[_].val),ownKeys:e=>(e[_].val,s(e))},x=e=>!v(e)||e[w]?e:new Proxy(F(e),O),D=e=>(e[p]=1,e),j=e=>e[w],K=a(m()),N=e=>new Proxy(e,{get:(e,t,r)=>a(e[t]??0)===K?{val:k(e[t].rawVal)}:i(e,t,r)}),k=e=>e?.[w]?new Proxy(N(e[w]),O):e,C=e=>e[S]=e[S].filter(e=>e.t.isConnected),E=(e,t,r,o,{t:l,f:f})=>{let a=Array.isArray(e),i=a?Number(t):t;u(l,()=>l[g][t]=f(r,()=>delete e[t],i)),a&&!o&&i!==e.length-1&&l.insertBefore(l.lastChild,l[g][n(e).find(e=>Number(e)>i)])},R=(e,t)=>{for(let r of C(e)){let e=r.t[g];e[t]?.remove(),delete e[t]}},T=r=>(e??(setTimeout(()=>(e.forEach(C),e=t),b),e=new Set)).add(r),q=(e,t,r)=>{let o={t:e instanceof Function?e():e,f:r},n=t[w];o.t[g]={},n[S].push(o),T(n);for(let[e,r]of l(n))E(t,e,r,1,o);return o.t},z=(e,t)=>{for(let[r,o]of l(t)){let t=e[r];v(t)&&v(o)?z(t,o):e[r]=o}for(let r in e)f(t,r)||delete e[r];let r=n(t),o=Array.isArray(e);if(o||n(e).some((e,t)=>e!==r[t])){let l=e[w];if(o)e.length=t.length;else{++l[_].val;let e={...l};for(let e of r)delete l[e];for(let t of r)l[t]=e[t]}for(let{t:e}of C(l)){let{firstChild:t,[g]:o}=e;for(let l of r)t===o[l]?t=t.nextSibling:e.insertBefore(o[l],t)}}return e},B=(e,n)=>{r=1;try{return z(e,n instanceof Function?Array.isArray(e)?n(e.filter(e=>1)):o(n(l(e))):n)}finally{r=t}},G=e=>Array.isArray(e)?e.filter(e=>1).map(G):v(e)?o(l(e).map(([e,t])=>[e,G(t)])):e;window.vanX={calc:P,reactive:x,noreactive:D,stateFields:j,raw:k,list:q,replace:B,compact:G}} + +//Store +vanX.Store =(obj, key)=> { + const recall = localStorage.getItem(key); + const store = vanX.reactive(recall ? JSON.parse(recall) : obj); + van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store)))); + return store; +} + +//gale +const KeyQuery="@",KeyPseudo=":",KeyChild=".",KeyGroup="^",Tier=(e,t)=>`${e}{${Object.keys(t).map((e=>{const n=t[e];switch(e[0]){case"@":return Tier(`@media(max-width:${e.substring(1)})`,n);case":":return Tier(`&${e}`,n);case".":return Tier(`${e}`,n);case"^":return Tier(`&:hover .${e.substring(1)}`,n)}return`${e.replace(/([a-z])([A-Z])/g,"$1-$2")}: ${n};`})).join("\n")}}`;let i=0;globalThis.Gale=e=>{const t=i?"_"+i:"";i++;const n=Object.keys(e).map((t=>Tier("."+t,e[t]))).join("\n");globalThis.document?.head.insertAdjacentHTML("beforeend",``);const r=(...e)=>{const n=(e,t)=>{const n=t.lastIndexOf(e)+e.length;return n?t.substring(n):t};return e.map((e=>n("^",n(".",e)))).join(t+" ")+t};return r.CSS=n,r.DOM=new Proxy({},{get(e,t){const n=t,r=[],s=new Proxy(((...e)=>{const t=van.tags[n](...e);return t.className=r.join(" "),t}),{get:(e,t)=>(r.push(t.substring(t.lastIndexOf(".")+1)),s)});return s}}),r}; +//boot +((t="/")=>{fetch(t+"deno.json").then((t=>t.json())).then((e=>{const n=(t,e)=>{let n=document.createElement("script");n.type=t,n.textContent=e,document.head.appendChild(n)},o=e.imports;for(let e in o){const n=o[e];n.startsWith("./")&&(o[e]=t+n.substring(2))}n("importmap",JSON.stringify({imports:o})),n("module",'import "entry"; ')}))})(); \ No newline at end of file diff --git a/deno.json b/deno.json index bbb3e72..7f2e8bb 100644 --- a/deno.json +++ b/deno.json @@ -5,7 +5,7 @@ "deno.window", "DOM" ], - "types": ["./types.d.ts"] + "types": ["./bundle.d.ts"] }, "imports": { "entry":"./app.js" diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..9ba1e26 --- /dev/null +++ b/deno.lock @@ -0,0 +1,95 @@ +{ + "version": "4", + "specifiers": { + "jsr:@std/media-types@*": "1.0.3" + }, + "jsr": { + "@std/media-types@1.0.3": { + "integrity": "b12d30a7852f7578f4d210622df713bbfd1cbdd9b4ec2eaf5c1845ab70bab159" + } + }, + "redirects": { + "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts" + }, + "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" + } +} diff --git a/dev_server.ts b/dev_server.ts new file mode 100644 index 0000000..fcafaf9 --- /dev/null +++ b/dev_server.ts @@ -0,0 +1,94 @@ +import { contentType } from "jsr:@std/media-types"; + +// Parse the port from the command-line arguments, defaulting to 8000 +const port = parseInt(Deno.args[0] || "8000", 10); +const sockets: WebSocket[] = []; +const connect = ``; + +const bundle = await fetch(import.meta.resolve("./bundle.js")).then(r=>r.text()); + +let html: string; +try { + html = Deno.readTextFileSync("./index.html").replace("", ""+connect); +} catch (_) { + html = ` + + + + ${connect} + + + + + + +`; +} + + +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 url = new URL(req.url); + + // Handle WebSocket connections + if (url.pathname === "/ws") { + const { socket, response } = Deno.upgradeWebSocket(req); + sockets.push(socket); + return response; + } + + // Serve static files or the predefined HTML for non-file routes + const path = new URL(req.url).pathname; + 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 file = await Deno.open("." + path, { read: true }); + return new Response(file.readable, { + 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") { + console.log("reload", event.paths); + for (const ws of sockets) { + if (ws.readyState === WebSocket.OPEN) { + ws.send("reload"); + } + } + } +} diff --git a/refresh_types.ts b/refresh_types.ts new file mode 100644 index 0000000..e2cc32d --- /dev/null +++ b/refresh_types.ts @@ -0,0 +1,33 @@ +import { resolve, toFileUrl } from "https://deno.land/std/path/mod.ts"; + +async function main() +{ + // Look for the deno.json file in the current directory + const denoJsonPath = resolve("./deno.json"); + + // 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; + if(!typeFile.startsWith("http")) + { + lookup = toFileUrl(resolve(Deno.cwd(), typeFile)).href; + } + console.log(`Caching ${lookup}`); + await import(lookup); // This will cache the file + } + } else { + console.log("No types found in compilerOptions."); + } +} + +main().catch((error) => { + console.error("Error:", error); + Deno.exit(1); +}); \ No newline at end of file -- 2.34.1 From 7cf382777e45e0914fd8f1344bf41e042f52bf99 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sat, 22 Feb 2025 16:58:53 -0500 Subject: [PATCH 14/15] scaffold script started --- dev_server.ts | 2 +- scaffold.ts | 31 ++++++++++++++++++++ scaffold/app.js | 47 ++++++++++++++++++++++++++++++ _index.html => scaffold/index.html | 0 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 scaffold.ts create mode 100644 scaffold/app.js rename _index.html => scaffold/index.html (100%) diff --git a/dev_server.ts b/dev_server.ts index fcafaf9..4250307 100644 --- a/dev_server.ts +++ b/dev_server.ts @@ -84,10 +84,10 @@ Deno.serve({ port }, async (req: Request) => { const watcher = Deno.watchFs("."); for await (const event of watcher) { if (event.kind === "modify") { - console.log("reload", event.paths); for (const ws of sockets) { if (ws.readyState === WebSocket.OPEN) { ws.send("reload"); + continue; } } } diff --git a/scaffold.ts b/scaffold.ts new file mode 100644 index 0000000..a001909 --- /dev/null +++ b/scaffold.ts @@ -0,0 +1,31 @@ +import { resolve, basename } from "https://deno.land/std/path/mod.ts"; + +const hostDir = "./scaffold/"; + +const filePaths = [ + "index.html", + "app.js", +]; + + +for (const filePath of filePaths) +{ + // Resolve the file path relative to the script's directory + const fileUrl = import.meta.resolve(hostDir + filePath); + + // Determine the destination path in the current working directory + const destinationPath = resolve(Deno.cwd(), basename(filePath)); + + console.log(`Downloading ${fileUrl} to ${destinationPath}`); + try { + const response = await fetch(fileUrl); + if (!response.ok) { + throw new Error(`Failed to fetch ${fileUrl}: ${response.statusText}`); + } + const fileData = await response.arrayBuffer(); + await Deno.writeFile(destinationPath, new Uint8Array(fileData)); + console.log(`Successfully downloaded ${filePath}`); + } catch (error) { + console.error(`Error downloading ${filePath}:`, error); + } +} \ No newline at end of file diff --git a/scaffold/app.js b/scaffold/app.js new file mode 100644 index 0000000..d815983 --- /dev/null +++ b/scaffold/app.js @@ -0,0 +1,47 @@ +const {DOM} = 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 DOM.div.Window( + DOM.div.Ability(), + DOM.div.Ability(), + DOM.div.Ability(), + DOM.div.Ability.Orange(), + ) +} + +van.add(document.body, UI()); \ No newline at end of file diff --git a/_index.html b/scaffold/index.html similarity index 100% rename from _index.html rename to scaffold/index.html -- 2.34.1 From 4fc45fa422f6b2f88c187de5d0f8d47617b1345c Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sat, 22 Feb 2025 17:27:28 -0500 Subject: [PATCH 15/15] scaffold script works --- app.js | 54 ------------------------ deno.lock | 95 ------------------------------------------ scaffold.ts | 46 ++++++++------------ scaffold/deno.json | 14 +++++++ scaffold/index.html | 27 ++---------- src/boot.js | 15 +++++++ gale.js => src/gale.js | 0 7 files changed, 50 insertions(+), 201 deletions(-) delete mode 100644 app.js delete mode 100644 deno.lock create mode 100644 scaffold/deno.json create mode 100644 src/boot.js rename gale.js => src/gale.js (100%) diff --git a/app.js b/app.js deleted file mode 100644 index b6a7c6b..0000000 --- a/app.js +++ /dev/null @@ -1,54 +0,0 @@ -const {DOM} = Gale({ - Button: { - padding: "20px", - background: "blue", - ".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)" - } - } -}); - - -/** @typedef {{done:boolean, text:string}} Todo */ -const items = vanX.Store({ - pending:"", - todos:/** @type {Todo[]}*/([]) -}, "Todos"); - -const {div, input, button, del, span, a} = van.tags; - -const TodoList = () => { - const inputDom = input({type: "text", value:()=>items.pending, oninput(){items.pending = this.value}}); - return div( - ()=>div(items.pending), - inputDom, DOM.button.Outline.Button({onclick: () => items.todos.push({text: inputDom.value, done: false})}, "Add"), - vanX.list(div, items.todos, ({val: v}, deleter) => div( - input({type: "checkbox", checked: () => v.done, onclick: e => v.done = e.target.checked}), - () => (v.done ? del : span)(v.text), - a({onclick: deleter}, "❌"), - )), - ) -} - -van.add(document.body, TodoList()); \ No newline at end of file diff --git a/deno.lock b/deno.lock deleted file mode 100644 index 9ba1e26..0000000 --- a/deno.lock +++ /dev/null @@ -1,95 +0,0 @@ -{ - "version": "4", - "specifiers": { - "jsr:@std/media-types@*": "1.0.3" - }, - "jsr": { - "@std/media-types@1.0.3": { - "integrity": "b12d30a7852f7578f4d210622df713bbfd1cbdd9b4ec2eaf5c1845ab70bab159" - } - }, - "redirects": { - "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts" - }, - "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" - } -} diff --git a/scaffold.ts b/scaffold.ts index a001909..814cea8 100644 --- a/scaffold.ts +++ b/scaffold.ts @@ -1,31 +1,19 @@ -import { resolve, basename } from "https://deno.land/std/path/mod.ts"; - -const hostDir = "./scaffold/"; - -const filePaths = [ - "index.html", - "app.js", -]; - - -for (const filePath of filePaths) +const hostedRoot = import.meta.resolve("../").slice(0, -1); +async function Download(file:string, processor = (text:string)=>text) { - // Resolve the file path relative to the script's directory - const fileUrl = import.meta.resolve(hostDir + filePath); - - // Determine the destination path in the current working directory - const destinationPath = resolve(Deno.cwd(), basename(filePath)); - - console.log(`Downloading ${fileUrl} to ${destinationPath}`); - try { - const response = await fetch(fileUrl); - if (!response.ok) { - throw new Error(`Failed to fetch ${fileUrl}: ${response.statusText}`); - } - const fileData = await response.arrayBuffer(); - await Deno.writeFile(destinationPath, new Uint8Array(fileData)); - console.log(`Successfully downloaded ${filePath}`); - } catch (error) { - console.error(`Error downloading ${filePath}:`, error); + const pathHosted = hostedRoot + "/scaffold/" + file; + try + { + const fileContents = await fetch(pathHosted).then(resp=>resp.text()); + await Deno.writeTextFile(file, processor(fileContents)); + console.log(`Successfully downloaded ${file}`); } -} \ No newline at end of file + catch (error) + { + console.error(`Error downloading ${file}:`, error); + } +} + +Download("deno.json", t=>t.replaceAll(`{HOSTED}`, hostedRoot)); +Download("index.html", t=>t.replaceAll(`{HOSTED}`, hostedRoot)); +Download("app.js"); \ No newline at end of file diff --git a/scaffold/deno.json b/scaffold/deno.json new file mode 100644 index 0000000..5d04f0b --- /dev/null +++ b/scaffold/deno.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "checkJs": true, + "lib": [ "deno.window", "DOM"], + "types": ["{HOSTED}/bundle.d.ts"] + }, + "tasks": { + "dev": "deno run -Ar {HOSTED}/dev_server.ts", + "types": "deno run -Ar {HOSTED}/refresh_types.ts" + }, + "imports": { + "entry":"./app.js" + } +} \ No newline at end of file diff --git a/scaffold/index.html b/scaffold/index.html index 5e6e962..4ac28b7 100644 --- a/scaffold/index.html +++ b/scaffold/index.html @@ -2,29 +2,10 @@ - Document + + + - - - - - - + \ No newline at end of file diff --git a/src/boot.js b/src/boot.js new file mode 100644 index 0000000..34d0157 --- /dev/null +++ b/src/boot.js @@ -0,0 +1,15 @@ +( + (root="/")=>fetch(root+"deno.json") + .then(text=>text.json()) + .then(json=>{ + const n=(t,e)=>{let n=document.createElement("script");n.type=t,n.textContent=e,document.head.appendChild(n)}; + const imports = json.imports; + for(let n in imports) + { + const path=imports[n]; + path.startsWith("./")&&(imports[n]=root+path.substring(2)) + } + n("importmap",JSON.stringify({imports})), + n("module",'import "entry"; ') + }) +)(); \ No newline at end of file diff --git a/gale.js b/src/gale.js similarity index 100% rename from gale.js rename to src/gale.js -- 2.34.1