Skip to content

Commit 390daa9

Browse files
author
blik
committed
jss fragments
json import browser support version change prevent buffer-arraybuffer-buffer conversion in response prevent Object enumeration before numeric term condition in combine three.js source definition
1 parent ed783c3 commit 390daa9

10 files changed

+159
-111
lines changed

Blik_2023_fragment.js

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
let classlist=name==="class"&&array(value);
5252
if(classlist)
5353
return [fragment,...nodes,[name,value.join(" ")]];
54+
let style=name==="style"&&simple(value)&&!defined(value["#text"]);
55+
if(style)
56+
value={"#text":css(value)};
5457
let defaults=
5558
{a:{target:"_blank"}
5659
,svg:{viewBox:"0 0 1 1",xmlns:namespaces.svg,"xmlns:xlink":namespaces.xlink}
@@ -344,7 +347,7 @@
344347
!["id","class","style"].includes(name.toLowerCase())&&!name.startsWith("on")).map(({name,value})=>
345348
"["+[name,value].join("='")+"']").join("");
346349
return name+Object.entries(selectors).flatMap(([attribute,selector])=>
347-
[attribute==="classList"?Array.from(node[attribute]):["class","className"].includes(attribute)?node[attribute]?.split(' '):node[attribute]].flat().filter(value=>
350+
[attribute==="classList"?Array.from(node[attribute]):["class","className"].includes(attribute)?node[attribute]?.split?.(' ')||[]:node[attribute]].flat().filter(value=>
348351
string(value)&&value?.length).map(value=>selector+value)).join('')+attributes;
349352
};
350353

