Skip to content

Commit 60dd6d1

Browse files
save file
1 parent 4d98c7a commit 60dd6d1

1 file changed

Lines changed: 289 additions & 0 deletions

File tree

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
<webcontainer-terminal>
2+
3+
<template shadowrootmode=open>
4+
5+
6+
</template>
7+
8+
9+
<script>
10+
11+
(function({mod,host}){
12+
13+
var obj = {
14+
version : 'v1.0.0',
15+
};
16+
17+
var df=true,did='webcontainer-terminal';
18+
19+
var Terminal,webcontainer,FitAddon,spinner,theme;
20+
21+
obj.initmod = function(params){
22+
23+
$ = mod.rd(params,'$',$);
24+
Terminal = mod.rd(params,'Terminal',Terminal);
25+
webcontainer = mod.rd(params,'webcontainer',webcontainer);
26+
FitAddon = mod.rd(params,'FitAddon',FitAddon);
27+
spinner = mod.rd(params,'spinner',spinner);
28+
theme = mod.rd(params,'theme',theme);
29+
30+
}//initmod
31+
32+
33+
//:
34+
35+
36+
var term;
37+
var shell;
38+
39+
var output;
40+
41+
42+
//:
43+
44+
45+
obj.init = async function(){
46+
47+
term = new Terminal({
48+
49+
fontFamily : 'monospace',
50+
fontSize : 16,
51+
lineHeight : 1.0,
52+
53+
theme : theme.light,
54+
rendererType : 'dom',
55+
56+
});
57+
58+
59+
term.buffer = [];
60+
term.pause = false;
61+
term.flush = ()=>{
62+
63+
term.buffer.forEach(data=>term.write(data));
64+
term.buffer.length = 0;
65+
66+
}//flush
67+
term.resume = (flush=true)=>{
68+
69+
if(flush){
70+
term.flush();
71+
}
72+
term.buffer.length = 0;
73+
term.pause = false;
74+
75+
}//resume
76+
term.write.xy = (x,y,txt)=>{
77+
78+
term.write(`${cursor.save}${cursor.to(x,y)}${txt}${cursor.restore}`);
79+
80+
}//xy
81+
82+
term.end_of_text = function(y){
83+
// xterm.js uses 0-based indexing for the buffer,
84+
// but 1-based for ANSI
85+
var line = term.buffer.active.getLine(y-1);
86+
if(!line){
87+
return 1;
88+
}
89+
90+
var last = 0;
91+
for(var i=term.cols-1;i>=0;i--){
92+
93+
var cell = line.getCell(i);
94+
// Check if the cell is not empty/whitespace
95+
if(cell&&cell.getChars().trim()!==''){
96+
last = i+1;
97+
break;
98+
}
99+
100+
}//for
101+
return last+1;
102+
103+
}//end_of_text
104+
105+
106+
107+
for(let key in colors){
108+
109+
if(key=='reset')continue;
110+
111+
term.write[key] = (...args)=>term.write(colors[key]+args.join(' ')+colors.reset);
112+
term.writeln[key] = (...args)=>term.writeln(colors[key]+args.join(' ')+colors.reset);
113+
114+
}//for
115+
116+
117+
//term.writeln('\x1b[1;31m THIS SHOULD BE BOLD RED \x1b[0m');
118+
119+
120+
term.parser.registerOscHandler(7, (data) => {
121+
console.log('osc-handler7 :',data);
122+
/*
123+
// data will look like: "file://localhost/home/project/src"
124+
try {
125+
const url = new URL(data);
126+
const newCwd = url.pathname;
127+
128+
console.log('CWD Changed to:', newCwd);
129+
130+
// You can now update your UI state or breadcrumbs here
131+
updateMyBreadcrumbs(newCwd);
132+
} catch (e) {
133+
return false; // Let xterm handle it if it's malformed
134+
}
135+
return true; // We handled it
136+
*/
137+
138+
});
139+
140+
141+
var fitAddon = new FitAddon();
142+
term.loadAddon(fitAddon);
143+
144+
145+
}//init
146+
147+
148+
//:
149+
150+
151+
obj.initdom = async function(){
152+
153+
shadow = host.shadowRoot;
154+
155+
terminal = $(shadow,'#terminal');
156+
157+
158+
term.open(terminal);
159+
fitAddon.fit();
160+
161+
162+
spawn_jsh();
163+
164+
//term.resize();
165+
term.focus();
166+
167+
}//initdom
168+
169+
170+
function spawn_jsh(){
171+
172+
term.writeln('spawn jsh ... ');
173+
var s3 = spinner({x:14,y:0});
174+
webcontainer.spawn('jsh').then(complete)
175+
176+
177+
function complete(){
178+
179+
shell = result;
180+
s3.stop();
181+
term.write.xy(14,1,`${colors.green}ok.${colors.reset}`);
182+
shell.output.pipeTo(output);
183+
input = shell.input.getWriter();
184+
term.onData(data=>input.write(data));
185+
//term.resize();
186+
setTimeout(()=>term.focus(),50);
187+
188+
}//complete
189+
190+
}//spawn_jsh
191+
192+
193+
//:
194+
195+
196+
output = new WritableStream({
197+
write(data){
198+
//console.log(data);
199+
var str = data;
200+
str = str.replaceAll('\r','');
201+
var lines = str.split('\n');
202+
lines.forEach(line=>{
203+
//console.log('Hex:',[...line].map(c=>c.charCodeAt(0).toString(16).padStart(2,'0')).join(' '));
204+
if(line.startsWith('\x1b[J') && line.indexOf('\x1b[39m')!=-1){
205+
var i1;
206+
var i;
207+
i = line.indexOf('/');
208+
if(i!=-1){
209+
i1 = i;
210+
}
211+
i = line.indexOf('~');
212+
if(i!=-1){
213+
i1 = i;
214+
}
215+
if(i1!==undefined){
216+
var i2 = line.indexOf('\x1b[39m');
217+
if(i1<i2){
218+
var dir = line.slice(i1,i2);
219+
if(dir!='/'){
220+
dir += '/';
221+
}
222+
if(user_dir===undefined){
223+
user_dir = dir.slice(2,-1);
224+
shell.user_dir = user_dir;
225+
console.log('[ user_dir ]',user_dir);
226+
}
227+
if(dir.indexOf('~')!=-1){
228+
dir = dir.replace('~',`/home`);
229+
}
230+
231+
if(dir.startsWith(`/home/${user_dir}`)){
232+
cwd_abs = dir;
233+
cwd = dir.slice(user_dir.length+6);
234+
}else{
235+
cwd_abs = dir;
236+
cwd = null;
237+
}
238+
shell.cwd_abs = cwd_abs;
239+
shell.cwd = cwd;
240+
console.log('[ cwd_abs ]',cwd_abs);
241+
console.log('[ cwd ]',cwd);
242+
}
243+
}
244+
}
245+
});
246+
247+
248+
if(output.pause){
249+
output.buffer.push(data);
250+
}else{
251+
term.write(data);
252+
}
253+
254+
}
255+
});
256+
257+
output.buffer = [];
258+
output.pause = false;
259+
output.flush = ()=>{
260+
261+
output.buffer.forEach(data=>term.write(data));
262+
output.buffer.length = 0;
263+
264+
}//flush
265+
output.resume = (flush=true)=>{
266+
267+
if(flush){
268+
output.flush();
269+
}
270+
output.buffer.length = 0;
271+
output.pause = false;
272+
273+
}//resume
274+
275+
276+
//:
277+
278+
279+
return obj;
280+
281+
//webcontainer-terminal
282+
})
283+
284+
</script>
285+
286+
</webcontainer-terminal>
287+
288+
289+

0 commit comments

Comments
 (0)