Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita702cbd

Browse files
committed
add support for custom widgets registration in Python
1 parente409f5c commita702cbd

File tree

4 files changed

+190
-2
lines changed

4 files changed

+190
-2
lines changed

‎pyscriptjs/src/components/base.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,171 @@ export class BaseEvalElement extends HTMLElement {
151151
}
152152
}
153153
}
154+
155+
functioncreateWidget(name:string,code:string,klass:string){
156+
157+
158+
classCustomWidgetextendsHTMLElement{
159+
shadow:ShadowRoot;
160+
wrapper:HTMLElement;
161+
162+
name:string=name;
163+
klass:string=klass;
164+
code:string=code;
165+
proxy:any;
166+
proxyClass:any;
167+
168+
constructor(){
169+
super();
170+
171+
// attach shadow so we can preserve the element original innerHtml content
172+
this.shadow=this.attachShadow({mode:'open'});
173+
174+
this.wrapper=document.createElement('slot');
175+
this.shadow.appendChild(this.wrapper);
176+
}
177+
178+
connectedCallback(){
179+
console.log(this.name,'connected!!!!')
180+
this.eval(this.code).then(()=>{
181+
this.proxy=this.proxyClass(this);
182+
console.log('proxy',this.proxy);
183+
this.proxy.connect();
184+
this.registerWidget();
185+
});
186+
}
187+
188+
asyncregisterWidget(){
189+
letpyodide=awaitpyodideReadyPromise;
190+
191+
console.log('new widget registered:',this.name);
192+
193+
194+
pyodide.globals.set(this.id,this.proxy);
195+
}
196+
197+
asynceval(source:string):Promise<void>{
198+
letoutput;
199+
letpyodide=awaitpyodideReadyPromise;
200+
try{
201+
output=awaitpyodide.runPythonAsync(source);
202+
this.proxyClass=pyodide.globals.get(this.klass);
203+
if(output!==undefined){
204+
console.log(output);
205+
}
206+
207+
}catch(err){
208+
console.log(err);
209+
}
210+
}
211+
}
212+
letxPyWidget=customElements.define(name,CustomWidget);
213+
}
214+
215+
exportclassPyWidgetextendsHTMLElement{
216+
shadow:ShadowRoot;
217+
name:string;
218+
klass:string;
219+
outputElement:HTMLElement;
220+
errorElement:HTMLElement;
221+
wrapper:HTMLElement;
222+
theme:string;
223+
source:string;
224+
code:string;
225+
226+
constructor(){
227+
super();
228+
229+
// attach shadow so we can preserve the element original innerHtml content
230+
this.shadow=this.attachShadow({mode:'open'});
231+
232+
this.wrapper=document.createElement('slot');
233+
this.shadow.appendChild(this.wrapper);
234+
235+
if(this.hasAttribute('src')){
236+
this.source=this.getAttribute('src');
237+
}
238+
239+
if(this.hasAttribute('name')){
240+
this.name=this.getAttribute('name');
241+
}
242+
243+
if(this.hasAttribute('klass')){
244+
this.klass=this.getAttribute('klass');
245+
}
246+
}
247+
248+
249+
connectedCallback(){
250+
if(this.id===undefined){
251+
thrownewReferenceError(`No id specified for component. Components must have an explicit id. Please use id="" to specify your component id.`)
252+
return;
253+
}
254+
255+
letmainDiv=document.createElement('div');
256+
mainDiv.id=this.id+'-main';
257+
this.appendChild(mainDiv);
258+
console.log('reading source')
259+
this.getSourceFromFile(this.source).then((code:string)=>{
260+
this.code=code;
261+
createWidget(this.name,code,this.klass);
262+
263+
});
264+
265+
console.log('py-template connected');
266+
}
267+
268+
initOutErr():void{
269+
if(this.hasAttribute('output')){
270+
this.errorElement=this.outputElement=document.getElementById(this.getAttribute('output'));
271+
272+
// in this case, the default output-mode is append, if hasn't been specified
273+
if(!this.hasAttribute('output-mode')){
274+
this.setAttribute('output-mode','append');
275+
}
276+
}else{
277+
if(this.hasAttribute('std-out')){
278+
this.outputElement=document.getElementById(this.getAttribute('std-out'));
279+
}else{
280+
// In this case neither output or std-out have been provided so we need
281+
// to create a new output div to output to
282+
this.outputElement=document.createElement('div');
283+
this.outputElement.classList.add("output");
284+
this.outputElement.hidden=true;
285+
this.outputElement.id=this.id+"-"+this.getAttribute("exec-id");
286+
287+
// add the output div id if there's not output pre-defined
288+
//mainDiv.appendChild(this.outputElement);
289+
}
290+
291+
if(this.hasAttribute('std-err')){
292+
this.outputElement=document.getElementById(this.getAttribute('std-err'));
293+
}else{
294+
this.errorElement=this.outputElement;
295+
}
296+
}
297+
}
298+
299+
asyncgetSourceFromFile(s:string):Promise<string>{
300+
letpyodide=awaitpyodideReadyPromise;
301+
letresponse=awaitfetch(s);
302+
returnawaitresponse.text();
303+
}
304+
305+
asynceval(source:string):Promise<void>{
306+
letoutput;
307+
letpyodide=awaitpyodideReadyPromise;
308+
try{
309+
output=awaitpyodide.runPythonAsync(source);
310+
311+
if(output!==undefined){
312+
console.log(output);
313+
}
314+
315+
}catch(err){
316+
console.log(err);
317+
}
318+
}
319+
320+
321+
}

‎pyscriptjs/src/components/pyscript.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ async function mountElements() {
296296
for(varelofmatches){
297297
letmountName=el.getAttribute('py-mount');
298298
if(!mountName){
299-
mountName=el.id.replace("-","_");
299+
mountName=el.id.split("-").join("_");
300300
}
301301
source+=`\n${mountName} = Element("${el.id}")`;
302302
}

‎pyscriptjs/src/interpreter.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ class Element:
5858
self._element = document.querySelector(f'#{self._id}');
5959
return self._element
6060
61+
@property
62+
def value(self):
63+
return self.element.value
64+
65+
@property
66+
def innerHtml(self):
67+
return self.element.innerHtml
68+
6169
def write(self, value, append=False):
6270
console.log(f"Element.write: {value} --> {append}")
6371
# TODO: it should be the opposite... pyscript.write should use the Element.write
@@ -96,6 +104,17 @@ class Element:
96104
97105
return Element(clone.id, clone)
98106
107+
108+
def remove_class(self, classname):
109+
if isinstance(classname, list):
110+
for cl in classname:
111+
self.remove_class(cl)
112+
else:
113+
self.element.classList.remove(classname)
114+
115+
def add_class(self, classname):
116+
self.element.classList.add(classname)
117+
99118
class OutputCtxManager:
100119
def __init__(self, out=None, output_to_console=True, append=True):
101120
self._out = out

‎pyscriptjs/src/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import { PyScript } from "./components/pyscript";
44
import{PyRepl}from"./components/pyrepl";
55
import{PyEnv}from"./components/pyenv";
66
import{PyBox}from"./components/pybox";
7-
7+
import{PyWidget}from"./components/base";
88

99
letxPyScript=customElements.define('py-script',PyScript);
1010
letxPyRepl=customElements.define('py-repl',PyRepl);
1111
letxPyEnv=customElements.define('py-env',PyEnv);
1212
letxPyBox=customElements.define('py-box',PyBox);
13+
letxPyWidget=customElements.define('py-register-widget',PyWidget);
1314

1415

1516
constapp=newApp({

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp