|
1 | | - import {merge,prune,unfold,record} from "./Blik_2023_search.js"; |
| 1 | + import {merge,prune,unfold,record,extract} from "./Blik_2023_search.js"; |
2 | 2 | import {aphorize,serialize} from "./Blik_2023_meta.js"; |
3 | 3 | import {infer,compose,buffer,whether,wait,string,note,basic,defined,drop,modular,observe} from "./Blik_2023_inference.js"; |
4 | 4 | import {window,fetch,digest,path,agent} from "./Blik_2023_interface.js"; |
5 | 5 | import {document,css,capture,metamarkup,destroy,keyboard} from "./Blik_2023_fragment.js"; |
6 | 6 | import {EditorState,Compartment} from './haverbeke_2022_codemirror_state.js'; |
7 | 7 | import {EditorView,keymap,lineNumbers,drawSelection} from './haverbeke_2022_codemirror_view.js'; |
8 | 8 | import {history,defaultKeymap,historyKeymap} from './haverbeke_2022_codemirror_commands.js'; |
9 | | - import {foldGutter,foldKeymap,codeFolding,syntaxHighlighting,defaultHighlightStyle,HighlightStyle,syntaxTree,ensureSyntaxTree,foldable,foldEffect,unfoldAll,foldAll} from './haverbeke_2022_codemirror_language.js'; |
| 9 | + import {foldGutter,foldKeymap,codeFolding,syntaxHighlighting,defaultHighlightStyle,HighlightStyle,syntaxTree,syntaxTreeAvailable,ensureSyntaxTree,forceParsing,foldable,foldEffect,unfoldAll,foldAll} from './haverbeke_2022_codemirror_language.js'; |
10 | 10 | import {javascript} from './haverbeke_2022_codemirror_js.js'; |
11 | 11 | import {StyleModule} from './haverbeke_2022_stylemod.js'; |
12 | 12 | import {parser as lezer} from "./haverbeke_2022_lezer_js.js" |
|
35 | 35 | {"/Blik_2023_search.js":["","merge","record"] |
36 | 36 | ,"/Blik_2023_interface.js":["","resolve","fetch"] |
37 | 37 | ,"/Blik_2023_inference.js":["","note","slip","compose","collect","combine"] |
38 | | - ,"/Blik_2023_fragment.js":["","metamarkup as dataset"] |
| 38 | + ,"/Blik_2023_fragment.js":["","metamarkup as dataset","destroy","size"] |
39 | 39 | ,[file]:["script","fold","resize"] |
40 | 40 | } |
41 | 41 | ,exports:{default: |
42 | 42 | {".codemirror": |
43 | 43 | {contextrestored(event) |
44 | 44 | {let lines=Array.from(this.querySelectorAll(".cm-line")).map(({textContent:line})=>line); |
45 | 45 | let meta=[dataset(this),{parent:this}].reduce(merge,{}); |
46 | | - this.childNodes.forEach(destroy); |
| 46 | + Array.from(this.childNodes).forEach(destroy); |
47 | 47 | script(lines.join("\n"),meta); |
48 | | -},keydown({keyCode,ctrlKey,altKey}) |
| 48 | +},keydown({keyCode,ctrlKey:ctrl,altKey:alt}) |
49 | 49 | {let {s,w,f}=keyboard(keyCode); |
50 | | - if(ctrlKey&&altKey&&f) |
51 | | - return fold.call(this); |
52 | | - if(w&&altKey) |
53 | | - return compose(combine(infer(),({whiteSpace})=>whiteSpace==="pre-wrap" |
| 50 | + if(alt&&f) |
| 51 | + return arguments[0].preventDefault(),fold.call(this); |
| 52 | + if(alt&&w) |
| 53 | + return compose(stash(({whiteSpace})=>whiteSpace==="pre-wrap" |
54 | 54 | ?{maxWidth:"",whiteSpace:"",wordBreak:""} |
55 | | -:{maxWidth:"calc(100% - 2.5em)",whiteSpace:"pre-wrap",wordBreak:"break-all"}),note,Object.assign)(this.querySelector(".cm-content").style); |
56 | | - if(!s||!ctrlKey)return; |
| 55 | +:{maxWidth:"calc(100% - 2.5em)",whiteSpace:"pre-wrap",wordBreak:"break-all"}),Object.assign)(this.querySelector(".cm-content").style); |
| 56 | + if(!s||!ctrl)return; |
57 | 57 | arguments[0].preventDefault(); |
58 | 58 | let source=this.querySelector(".cm-content").cmView.view.viewState.state.doc.toString(); |
59 | 59 | let bytes=new Array(source.length); |
60 | 60 | for(let index in source) |
61 | 61 | bytes[index]=source.charCodeAt(index); |
62 | 62 | var blob=new Blob([new Uint8Array(bytes)],{type:'text/plain'}); |
63 | 63 | let target=this.dataset.source+"?override=true"; |
64 | | - let buffer=Object.assign(new FileReader(),{onload:compose |
| 64 | + let buffer=Object.assign(new FileReader() |
| 65 | +,{onload:compose |
65 | 66 | ((file,event)=>fetch(target,{method:"put",body:btoa(event.target.result)}) |
66 | | -,compose("text",["message"],record,{action:"broadcast",room:this.dataset.source},merge |
| 67 | +,note,"text",combine |
| 68 | +(body=>fetch("/inspect?module="+this.dataset.source,{method:"put",body}) |
| 69 | +,compose(["message"],record,{action:"broadcast",room:this.dataset.source},merge |
67 | 70 | ,["data"],record,{bubbles:true},merge,slip("message"),collect,slip(MessageEvent) |
68 | 71 | ,Reflect.construct,slip(this),"dispatchEvent") |
| 72 | +) |
69 | 73 | )}) |
70 | 74 | buffer.readAsBinaryString(blob); |
71 | | -},...observe({pinch(event) |
72 | | -{if(event.touches.length!==2) |
| 75 | +},...observe({touch(event) |
| 76 | +{let {type,touches,isTrusted:start}=event; |
| 77 | + if(!start) |
| 78 | + return this.control?.abort(); |
| 79 | + if(touches.length!==2) |
73 | 80 | return; |
| 81 | + let width=({touches})=>Array.from(touches).map(({pageX:x,pageY:y})=>[x,y]).reduce(([x1,y1],[x2,y2])=>Math.hypot(x1-x2,y1-y2)); |
| 82 | + let unit=width(event); |
| 83 | + let font=size(this.querySelector(".cm-content")); |
| 84 | + merge(this,{control:new AbortController()}); |
| 85 | + observe.call(this |
| 86 | +,{touchmove(event) |
| 87 | +{event.preventDefault(); |
| 88 | + resize.call(this,Math.max(1,Math.round(width(event)/unit*font))); |
| 89 | +}},{signal:this.control.signal}); |
| 90 | +}}) |
| 91 | + ,wheel(event) |
| 92 | +{if(!event.ctrlKey)return; |
74 | 93 | event.preventDefault(); |
75 | | - let {type,touches,isTrusted:start}=event; |
76 | | - let [[x1,y1],[x2,y2]]=Array.from(touches).map(({pageX:x,pageY:y})=>[x,y]); |
77 | | - let width=Math.hypot(x1-x2,y1-y2); |
78 | | - if(start) |
79 | | - return this.start=width; |
80 | | - let scale=2**(Math.floor(width-this.start)/50); |
81 | | - resize.call(this,scale); |
82 | | -}})} |
| 94 | + let past=size(this.querySelector(".cm-content")); |
| 95 | + let dy=event.deltaY/4; |
| 96 | + let scale=1-Math.sign(dy)*Math.min(24,Math.abs(dy)) |
| 97 | + resize.call(this,Math.max(1,Math.round(past*scale))); |
| 98 | +}} |
83 | 99 | }}}; |
84 | 100 | let parent=settings.parent||document({div:{class:"codemirror",...metamarkup(settings)}}); |
85 | 101 | //let language=(new Compartment).of(js()); |
86 | 102 | let indentation=new Compartment().of(EditorState.tabSize.of(1)); |
87 | 103 | let doc=string(source)?settings.source?source:await compose(fetch,digest,infer(serialize,"json"),buffer(compose(JSON.parse,aphorize),drop(1)))(source):JSON.stringify(source); |
| 104 | + let author=cookie("author"); |
| 105 | + let {font}=author?await compose(fetch,digest)("/author/"+author):{}; |
| 106 | + let size=font?font.size+"px":"1em"; |
88 | 107 | let theme=new Compartment().of(EditorView.theme( |
89 | | - {".cm-content":{"text-align":"left","font-family":settings.font,"font-size":"1em"} |
90 | | - ,".cm-gutters":{background:"transparent"} |
| 108 | + {".cm-content":{"text-align":"left","font-family":settings.font,"font-size":size} |
| 109 | + ,".cm-gutters":{background:"transparent","font-size":size} |
91 | 110 | // gutter heights are calculated dynamically on client-side. |
92 | 111 | ,".cm-gutterElement":{height:"4px !important",color:"var(--note)"} |
93 | 112 | ,".cm-gutterElement:not(:first-of-type)":{height:"1.4em !important",transform:"translate(0,-4px)"} |
|
101 | 120 | },{dark:true})); |
102 | 121 | let state=EditorState.create({doc,extensions:[basetheme,foldtheme,theme,extensions].flat()}); |
103 | 122 | let view=new EditorView({parent,state},window); |
104 | | - if(defined(settings.fold)) |
105 | | - settings.fold<1?foldAll(view):fold.call(parent,settings.fold); |
106 | | - let style=parent.ownerDocument.querySelector("head").querySelector("style").textContent; |
| 123 | + if(settings.fold!==false&&globalThis.window) |
| 124 | + fold.call(parent,settings.fold||0); |
107 | 125 | //let style=view.styleModules.flatMap(({rules})=>rules).reverse().join("\n"); |
108 | | - parent.prepend(document({style:{"#text":style}})); |
| 126 | + let style=parent.ownerDocument.querySelector("head").querySelector("style"); |
109 | 127 | if(!globalThis.window) |
110 | | - parent.querySelector(".cm-content").cmView.view.viewState.state.doc.toString().split("\n").forEach((line,index)=> |
| 128 | + parent.prepend(document({style:{"#text":style.textContent}})),style.remove() |
| 129 | +,parent=parent.cloneNode(true),doc.split("\n").forEach((line,index)=> |
111 | 130 | [".cm-line",".cm-lineNumbers>.cm-gutterElement"].map(name=> |
112 | 131 | Array.from(parent.querySelectorAll(name))).forEach((lines,gutter)=> |
113 | | - lines[index+gutter]||lines.at(-1).after(Object.assign(lines[gutter].cloneNode(true) |
| 132 | + lines[index+gutter]||lines.at(-1).after(Object.assign(lines.at(-1).cloneNode(true) |
114 | 133 | ,{textContent:gutter?index+1:line})))); |
115 | | - return capture.call(parent,file+"/module/default/module"); |
| 134 | + return settings.parent?parent:capture.call(parent,file+"/module/default/module"); |
116 | 135 | }; |
117 | 136 |
|
118 | | - export function resize(scale) |
| 137 | + export function resize(next) |
119 | 138 | {let text=this.querySelector(".cm-content"); |
120 | | - let {view}=text.cmView; |
121 | | - let {fontSize}=window.getComputedStyle(text); |
| 139 | + let past=size(text); |
| 140 | + if(next===past)return; |
| 141 | + let {cmView:{view}}=text; |
122 | 142 | let theme=view.viewState.state.config.base[2]; |
123 | | - let size=Number(fontSize.replace(/[a-z]/g,"")||1)*scale; |
124 | | - view.dispatch({effects:theme.compartment.reconfigure([theme.inner,EditorView.theme( |
125 | | - {".cm-content":{"font-size":size+"em"} |
126 | | - ,".cm-gutters":{"font-size":size+"em"} |
127 | | - })])}); |
| 143 | + view.dispatch({effects:theme.compartment.reconfigure([EditorView.theme( |
| 144 | + {".cm-content":{"font-size":next+"px"} |
| 145 | + ,".cm-gutters":{"font-size":next+"px"} |
| 146 | + }),theme.inner])}); |
| 147 | + let author=cookie("author"); |
| 148 | + if(!author)return; |
| 149 | + buffer(compose |
| 150 | +(wait(10000),size,when(is(next)),drop() |
| 151 | +,"/author/"+author,{method:"put",body:JSON.stringify({font:{size:next}})},fetch,digest,note |
| 152 | +),note)(text); |
128 | 153 | }; |
129 | 154 |
|
130 | 155 | export function fold(depth=0) |
131 | 156 | {let {view}=this.querySelector(".cm-content").cmView; |
132 | 157 | let {state}=view.viewState; |
133 | 158 | let effects=[]; |
134 | | - ensureSyntaxTree(state,state.doc.length,5000).iterate( |
| 159 | + ensureSyntaxTree(state,state.doc.length,10000).iterate( |
135 | 160 | {enter({stack:{length},from,to}) |
136 | 161 | {let effect=depth<=length?foldable(state,from,to):undefined; |
137 | 162 | if(effect)effects.push(foldEffect.of(effect)); |
138 | 163 | },from:0,to:state.doc.length |
139 | 164 | }); |
140 | 165 | view.dispatch({effects}); |
141 | | - }; |
| 166 | +}; |
142 | 167 |
|
143 | 168 | export function highlight(source) |
144 | 169 | {let span=[]; |
|
183 | 208 | },Object.entries,infer("map",([field,value])=>[".cm-"+field,value]),Object.fromEntries |
184 | 209 | )); |
185 | 210 |
|
186 | | -const foldtheme = EditorView.baseTheme( |
| 211 | + var foldtheme=EditorView.baseTheme( |
187 | 212 | {".cm-foldPlaceholder":{backgroundColor: "#eee",border: "1px solid #ddd",color: "#888",borderRadius: ".2em",margin: "0 1px",padding: "0 1px",cursor: "pointer"} |
188 | 213 | ,".cm-foldGutter span": {padding: "0 1px",cursor: "pointer"} |
189 | 214 | }); |
0 commit comments