improved typing
This commit is contained in:
parent
eb12efae50
commit
836c4bcea8
@ -104,6 +104,8 @@
|
||||
"https://deno.land/std@0.224.0/path/windows/relative.ts": "3e1abc7977ee6cc0db2730d1f9cb38be87b0ce4806759d271a70e4997fc638d7",
|
||||
"https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972",
|
||||
"https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e",
|
||||
"https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c"
|
||||
"https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c",
|
||||
"https://vanjs.org/code/van-1.5.5.nomodule.min.js": "32403d4dd6203a46513f000fd64b18e4eaef0823bf757ca0092e70130d059aa3",
|
||||
"https://vanjs.org/code/van-x-0.6.3.nomodule.min.js": "e4b7de89bf2f84c22669ce7bcef592fb398d9dcf8b8a36f4562b8ac6354b1f2f"
|
||||
}
|
||||
}
|
||||
|
3
dist/bundle_entry.js
vendored
Normal file
3
dist/bundle_entry.js
vendored
Normal file
File diff suppressed because one or more lines are too long
103
dist/core.d.ts
vendored
103
dist/core.d.ts
vendored
@ -1,103 +0,0 @@
|
||||
export {}
|
||||
declare global
|
||||
{
|
||||
namespace Van {
|
||||
|
||||
interface State<T> {
|
||||
val: T
|
||||
readonly oldVal: T
|
||||
readonly rawVal: T
|
||||
}
|
||||
|
||||
// Defining readonly view of State<T> for covariance.
|
||||
// Basically we want StateView<string> to implement StateView<string | number>
|
||||
type StateView<T> = Readonly<State<T>>
|
||||
|
||||
type Val<T> = State<T> | 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> | (() => PropValue)
|
||||
|
||||
type Props = Record<string, PropValueOrDerived> & { class?: PropValueOrDerived; is?: string }
|
||||
|
||||
type PropsWithKnownKeys<ElementType> = Partial<{[K in keyof ElementType]: PropValueOrDerived}>
|
||||
|
||||
type ValidChildDomValue = Primitive | Node | null | undefined
|
||||
|
||||
type BindingFunc = ((dom?: Node) => ValidChildDomValue) | ((dom?: Element) => Element)
|
||||
|
||||
type ChildDom = ValidChildDomValue | StateView<Primitive | null | undefined> | BindingFunc | readonly ChildDom[]
|
||||
|
||||
type TagFunc<Result> = (first?: Props & PropsWithKnownKeys<Result> | ChildDom, ...rest: readonly ChildDom[]) => Result
|
||||
|
||||
type Tags = Readonly<Record<string, TagFunc<Element>>> & {
|
||||
[K in keyof HTMLElementTagNameMap]: TagFunc<HTMLElementTagNameMap[K]>
|
||||
}
|
||||
}
|
||||
const van:{
|
||||
readonly state: <T>(initVal: T, HMRKey?:string)=> Van.State<T>
|
||||
readonly derive: <T>(f: () => T) => Van.State<T>
|
||||
readonly add: (dom: Element, ...children: readonly Van.ChildDom[]) => Element
|
||||
readonly tags: Van.Tags & ((namespaceURI: string) => Readonly<Record<string, Van.TagFunc<Element>>>)
|
||||
readonly hydrate: <T extends Node>(dom: T, f: (dom: T) => T | null | undefined) => T
|
||||
};
|
||||
|
||||
|
||||
namespace VanX
|
||||
{
|
||||
type StateOf<T> = { readonly [K in keyof T]: Van.State<T[K]> }
|
||||
type ValueType<T> = T extends (infer V)[] ? V : T[keyof T]
|
||||
type KeyType<T> = T extends unknown[] ? number : string
|
||||
type ReplacementFunc<T> =
|
||||
T extends (infer V)[] ? (items: V[]) => readonly V[] :
|
||||
(items: [string, T[keyof T]][]) => readonly [string, T[keyof T]][]
|
||||
}
|
||||
const vanX:{
|
||||
readonly calc: <R>(f: () => R) => R
|
||||
readonly reactive: <T extends object>(obj: T, HMRKey?:string) => T
|
||||
readonly noreactive: <T extends object>(obj: T) => T
|
||||
readonly stateFields: <T extends object>(obj: T) => VanX.StateOf<T>
|
||||
readonly raw: <T extends object>(obj: T) => T
|
||||
readonly list: <T extends object, ElementType extends Element>(
|
||||
container: (() => ElementType) | ElementType,
|
||||
items: T,itemFunc: (v: Van.State<VanX.ValueType<T>>, deleter: () => void, k: VanX.KeyType<T>) => Node
|
||||
) => ElementType
|
||||
readonly replace: <T extends object>(obj: T, replacement: VanX.ReplacementFunc<T> | T) => T
|
||||
readonly compact: <T extends object>(obj: T) => T
|
||||
// my addition
|
||||
readonly Store: <T extends object>(obj:T, key:string)=>T
|
||||
};
|
||||
|
||||
namespace Gale {
|
||||
type KeyQuery = "@";
|
||||
type KeyState = ":";
|
||||
type KeyChild = ".";
|
||||
type KeyGroup = "^";
|
||||
type UserStyles = Partial<CSSStyleDeclaration> & {[key: `${KeyQuery|KeyState|KeyChild|KeyGroup}${string}`]: UserStyles }
|
||||
type UserSheet = Record<string, UserStyles>
|
||||
type CollectKeys<Obj> = {[Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys<Obj[Key]> : Key }[keyof Obj]
|
||||
type FilterKeys<Keys> = Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never
|
||||
type CrossMultiply<A, B> = A extends string ? B extends string ? `${A}${B}` : never : never
|
||||
type CrossMultiplyRecord<Rec> = keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply<K, FilterKeys<CollectKeys<Rec[K]>>> : never }[keyof Rec]
|
||||
type Tier = (selector:string, obj:UserStyles, suffix:string)=>string;
|
||||
type CreateSheet = <T extends UserSheet>(sheet:UserSheet&T, hash?:string)=>{
|
||||
Tag:(...args:CrossMultiplyRecord<T>[])=>string,
|
||||
CSS:string,
|
||||
DOM:Elemental<CrossMultiplyRecord<T>>,
|
||||
Div:Circular<CrossMultiplyRecord<T>, Van.TagFunc<HTMLDivElement>>
|
||||
}
|
||||
|
||||
|
||||
type Elemental<T extends string> = {[K in keyof HTMLElementTagNameMap]: Van.TagFunc<HTMLElementTagNameMap[K]>&Circular<T, Van.TagFunc<HTMLElementTagNameMap[K]>>}
|
||||
|
||||
type Circular<Keys extends string, Func> = {
|
||||
[K in Keys]: Circular<Keys, Func>&Func
|
||||
};
|
||||
|
||||
}
|
||||
const Gale:Gale.CreateSheet
|
||||
}
|
3
dist/core.js
vendored
3
dist/core.js
vendored
File diff suppressed because one or more lines are too long
1
dist/hmr-NY37ZYM7.js
vendored
Normal file
1
dist/hmr-NY37ZYM7.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
var g=0,c={};function d(){for(let e in c)sessionStorage.setItem(e,c[e]);c={},g=0}function f(e,t){c[e]=t,g||(g=setTimeout(d,500)),console.log("SAVE",e,t)}function m(e){let t=sessionStorage.getItem(e);return console.log("LOAD",e,t),t}var S,u=0;function v(e){u=0,S=e}function h(){return S?S+"_"+u+++"_":""}var I=globalThis.van.state;globalThis.van.state=(e,t="")=>{let n=typeof e,o=l=>l,a=l=>l?.toString()||null;switch(n){case"boolean":o=l=>l==="true";break;case"number":o=parseFloat;break;case"object":o=JSON.parse,a=JSON.stringify;break}let r="HMR_"+h()+t,s=m(r),i=I(s?o(s):e);return van.derive(()=>f(r,a(i.val))),i};var w=globalThis.vanX.reactive;globalThis.vanX.reactive=(e,t)=>{v(t);let n=w(e);return v(),n};new WebSocket("ws://"+window.location.host+"/ws").addEventListener("message",e=>e.data==="reload"&&window.location.reload());vanX.Store=(e,t)=>{let n=JSON.stringify(e),o=localStorage.getItem(t+"check");localStorage.setItem(t+"check",n);let a;if(n==o){let s=localStorage.getItem(t);try{a=JSON.parse(s)||e}catch{a=e}}else a=e;let r=vanX.reactive(a);return van.derive(()=>localStorage.setItem(t,JSON.stringify(vanX.compact(r)))),r};
|
@ -1,6 +1,5 @@
|
||||
const bundle = await fetch(import.meta.resolve("../dist/core.js")).then(r=>r.text());
|
||||
const index = await fetch(import.meta.resolve("../dist/index.html")).then(r=>r.text());
|
||||
export const HTML = index.replace(`</head>`, `<script>${bundle}</script></head>`);
|
||||
export const HTML = index.replace(`</head>`, `<script type="module" src="/dist/bundle_entry.js?map&hmr"></script></head>`);
|
||||
export const Root = import.meta.resolve("../");
|
||||
export const Load =async(file:string)=> await fetch(Root + file).then(resp=>resp.text());
|
||||
export const Save =async(text:string, name:string)=> await Deno.writeTextFile(name, text);
|
@ -7,8 +7,27 @@ globalThis.vanX = VanX;
|
||||
import Gale from "../src/gale.js";
|
||||
globalThis.Gale = Gale;
|
||||
|
||||
import BindHMR from "../src/hmr.js";
|
||||
BindHMR();
|
||||
const args = new URL(import.meta.url).searchParams;
|
||||
|
||||
import Boot from "../src/boot.js";
|
||||
Boot();
|
||||
//Store
|
||||
vanX.Store=(e,t)=>{const a=localStorage.getItem(t),r=vanX.reactive(a?JSON.parse(a):e);return van.derive((()=>localStorage.setItem(t,JSON.stringify(vanX.compact(r))))),r};
|
||||
|
||||
if(args.has("hmr"))
|
||||
{
|
||||
await import("../src/hmr.js");
|
||||
}
|
||||
|
||||
const root = args.get("root")||"/";
|
||||
fetch(root+"deno.json")
|
||||
.then(text=>text.json())
|
||||
.then(json=>{
|
||||
const Script=(t,e)=>{let n=document.createElement("script"); n.type=t; n.textContent=e; document.head.appendChild(n); return n;};
|
||||
const imports = json.imports;
|
||||
for(let n in imports)
|
||||
{
|
||||
const path=imports[n];
|
||||
path.startsWith("./")&&(imports[n]=root+path.substring(2))
|
||||
}
|
||||
args.has("map") && Script("importmap",JSON.stringify({imports}));
|
||||
Script("module").src=imports.entry;
|
||||
});
|
@ -5,8 +5,14 @@ const command = new Deno.Command("deno", {
|
||||
"--platform=browser",
|
||||
"--inline-imports=true",
|
||||
"--output=dist/core.js",
|
||||
"--outdir=dist",
|
||||
"--minify",
|
||||
"--code-splitting",
|
||||
"scripts/bundle_entry.ts"
|
||||
]
|
||||
});
|
||||
command.outputSync();
|
||||
const result = command.outputSync();
|
||||
|
||||
const textDecoder = new TextDecoder();
|
||||
console.log("stdout:", textDecoder.decode(result.stdout));
|
||||
console.log("stderr:", textDecoder.decode(result.stderr));
|
13
src/boot.js
13
src/boot.js
@ -1,13 +0,0 @@
|
||||
export default (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"; ')
|
||||
})
|
129
src/hmr.js
129
src/hmr.js
@ -47,75 +47,74 @@ function NextID()
|
||||
return _ID ? _ID + "_" + (_index++) + "_" : "";
|
||||
}
|
||||
|
||||
export default()=>{
|
||||
//bind Van
|
||||
const origninalState = globalThis.van.state;
|
||||
globalThis.van.state =(value, key="")=>
|
||||
|
||||
//bind Van
|
||||
const origninalState = globalThis.van.state;
|
||||
globalThis.van.state =(value, key="")=>
|
||||
{
|
||||
const type = typeof value;
|
||||
let reader =d=>d;
|
||||
let writer =d=>d?.toString() || null;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
const type = typeof value;
|
||||
let reader =d=>d;
|
||||
let writer =d=>d?.toString() || null;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case "boolean" :
|
||||
reader =(data)=> data === "true"; break;
|
||||
case "number" :
|
||||
reader = parseFloat; break;
|
||||
case "object" :
|
||||
reader = JSON.parse;
|
||||
writer = JSON.stringify;
|
||||
break;
|
||||
}
|
||||
|
||||
const fullKey = "HMR_" + NextID() + key;
|
||||
const stringValue = Load(fullKey);
|
||||
const signal = origninalState((stringValue ? reader(stringValue) : value));
|
||||
van.derive(()=>Save(fullKey, writer(signal.val)));
|
||||
|
||||
return signal;
|
||||
};
|
||||
|
||||
//bind VanX
|
||||
const originalReactive = globalThis.vanX.reactive;
|
||||
globalThis.vanX.reactive =(obj, id)=>
|
||||
{
|
||||
StartID(id);
|
||||
const state = originalReactive(obj);
|
||||
StartID();
|
||||
return state;
|
||||
case "boolean" :
|
||||
reader =(data)=> data === "true"; break;
|
||||
case "number" :
|
||||
reader = parseFloat; break;
|
||||
case "object" :
|
||||
reader = JSON.parse;
|
||||
writer = JSON.stringify;
|
||||
break;
|
||||
}
|
||||
|
||||
// added in devmode to index.html
|
||||
new WebSocket('ws://'+window.location.host+'/ws').addEventListener('message',e=>e.data==='reload'&&window.location.reload());
|
||||
const fullKey = "HMR_" + NextID() + key;
|
||||
const stringValue = Load(fullKey);
|
||||
const signal = origninalState((stringValue ? reader(stringValue) : value));
|
||||
van.derive(()=>Save(fullKey, writer(signal.val)));
|
||||
|
||||
vanX.Store =(obj, key)=>
|
||||
return signal;
|
||||
};
|
||||
|
||||
//bind VanX
|
||||
const originalReactive = globalThis.vanX.reactive;
|
||||
globalThis.vanX.reactive =(obj, id)=>
|
||||
{
|
||||
StartID(id);
|
||||
const state = originalReactive(obj);
|
||||
StartID();
|
||||
return state;
|
||||
}
|
||||
|
||||
// added in devmode to index.html
|
||||
new WebSocket('ws://'+window.location.host+'/ws').addEventListener('message',e=>e.data==='reload'&&window.location.reload());
|
||||
|
||||
vanX.Store =(obj, key)=>
|
||||
{
|
||||
let checkInit = JSON.stringify(obj);
|
||||
let checkStore = localStorage.getItem(key+"check");
|
||||
localStorage.setItem(key+"check", checkInit);
|
||||
|
||||
let recallJSON;
|
||||
if(checkInit == checkStore)
|
||||
{
|
||||
let recallText = localStorage.getItem(key);
|
||||
try
|
||||
{
|
||||
recallJSON = JSON.parse(recallText) || obj;
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
recallJSON = obj;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let checkInit = JSON.stringify(obj);
|
||||
let checkStore = localStorage.getItem(key+"check");
|
||||
localStorage.setItem(key+"check", checkInit);
|
||||
|
||||
let recallJSON;
|
||||
if(checkInit == checkStore)
|
||||
{
|
||||
let recallText = localStorage.getItem(key);
|
||||
try
|
||||
{
|
||||
recallJSON = JSON.parse(recallText) || obj;
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
recallJSON = obj;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
recallJSON = obj;
|
||||
}
|
||||
recallJSON = obj;
|
||||
}
|
||||
|
||||
const store = vanX.reactive( recallJSON );
|
||||
van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store))));
|
||||
return store;
|
||||
}
|
||||
}
|
||||
const store = vanX.reactive( recallJSON );
|
||||
van.derive(() => localStorage.setItem(key, JSON.stringify(vanX.compact(store))));
|
||||
return store;
|
||||
}
|
||||
|
45
types.d.ts
vendored
Normal file
45
types.d.ts
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
import type * as VAN from "https://vanjs.org/code/van-1.5.5.d.ts";
|
||||
import type * as VANX from "https://vanjs.org/code/van-x-0.6.3.d.ts";
|
||||
type Replace<T extends object, K extends keyof T, R> = Omit<T, K> & { readonly [P in K]: R };
|
||||
declare module "vanjs-core" { export type State<T> = VAN.State<T> }
|
||||
declare global
|
||||
{
|
||||
namespace Van { export type * from "https://vanjs.org/code/van-1.5.5.d.ts"; }
|
||||
namespace VanX { export type * from "https://vanjs.org/code/van-x-0.6.3.d.ts"; }
|
||||
const van: Replace<VAN.Van, "state", <T>(arg:T, HMRKey?:string)=>VAN.State<T>>
|
||||
const vanX: Replace<typeof VANX, "reactive", <T extends object>(obj: T, HMRKey?:string) => T> & {Store:<T>(obj:T, key:string)=>T}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
namespace Gale {
|
||||
type KeyQuery = "@";
|
||||
type KeyState = ":";
|
||||
type KeyChild = ".";
|
||||
type KeyGroup = "^";
|
||||
type UserStyles = Partial<CSSStyleDeclaration> & {[key: `${KeyQuery|KeyState|KeyChild|KeyGroup}${string}`]: UserStyles }
|
||||
type UserSheet = Record<string, UserStyles>
|
||||
type CollectKeys<Obj> = {[Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys<Obj[Key]> : Key }[keyof Obj]
|
||||
type FilterKeys<Keys> = Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never
|
||||
type CrossMultiply<A, B> = A extends string ? B extends string ? `${A}${B}` : never : never
|
||||
type CrossMultiplyRecord<Rec> = keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply<K, FilterKeys<CollectKeys<Rec[K]>>> : never }[keyof Rec]
|
||||
type Tier = (selector:string, obj:UserStyles, suffix:string)=>string;
|
||||
type CreateSheet = <T extends UserSheet>(sheet:UserSheet&T, hash?:string)=>{
|
||||
Tag:(...args:CrossMultiplyRecord<T>[])=>string,
|
||||
CSS:string,
|
||||
DOM:Elemental<CrossMultiplyRecord<T>>,
|
||||
Div:Circular<CrossMultiplyRecord<T>, Van.TagFunc<HTMLDivElement>>
|
||||
}
|
||||
|
||||
|
||||
type Elemental<T extends string> = {[K in keyof HTMLElementTagNameMap]: Van.TagFunc<HTMLElementTagNameMap[K]>&Circular<T, Van.TagFunc<HTMLElementTagNameMap[K]>>}
|
||||
|
||||
type Circular<Keys extends string, Func> = {
|
||||
[K in Keys]: Circular<Keys, Func>&Func
|
||||
};
|
||||
}
|
||||
|
||||
const Gale:Gale.CreateSheet
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user