@@ -678,11 +681,12 @@
678681
{return document(
679682
{style:index?undefined:
680683
{"#text":await css({".article":
681-
{color:"#b71c1c",display:"block","white-space":"pre-wrap",cursor:"pointer",padding:"0.5em",position:"relative","z-index":2
684+
{color:"#b71c1c",display:"block","white-space":"pre-wrap"
685+
,cursor:"pointer",padding:"0.5em",position:"relative","z-index":2
682686
,"&>canvas":{"border-radius":"50%",height:"1em",width:"1em","vertical-align":"bottom"}
683687
,"&>span":{color:"var(--text)",display:"block"}
684688
,"&:hover>span":layout.text.glow
685-
,"&+span":{"text-align":"left","& img":{"max-width":"100%",height:"auto"},"& audio":layout.audio}
689+
,"&+span":{"text-align":"left","&>img":{"max-width":"100%",height:"auto"},"&>audio":layout.audio}
686690
}})
687691
}
688692
,span:
@@ -989,8 +993,10 @@
989993

990994
export function defer(event)
991995
{// asynchronizing event dispatch unblocks its synchronous default unless prevented.
992-
this.then(actions=>delegate.call(actions,event));
993996
event.preventDefault();
997+
event=Object.fromEntries("type/target/keyCode/isTrusted/bubbles/srcElement".split("/").map(field=>
998+
[field,event[field]]));
999+
this.then(actions=>delegate.call(actions,event));
9941000
console.warn({["captured "+event.type+" event from"]:event.target});
9951001
};
9961002

@@ -1260,22 +1266,25 @@
12601266
return false;
12611267
if(!past?.nodeName)
12621268
return [merge(last,{text:""}),simple(past)?document({span:{"#text":past.text}}):past||[],syntax];
1263-
let style=buffer(compose(style=>"{"+style+"}",JSON.parse),drop(1))(last.style);
1264-
if(!style)
1269+
let fragment=buffer(compose(style=>"{"+style+"}",JSON.parse),drop(1))(last.style);
1270+
if(!fragment)
12651271
return [{text:""},past,syntax];
1266-
let fragment=defined(style.style)
1267-
?compose.call(style,({style,...fragment})=>fragment)
1268-
:undefined;
1269-
style=compose(style=>simple(style)
1270-
?{"#text":css(
1271-
{[qualify(fragment)]:merge(style,last.block?{position:"relative"}:{},0)
1272-
})}
1273-
:(last.block?"position:relative;":"")+style)(style.style??style);
1274-
let jss=simple(style);
1272+
let selector=simple(fragment)&&qualify(fragment);
1273+
// jss text is deprecated in favor of fragment jss
1274+
let style=selector?fragment.style:simple(fragment)
1275+
?Object.entries(fragment).map(entry=>entry.join(":")).join(";")
1276+
:fragment;
1277+
let jss=selector&&simple(style);
1278+
fragment=
1279+
{...selector&&fragment,style:jss
1280+
?{[selector]:merge(style,last.block?{position:"relative"}:{},0)
1281+
}
1282+
:style&&((last.block?"position:relative;":"")+style)
1283+
};
12751284
if(last.block)
1276-
return [document({div:{class:"inline",style,...fragment}}),past,syntax];
1277-
document.call(past,!jss?{style,...fragment}:fragment);
1278-
let next=jss?document({style}):[];
1285+
return [document({div:{class:"inline",...fragment}}),past,syntax];
1286+
document.call(past,fragment);
1287+
let next=jss?document({style:fragment.style}):[];
12791288
return [{text:""},next,past,syntax];
12801289
},"[":function compound(last,...syntax)
12811290
{if(!string(last.tag)||last.compound)

Blik_2023_host.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {note,colors,when,functor,string,pattern,revert,each,describe,clock,observe,is,has,same,slip,something,compound,infer,tether,whether,collect,provide,route,buffer,differ,compose,combine,either,drop,crop,swap,record,wait,exit,pass,remember,binary,simple,array} from "./Blik_2023_inference.js";
22
import {thread,resolve,access,locate,prompt,list,window,jsdom,fetch,persist,version,compress,stage,cookies,cookie,feature} from "./Blik_2023_interface.js";
33
import {search,merge,sum,prune,extract,encrypt} from "./Blik_2023_search.js";
4-
import {scope,mime} from "./Blik_2023_meta.js";
4+
import {scope,mime,bytes} from "./Blik_2023_meta.js";
55
import {document} from "./Blik_2023_fragment.js";
66
import {animal} from "./Blik_2024_svg.js";
77
var {memory}=Object.assign(globalThis,{memory:{}});
@@ -85,10 +85,8 @@
8585
let type=this.headers.get("Content-Type");
8686
let gzip=this.headers.get("Content-Encoding")==="gzip";
8787
let stream=functor(this.body);
88-
body=stream?this.body:await buffer(type===mime("json")&&!gzip?"text":compose("arrayBuffer",buffer=>
89-
new Uint8Array(buffer).reduce((buffer,bytes,index)=>
90-
Object.assign(buffer,{[index]:bytes})
91-
,Buffer.alloc(buffer.byteLength))))(this);
88+
body=stream?this.body:await buffer(type===mime("json")&&!gzip?"text"
89+
:is(Buffer)(this.body)?"body":compose("arrayBuffer",bytes))(this);
9290
if(is(Error)(body))
9391
body=note.call(1,body).message,status=500,type=mime("txt");
9492
let header=compose.call

Blik_2023_inference.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
export function binary(term){return typeof term==="boolean";};
1717
export function string(term){return typeof term==="string";};
1818
export function numeric(term){return typeof term==="number"};
19+
export function finite(term){return numeric(term)&&term<Infinity};
1920
export function simple(term){return term?.constructor?.name==="Object";};
2021
export function compound(term){return Boolean(typeof term==="object"&&term);};
2122
export function basic(term){return compound(term)&&(simple(term)||array(term));};
@@ -316,16 +317,15 @@
316317
return confer(combine,...arguments);
317318
let context=collect(this);
318319
let [factor]=context;
319-
let records=Object.entries(Object(factor));
320320
let content=terms.map(term=>!numeric(term)
321321
?compose.call(context,provide,term)
322322
:Object.assign([]
323323
,Array(Math.floor(term)).fill(factor)
324324
,term%1&&
325-
{[Math.floor(term)]:records.length
326-
?compose.call(records.slice(0,term%1*records.length)
327-
,Object.fromEntries,...array(factor)?[Object.values]:[])
328-
:term%1*factor
325+
{[Math.floor(term)]:infer.call(Object[array(factor)?"values":"entries"](Object(factor))
326+
,records=>records.length
327+
?Object[array(factor)?"values":"fromEntries"](records.slice(0,term%1*records.length))
328+
:term%1*factor)
329329
}));
330330
return provide(collect(...content));
331331
// length?compose(drop(),functor,Math.ceil,Array,fields,"fill","flat",[]

Blik_2023_interface.js

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {note,collect,same,has,promise,pass,slip,something,observe,functor,describe,remember,expect,control,trace,array,compound,simple,apply,stream,record,revert,provide,tether,differ,whether,either,when,each,drop,swap,crop,infer,buffer,is,not,plural,numeric,binary,basic,match,wait,string,defined,compose,combine,exit,clock,route,major} from "./Blik_2023_inference.js";
22
import {sum,merge,stringify,search,edit,prune,parse as records,relevant} from "./Blik_2023_search.js";
3-
import {parse,sanitize,serialize,exports,reexport,test,mime,coordinates} from "./Blik_2023_meta.js";
3+
import {parser,parse,sanitize,serialize,exports,reexport,test,mime,coordinates} from "./Blik_2023_meta.js";
44

55
export const address=new URL(import.meta.url).pathname;
66
export const location=address.replace(/\/[^/]*$/,"");//path.dirname(address);
@@ -16,17 +16,22 @@
1616
export function version(navigator)
1717
{let agent=["user-agent","userAgent"].reduce((agent,field)=>
1818
agent||navigator?.[field],undefined);
19+
let device=/\((.*?)\)/.exec(agent)?.[1];
1920
let entries=agent?.match(/[\w\.]+\/(\.{0,1}\d+){1,2}/g)?.map(agent=>agent.split("/"))||
2021
[[agent]];
21-
return entries.map(([name,version])=>({[name]:Number(version)})).reduce(merge);
22+
return entries.map(([name,version])=>({[name]:Number(version)})).reduce(merge
23+
,device?.split(";").reduce(function(platform)
24+
{return {[platform]:arguments[3].splice(1).join(";")};
25+
})||{});
2226
};
2327

2428
export var feature=agent=>agent&&prune.call
2529
({attributes:{node:21,Chrome:123}
2630
,assertions:{node:16.14,Chrome:91,Firefox:Infinity}
2731
,json:{Chrome:125,Firefox:Infinity}
2832
},([feature,condition])=>
29-
[true,Object.keys(condition).find(name=>agent[name])].filter(Boolean).reduce((value,name)=>
33+
[true,Object.keys(condition).find(name=>agent[name])
34+
].filter(Boolean).reduce((value,name)=>
3035
condition[name]<=agent[name])
3136
);
3237

@@ -171,7 +176,7 @@
171176
let json=source.endsWith(".json")||undefined;
172177
let recover=compose(recovery,infer("call",scope,absolute,target),infer(resolve,context,next));
173178
let module=command
174-
?import(source,json&&{[feature(agent).attributes?"with":"assert"]:{type:"json"}})
179+
?import(source,json&&{[!agent.Linux&&feature(agent).attributes?"with":"assert"]:{type:"json"}})
175180
:either(precedent,compose
176181
(either(buffer(next,buffer(recover)),compose(swap(source),request))
177182
,shortcircuit,{imports:new Set()},merge,[absolute],record,slip(scope),merge
@@ -335,7 +340,7 @@
335340
,transform:(source,address)=>compose.call
336341
("url","pathToFileURL",address,resolve,"href"
337342
,{format:formats[route(address)[1]]}
338-
,load,code=>({code,map:{mappings:''}})
343+
,load,(code,map={mappings:''})=>({code,map})
339344
),resolveId:(source,client)=>client
340345
?/^\./.test(source)
341346
?route(client).reduce((source,entry,index,route)=>
@@ -387,6 +392,8 @@
387392
Object.assign(context,{format:format="builtin"});
388393
if(!format&&/\.ts$/.test(source))
389394
Object.assign(context,{format:format="typescript"});
395+
if(format==="module"&&/\.glsl\.js$/.test(source))
396+
Object.assign(context,{format:syntax=format="shader"});
390397
if(format==="commonjs")
391398
// don't trust default assumption from nearest package.json as it often refers to inaccessible build outputs.
392399
await require(target).catch(fail=>
@@ -399,7 +406,7 @@
399406
[entry,relative.splice(2).join("/")]);
400407
let {comment,...definition}=
401408
[{syntax}
402-
,typeof format==="object"?format||{}:await import(sources).then(sources=>
409+
,compound(format)?format||{}:await import(sources).then(sources=>
403410
[Object.values(sources.default[format]||{})[index]||sources.default[format]||{}].reduce(function flat(entries,source)
404411
{return [entries,!compound(source)||array(source)?source:Object.values(source).reduce(flat,[])].flat();
405412
},[]).filter(compound).map(entry=>
@@ -409,17 +416,21 @@
409416
syntax=definition.syntax;
410417
let foreign=!["javascript"].includes(syntax)||Object.keys(definition).length>1;
411418
// parse foreign to serialize standard syntax. without native interpretter to call (next), all syntax are foreign.
412-
// using acorn's Parser methods (parse) until interpretation reducer is complete.
419+
// using acorn's Parser methods (parse) until semiotic reducer is complete.
413420
let edits=relevant(definition.edit||{},sparse);
414421
if(syntax==="json")
415422
syntax="module",edits["^((?:.*[\n$])*)"]="export default $1";
416-
let patriate=foreign?[infer(parse,syntax,{source}),definition,sanitize,serialize,"javascript",{source},parse,serialize]:[];
423+
let patriate=foreign?parser[format]||compose
424+
(infer(parse,syntax,{source}),definition,sanitize,serialize
425+
,"javascript",{source},parse,serialize):infer();
417426
let module=await buffer
418-
(compose(access,edits,edit,...patriate)
427+
(compose(access,edits,edit,patriate)
419428
,fail=>note.call(1,"Failed to patriate "+syntax+" \""+source+"\" due to",fail)&&wait(1000)(fail).then(exit)
420429
)(source,true);
421430
if(next)
422-
return compose.call({source:module,format:{json:"json"}[syntax]||"module"},shortcircuit);
431+
return compose.call(module,source=>(
432+
{source,format:{json:"json"}[syntax]||"module"
433+
}),shortcircuit);
423434
return module;
424435
};
425436

@@ -778,7 +789,8 @@
778789
async function freefetch(request,{method,body,headers}={})
779790
{let remote=/^http/.test(request);
780791
let url=string(request)?!remote
781-
?[this.location.origin,request?.replace(/^[\.\/]+/,"")||""].join("/")
792+
?!this?exit(freefetch.name+" not bound to JSDOM for local origin request. No server context for "+request+"?")
793+
:[this.location.origin,request?.replace(/^[\.\/]+/,"")||""].join("/")
782794
:request:request.url;
783795
let {protocol,host,hostname,path,port}=await resolve("url","parse",url);
784796
return revert((respond,reject,request,body)=>compose
@@ -789,7 +801,7 @@
789801
,{data:record(body=>body).bind(body)
790802
,error:compose(note,reject)
791803
,end:compose
792-
(swap(body),body=>Buffer.concat(body,sum(body.map(({length})=>length))),buffer(status===302
804+
(swap(body),body=>Buffer.concat(body,sum(body.map(({length})=>length))),buffer([302,308].includes(status)
793805
?compose(swap({...request,url:headers.location}),fetch)
794806
:compose(body=>({body,status,headers,type:headers["content-type"]}),request,stage)
795807
,reject),respond
@@ -824,15 +836,16 @@
824836
note.call(3,"navigated browser to "+url);
825837
expose(window=browser.window);
826838
})(url);
827-
}
839+
};
828840

829841
export async function stage(response,request)
830842
{let agent=version(request.headers);
831-
let browser="Mozilla/Chrome/Safari/AppleWebKit".split("/").some(has.bind(agent||{}));
832843
let features=feature(agent);
833-
let importing=request.headers?.referer&&!request.headers.referer.endsWith(request.url)&&request?.headers?.["sec-fetch-dest"]==="script";
844+
let browser="Mozilla/Chrome/Safari/AppleWebKit".split("/").some(has.bind(agent||{}));
845+
let direct=request.headers?.referer?.endsWith(request.url)===false;
846+
let importing=!direct&&request?.headers?.["sec-fetch-dest"]==="script";
834847
let fail=is(Error)(response);
835-
let type=!fail&&response?.type||mime(response?.nodeName?.toLowerCase()||(either(simple,array)(response)?"json":request.url))||mime(response.nodeName?"html":"txt");
848+
let type=!fail&&response?.type||response.headers?.get("Content-Type")||mime(response?.nodeName?.toLowerCase()||(either(simple,array)(response)?"json":path(request)))||mime(response.nodeName?"html":"txt");
836849
let [js,json]=[type===mime("js"),type===mime("json")];
837850
let status=response?fail?500:response.status||200:404;
838851
let success=status<400;
@@ -874,10 +887,10 @@
874887
{let gzip=this.headers["Content-Encoding"]==="gzip";
875888
// if(simple(this.body))
876889
// return compose(JSON.stringify(this.body),"encode","buffer")(new TextEncoder());
877-
if(this.body.constructor?.name=="Buffer")
890+
if(this.body.constructor?.name==="Buffer")
878891
return compose
879-
(infer("reduce",(array,byte,index)=>Object.assign(array,{[index]:byte})
880-
,new Uint8Array(new ArrayBuffer(this.body.length)))
892+
(new Uint8Array(new ArrayBuffer(this.body.length))
893+
,(buffer,array)=>{for(let i=0;i<array.length;i++){array[i]=buffer[i]};return array}
881894
,"buffer"
882895
)(this.body);
883896
return Buffer.from(this.body,"utf-8");

Blik_2023_layout.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,31 +62,6 @@
6262
{glow:{"text-shadow":"white 0px 0px 2px,white 0px 0px 2px",transition:"all 0.3s"}
6363
};
6464

65-
export var table=
66-
{"font-size":"inherit",transition:"all 1s"
67-
,"&#dashboard tr":{"vertical-align":"top"}
68-
,"& tr input[type=checkbox]":
69-
{appearance:"none","font-family":"inherit",cursor:"pointer",width:"auto","line-height":"1.3em","font-size":"1.5em",margin:0
70-
,"&:not(:disabled):hover":{"text-shadow":"rgb(255,255,255) 0px 0px 10px,rgb(255,255,255) 0px 0px 10px,rgb(255,255,255) 0px 0px 10px"}
71-
,"&:after":{content:"'✘'",color:"var(--isle)","margin-left":"3px","margin-right":"3px"}
72-
//,"&:last-of-type:after":{content:"'🔓'"}
73-
,"&:focus:after":{"text-shadow":"rgb(255,255,255) 0px 0px 10px, rgb(255,255,255) 0px 0px 10px, rgb(255,255,255) 0px 0px 10px"}
74-
,"&:checked:after":{content:"'✓'",color:"var(--highlight)","font-weight":800}
75-
}
76-
,"&.homogenous>tbody>tr":{"flex-direction":"row",width:"90vw","justify-content":"center"}
77-
,"&.heterogenous,&.homogenous":
78-
{position:"relative","font-family":"averia","font-size":"10px",display:"block"
79-
,"&>tbody":
80-
{display:"block"
81-
,"&>tr":
82-
{position:"relative",display:"flex","flex-wrap":"wrap",width:"90vw","justify-content":"center",margin:"auto"
83-
,"&>td":{position:"relative","text-align":"center",display:"block","& div":{width:"150px",height:"150px","text-align":"center",margin:"auto",overflow:"hidden"}}
84-
,"& svg":{height:"30px"}
85-
}
86-
}
87-
}
88-
};
89-
9065
export var message=
9166
{display:"table-row","text-align":"left"
9267
,"&>span":

Blik_2023_meta.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,17 @@
415415
}
416416
};
417417

418+
export var parser=
419+
{async shader(code)
420+
{let {default:Magic}=await import("./Harris_2014_magic_string.js");
421+
let js=new Magic(code).replace(/\/\* glsl \*\/\`(.*?)\`/sg,function(match,p1)
422+
{return JSON.stringify(
423+
[/\r/g,/[ \t]*\/\/.*\n/g,/[ \t]*\/\*[\s\S]*?\*\//g].reduce((p1,expression)=>
424+
p1.replace(expression,""),p1.trim()).replace(/\n{2,}/g,"\n"));
425+
});
426+
return provide([js.toString(),js.generateMap()]);
427+
}};
428+
418429
export function serialize(syntax,format="astring",options)
419430
{// convert abstract syntax tree or runtime namespace to javascript;
420431
if(functor(syntax))
@@ -565,7 +576,7 @@
565576
,image:{jpeg:["jpg","jpeg"],"x-icon":"ico","svg+xml":"svg","":["gif","png"]}
566577
,audio:{mpeg:"mp3"}
567578
,font:{ttf:"ttf"}
568-
,application:{xml:["gexf"],"":["json","pdf","xml"]}
579+
,application:{xml:["gexf"],"geo+json":"geojson","":["json","pdf","xml"]}
569580
}
570581
,(extension,mime)=>
571582
Object.entries(mime).reduce((mime,[type,subtypes])=>mime||
@@ -575,13 +586,17 @@
575586
,undefined)?.join("/")
576587
);
577588

589+
export var demarkup=text=>Array.from(text).map(symbol=>
590+
({"<":"&lt;",">":"&gt;"}[symbol]||symbol)).join("");
578591
export var data=(mime,base64)=>"data:image/"+mime+";base64,"+base64;
579592
export var quote=text=>"\""+text.replace(/([^\\])\\([^\\])/g,"$1\\\\$2").replace(/\"/g,"\\\"").replace(/\n/g
580593
// css:after pseudoelement takes \A for linebreak.
581594
,"\\A ")+"\"";
582-
export var demarkup=text=>Array.from(text).map(symbol=>
583-
({"<":"&lt;",">":"&gt;"}[symbol]||symbol)).join("");
584-
595+
export function bytes(buffer)
596+
{let bytes=new Uint8Array(buffer),next=Buffer.alloc(buffer.byteLength);
597+
for(let i=0;i<buffer.byteLength;i++){next[i]=bytes[i];}
598+
return next;
599+
};
585600
export async function test(namespace,tests,path=[])
586601
{// compose tests defined in namespace.
587602
let assert=await import("assert");

0 commit comments

Comments
 (0)