upgraded ui

This commit is contained in:
Saifeddine ALOUI 2025-04-09 08:49:18 +02:00
parent 2d2d3736a6
commit 8b617c39a1
12 changed files with 201 additions and 262 deletions

@ -1 +1 @@
Subproject commit ad12efdf07a0b39003118695c5bd2b6e29185965
Subproject commit c940d0abf631dfcc8f00fcffe738758173b25cb1

View File

@ -1 +1 @@
import{b as O,d as b,L as r,f as s,g as a,s as t,j as P,l as n,t as e}from"./index-DgMg835f.js";const S={__proto__:null,anyref:34,dataref:34,eqref:34,externref:34,i31ref:34,funcref:34,i8:34,i16:34,i32:34,i64:34,f32:34,f64:34},Q=r.deserialize({version:14,states:"!^Q]QPOOOqQPO'#CbOOQO'#Cd'#CdOOQO'#Cl'#ClOOQO'#Ch'#ChQ]QPOOOOQO,58|,58|OxQPO,58|OOQO-E6f-E6fOOQO1G.h1G.h",stateData:"!P~O_OSPOSQOS~OTPOVROXROYROZROaQO~OSUO~P]OSXO~P]O",goto:"xaPPPPPPbPbPPPhPPPrXROPTVQTOQVPTWTVXSOPTV",nodeNames:"⚠ LineComment BlockComment Module ) ( App Identifier Type Keyword Number String",maxTerm:17,nodeProps:[["isolate",-3,1,2,11,""],["openedBy",4,"("],["closedBy",5,")"],["group",-6,6,7,8,9,10,11,"Expression"]],skippedNodes:[0,1,2],repeatNodeCount:1,tokenData:"0o~R^XY}YZ}]^}pq}rs!Stu#pxy'Uyz(e{|(j}!O(j!Q!R(s!R![*p!]!^.^#T#o.{~!SO_~~!VVOr!Srs!ls#O!S#O#P!q#P;'S!S;'S;=`#j<%lO!S~!qOZ~~!tRO;'S!S;'S;=`!};=`O!S~#QWOr!Srs!ls#O!S#O#P!q#P;'S!S;'S;=`#j;=`<%l!S<%lO!S~#mP;=`<%l!S~#siqr%bst%btu%buv%bvw%bwx%bz{%b{|%b}!O%b!O!P%b!P!Q%b!Q![%b![!]%b!^!_%b!_!`%b!`!a%b!a!b%b!b!c%b!c!}%b#Q#R%b#R#S%b#S#T%b#T#o%b#p#q%b#r#s%b~%giV~qr%bst%btu%buv%bvw%bwx%bz{%b{|%b}!O%b!O!P%b!P!Q%b!Q![%b![!]%b!^!_%b!_!`%b!`!a%b!a!b%b!b!c%b!c!}%b#Q#R%b#R#S%b#S#T%b#T#o%b#p#q%b#r#s%b~'ZPT~!]!^'^~'aTO!]'^!]!^'p!^;'S'^;'S;=`(_<%lO'^~'sVOy'^yz(Yz!]'^!]!^'p!^;'S'^;'S;=`(_<%lO'^~(_OQ~~(bP;=`<%l'^~(jOS~~(mQ!Q!R(s!R![*p~(xUY~!O!P)[!Q![*p!g!h){#R#S+U#X#Y){#l#m+[~)aRY~!Q![)j!g!h){#X#Y){~)oSY~!Q![)j!g!h){#R#S*j#X#Y){~*OR{|*X}!O*X!Q![*_~*[P!Q![*_~*dQY~!Q![*_#R#S*X~*mP!Q![)j~*uTY~!O!P)[!Q![*p!g!h){#R#S+U#X#Y){~+XP!Q![*p~+_R!Q![+h!c!i+h#T#Z+h~+mVY~!O!P,S!Q![+h!c!i+h!r!s-P#R#S+[#T#Z+h#d#e-P~,XTY~!Q![,h!c!i,h!r!s-P#T#Z,h#d#e-P~,mUY~!Q![,h!c!i,h!r!s-P#R#S.Q#T#Z,h#d#e-P~-ST{|-c}!O-c!Q![-o!c!i-o#T#Z-o~-fR!Q![-o!c!i-o#T#Z-o~-tSY~!Q![-o!c!i-o#R#S-c#T#Z-o~.TR!Q![,h!c!i,h#T#Z,h~.aP!]!^.d~.iSP~OY.dZ;'S.d;'S;=`.u<%lO.d~.xP;=`<%l.d~/QiX~qr.{st.{tu.{uv.{vw.{wx.{z{.{{|.{}!O.{!O!P.{!P!Q.{!Q![.{![!].{!^!_.{!_!`.{!`!a.{!a!b.{!b!c.{!c!}.{#Q#R.{#R#S.{#S#T.{#T#o.{#p#q.{#r#s.{",tokenizers:[0],topRules:{Module:[0,3]},specialized:[{term:9,get:o=>S[o]||-1}],tokenPrec:0}),i=O.define({name:"wast",parser:Q.configure({props:[s.add({App:P({closing:")",align:!1})}),a.add({App:n,BlockComment(o){return{from:o.from+2,to:o.to-2}}}),t({Keyword:e.keyword,Type:e.typeName,Number:e.number,String:e.string,Identifier:e.variableName,LineComment:e.lineComment,BlockComment:e.blockComment,"( )":e.paren})]}),languageData:{commentTokens:{line:";;",block:{open:"(;",close:";)"}},closeBrackets:{brackets:["(",'"']}}});function p(){return new b(i)}export{p as wast,i as wastLanguage};
import{b as O,d as b,L as r,f as s,g as a,s as t,j as P,l as n,t as e}from"./index-BgJuLk5j.js";const S={__proto__:null,anyref:34,dataref:34,eqref:34,externref:34,i31ref:34,funcref:34,i8:34,i16:34,i32:34,i64:34,f32:34,f64:34},Q=r.deserialize({version:14,states:"!^Q]QPOOOqQPO'#CbOOQO'#Cd'#CdOOQO'#Cl'#ClOOQO'#Ch'#ChQ]QPOOOOQO,58|,58|OxQPO,58|OOQO-E6f-E6fOOQO1G.h1G.h",stateData:"!P~O_OSPOSQOS~OTPOVROXROYROZROaQO~OSUO~P]OSXO~P]O",goto:"xaPPPPPPbPbPPPhPPPrXROPTVQTOQVPTWTVXSOPTV",nodeNames:"⚠ LineComment BlockComment Module ) ( App Identifier Type Keyword Number String",maxTerm:17,nodeProps:[["isolate",-3,1,2,11,""],["openedBy",4,"("],["closedBy",5,")"],["group",-6,6,7,8,9,10,11,"Expression"]],skippedNodes:[0,1,2],repeatNodeCount:1,tokenData:"0o~R^XY}YZ}]^}pq}rs!Stu#pxy'Uyz(e{|(j}!O(j!Q!R(s!R![*p!]!^.^#T#o.{~!SO_~~!VVOr!Srs!ls#O!S#O#P!q#P;'S!S;'S;=`#j<%lO!S~!qOZ~~!tRO;'S!S;'S;=`!};=`O!S~#QWOr!Srs!ls#O!S#O#P!q#P;'S!S;'S;=`#j;=`<%l!S<%lO!S~#mP;=`<%l!S~#siqr%bst%btu%buv%bvw%bwx%bz{%b{|%b}!O%b!O!P%b!P!Q%b!Q![%b![!]%b!^!_%b!_!`%b!`!a%b!a!b%b!b!c%b!c!}%b#Q#R%b#R#S%b#S#T%b#T#o%b#p#q%b#r#s%b~%giV~qr%bst%btu%buv%bvw%bwx%bz{%b{|%b}!O%b!O!P%b!P!Q%b!Q![%b![!]%b!^!_%b!_!`%b!`!a%b!a!b%b!b!c%b!c!}%b#Q#R%b#R#S%b#S#T%b#T#o%b#p#q%b#r#s%b~'ZPT~!]!^'^~'aTO!]'^!]!^'p!^;'S'^;'S;=`(_<%lO'^~'sVOy'^yz(Yz!]'^!]!^'p!^;'S'^;'S;=`(_<%lO'^~(_OQ~~(bP;=`<%l'^~(jOS~~(mQ!Q!R(s!R![*p~(xUY~!O!P)[!Q![*p!g!h){#R#S+U#X#Y){#l#m+[~)aRY~!Q![)j!g!h){#X#Y){~)oSY~!Q![)j!g!h){#R#S*j#X#Y){~*OR{|*X}!O*X!Q![*_~*[P!Q![*_~*dQY~!Q![*_#R#S*X~*mP!Q![)j~*uTY~!O!P)[!Q![*p!g!h){#R#S+U#X#Y){~+XP!Q![*p~+_R!Q![+h!c!i+h#T#Z+h~+mVY~!O!P,S!Q![+h!c!i+h!r!s-P#R#S+[#T#Z+h#d#e-P~,XTY~!Q![,h!c!i,h!r!s-P#T#Z,h#d#e-P~,mUY~!Q![,h!c!i,h!r!s-P#R#S.Q#T#Z,h#d#e-P~-ST{|-c}!O-c!Q![-o!c!i-o#T#Z-o~-fR!Q![-o!c!i-o#T#Z-o~-tSY~!Q![-o!c!i-o#R#S-c#T#Z-o~.TR!Q![,h!c!i,h#T#Z,h~.aP!]!^.d~.iSP~OY.dZ;'S.d;'S;=`.u<%lO.d~.xP;=`<%l.d~/QiX~qr.{st.{tu.{uv.{vw.{wx.{z{.{{|.{}!O.{!O!P.{!P!Q.{!Q![.{![!].{!^!_.{!_!`.{!`!a.{!a!b.{!b!c.{!c!}.{#Q#R.{#R#S.{#S#T.{#T#o.{#p#q.{#r#s.{",tokenizers:[0],topRules:{Module:[0,3]},specialized:[{term:9,get:o=>S[o]||-1}],tokenPrec:0}),i=O.define({name:"wast",parser:Q.configure({props:[s.add({App:P({closing:")",align:!1})}),a.add({App:n,BlockComment(o){return{from:o.from+2,to:o.to-2}}}),t({Keyword:e.keyword,Type:e.typeName,Number:e.number,String:e.string,Identifier:e.variableName,LineComment:e.lineComment,BlockComment:e.blockComment,"( )":e.paren})]}),languageData:{commentTokens:{line:";;",block:{open:"(;",close:";)"}},closeBrackets:{brackets:["(",'"']}}});function p(){return new b(i)}export{p as wast,i as wastLanguage};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{b as q,d as P,q as g,r as l,L as c,u as i,s as R,t as r,E as p}from"./index-DgMg835f.js";const b=1,$=33,m=34,v=35,x=36,d=new p(O=>{let e=O.pos;for(;;){if(O.next==10){O.advance();break}else if(O.next==123&&O.peek(1)==123||O.next<0)break;O.advance()}O.pos>e&&O.acceptToken(b)});function n(O,e,a){return new p(t=>{let u=t.pos;for(;t.next!=O&&t.next>=0&&(a||t.next!=38&&(t.next!=123||t.peek(1)!=123));)t.advance();t.pos>u&&t.acceptToken(e)})}const W=n(39,$,!1),C=n(34,m,!1),T=n(39,v,!0),f=n(34,x,!0),A=c.deserialize({version:14,states:"(jOVOqOOOeQpOOOvO!bO'#CaOOOP'#Cx'#CxQVOqOOO!OQpO'#CfO!WQpO'#ClO!]QpO'#CrO!bQpO'#CsOOQO'#Cv'#CvQ!gQpOOQ!lQpOOQ!qQpOOOOOV,58{,58{O!vOpO,58{OOOP-E6v-E6vO!{QpO,59QO#TQpO,59QOOQO,59W,59WO#YQpO,59^OOQO,59_,59_O#_QpOOO#_QpOOO#gQpOOOOOV1G.g1G.gO#oQpO'#CyO#tQpO1G.lOOQO1G.l1G.lO#|QpO1G.lOOQO1G.x1G.xO$UO`O'#DUO$ZOWO'#DUOOQO'#Co'#CoQOQpOOOOQO'#Cu'#CuO$`OtO'#CwO$qOrO'#CwOOQO,59e,59eOOQO-E6w-E6wOOQO7+$W7+$WO%SQpO7+$WO%[QpO7+$WOOOO'#Cp'#CpO%aOpO,59pOOOO'#Cq'#CqO%fOpO,59pOOOS'#Cz'#CzO%kOtO,59cOOQO,59c,59cOOOQ'#C{'#C{O%|OrO,59cO&_QpO<<GrOOQO<<Gr<<GrOOQO1G/[1G/[OOOS-E6x-E6xOOQO1G.}1G.}OOOQ-E6y-E6yOOQOAN=^AN=^",stateData:"&d~OvOS~OPROSQOVROWRO~OZTO[XO^VOaUOhWO~OR]OU^O~O[`O^aO~O[bO~O[cO~O[dO~ObeO~ObfO~ObgO~ORhO~O]kOwiO~O[lO~O_mO~OynOzoO~OysOztO~O[uO~O]wOwiO~O_yOwiO~OtzO~Os|O~OSQOV!OOW!OOr!OOy!QO~OSQOV!ROW!ROq!ROz!QO~O_!TOwiO~O]!UO~Oy!VO~Oz!VO~OSQOV!OOW!OOr!OOy!XO~OSQOV!ROW!ROq!ROz!XO~O]!ZO~O",goto:"#dyPPPPPzPPPP!WPPPPP!WPP!Z!^!a!d!dP!g!j!m!p!v#Q#WPPPPPPPP#^SROSS!Os!PT!Rt!SRYPRqeR{nR}oRZPRqfR[PRqgQSOR_SQj`SvjxRxlQ!PsR!W!PQ!StR!Y!SQpeRrf",nodeNames:"⚠ Text Content }} {{ Interpolation InterpolationContent Entity InvalidEntity Attribute BoundAttributeName [ Identifier ] ( ) ReferenceName # Is ExpressionAttributeValue AttributeInterpolation AttributeInterpolation EventName DirectiveName * StatementAttributeValue AttributeName AttributeValue",maxTerm:42,nodeProps:[["openedBy",3,"{{",15,"("],["closedBy",4,"}}",14,")"],["isolate",-4,5,19,25,27,""]],skippedNodes:[0],repeatNodeCount:4,tokenData:"0r~RyOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mqr#rrs%jst&Qtv#rvw&hwx)zxy*byz*xz{+`{}#r}!O+v!O!P-]!P!Q#r!Q![+v![!]+v!]!_#r!_!`-s!`!c#r!c!}+v!}#O.Z#O#P#r#P#Q.q#Q#R#r#R#S+v#S#T#r#T#o+v#o#p/X#p#q#r#q#r0Z#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vQ#wTUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rQ$ZSO#q#r#r;'S#r;'S;=`$g<%lO#rQ$jP;=`<%l#rR$t[UQvPOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mq#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR%qTyPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&XTaPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&oXUQWPOp'[pq#rq!]'[!]!^#r!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R'aXUQOp'[pq#rq!]'[!]!^'|!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R(TTVPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR(gXOp'[pq#rq!]'[!]!^'|!^#q'[#q#r)S#r;'S'[;'S;=`)t<%lO'[P)VUOp)Sq!])S!]!^)i!^;'S)S;'S;=`)n<%lO)SP)nOVPP)qP;=`<%l)SR)wP;=`<%l'[R*RTzPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR*iT^PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+PT_PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+gThPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+}b[PUQO}#r}!O+v!O!Q#r!Q![+v![!]+v!]!c#r!c!}+v!}#R#r#R#S+v#S#T#r#T#o+v#o#q#r#q#r$W#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vR-YP;=`<%l+vR-dTwPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR-zTUQbPO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.bTZPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.xT]PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/^VUQO#o#r#o#p/s#p#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/zTSPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#r~0^TO#q#r#q#r0m#r;'S#r;'S;=`$g<%lO#r~0rOR~",tokenizers:[d,W,C,T,f,0,1],topRules:{Content:[0,2],Attribute:[1,9]},tokenPrec:0}),V=i.parser.configure({top:"SingleExpression"}),Q=A.configure({props:[R({Text:r.content,Is:r.definitionOperator,AttributeName:r.attributeName,"AttributeValue ExpressionAttributeValue StatementAttributeValue":r.attributeValue,Entity:r.character,InvalidEntity:r.invalid,"BoundAttributeName/Identifier":r.attributeName,"EventName/Identifier":r.special(r.attributeName),"ReferenceName/Identifier":r.variableName,"DirectiveName/Identifier":r.keyword,"{{ }}":r.brace,"( )":r.paren,"[ ]":r.bracket,"# '*'":r.punctuation})]}),o={parser:V},w={parser:i.parser},U=Q.configure({wrap:l((O,e)=>O.name=="InterpolationContent"?o:null)}),y=Q.configure({wrap:l((O,e)=>{var a;return O.name=="InterpolationContent"?o:O.name!="AttributeInterpolation"?null:((a=O.node.parent)===null||a===void 0?void 0:a.name)=="StatementAttributeValue"?w:o}),top:"Attribute"}),E={parser:U},N={parser:y},s=g();function S(O){return O.configure({wrap:l(z)},"angular")}const k=S(s.language);function z(O,e){switch(O.name){case"Attribute":return/^[*#(\[]|\{\{/.test(e.read(O.from,O.to))?N:null;case"Text":return E}return null}function G(O={}){let e=s;if(O.base){if(O.base.language.name!="html"||!(O.base.language instanceof q))throw new RangeError("The base option must be the result of calling html(...)");e=O.base}return new P(e.language==s.language?k:S(e.language),[e.support,e.language.data.of({closeBrackets:{brackets:["[","{",'"']},indentOnInput:/^\s*[\}\]]$/})])}export{G as angular,k as angularLanguage};
import{b as q,d as P,q as g,r as l,L as c,u as i,s as R,t as r,E as p}from"./index-BgJuLk5j.js";const b=1,$=33,m=34,v=35,x=36,d=new p(O=>{let e=O.pos;for(;;){if(O.next==10){O.advance();break}else if(O.next==123&&O.peek(1)==123||O.next<0)break;O.advance()}O.pos>e&&O.acceptToken(b)});function n(O,e,a){return new p(t=>{let u=t.pos;for(;t.next!=O&&t.next>=0&&(a||t.next!=38&&(t.next!=123||t.peek(1)!=123));)t.advance();t.pos>u&&t.acceptToken(e)})}const W=n(39,$,!1),C=n(34,m,!1),T=n(39,v,!0),f=n(34,x,!0),A=c.deserialize({version:14,states:"(jOVOqOOOeQpOOOvO!bO'#CaOOOP'#Cx'#CxQVOqOOO!OQpO'#CfO!WQpO'#ClO!]QpO'#CrO!bQpO'#CsOOQO'#Cv'#CvQ!gQpOOQ!lQpOOQ!qQpOOOOOV,58{,58{O!vOpO,58{OOOP-E6v-E6vO!{QpO,59QO#TQpO,59QOOQO,59W,59WO#YQpO,59^OOQO,59_,59_O#_QpOOO#_QpOOO#gQpOOOOOV1G.g1G.gO#oQpO'#CyO#tQpO1G.lOOQO1G.l1G.lO#|QpO1G.lOOQO1G.x1G.xO$UO`O'#DUO$ZOWO'#DUOOQO'#Co'#CoQOQpOOOOQO'#Cu'#CuO$`OtO'#CwO$qOrO'#CwOOQO,59e,59eOOQO-E6w-E6wOOQO7+$W7+$WO%SQpO7+$WO%[QpO7+$WOOOO'#Cp'#CpO%aOpO,59pOOOO'#Cq'#CqO%fOpO,59pOOOS'#Cz'#CzO%kOtO,59cOOQO,59c,59cOOOQ'#C{'#C{O%|OrO,59cO&_QpO<<GrOOQO<<Gr<<GrOOQO1G/[1G/[OOOS-E6x-E6xOOQO1G.}1G.}OOOQ-E6y-E6yOOQOAN=^AN=^",stateData:"&d~OvOS~OPROSQOVROWRO~OZTO[XO^VOaUOhWO~OR]OU^O~O[`O^aO~O[bO~O[cO~O[dO~ObeO~ObfO~ObgO~ORhO~O]kOwiO~O[lO~O_mO~OynOzoO~OysOztO~O[uO~O]wOwiO~O_yOwiO~OtzO~Os|O~OSQOV!OOW!OOr!OOy!QO~OSQOV!ROW!ROq!ROz!QO~O_!TOwiO~O]!UO~Oy!VO~Oz!VO~OSQOV!OOW!OOr!OOy!XO~OSQOV!ROW!ROq!ROz!XO~O]!ZO~O",goto:"#dyPPPPPzPPPP!WPPPPP!WPP!Z!^!a!d!dP!g!j!m!p!v#Q#WPPPPPPPP#^SROSS!Os!PT!Rt!SRYPRqeR{nR}oRZPRqfR[PRqgQSOR_SQj`SvjxRxlQ!PsR!W!PQ!StR!Y!SQpeRrf",nodeNames:"⚠ Text Content }} {{ Interpolation InterpolationContent Entity InvalidEntity Attribute BoundAttributeName [ Identifier ] ( ) ReferenceName # Is ExpressionAttributeValue AttributeInterpolation AttributeInterpolation EventName DirectiveName * StatementAttributeValue AttributeName AttributeValue",maxTerm:42,nodeProps:[["openedBy",3,"{{",15,"("],["closedBy",4,"}}",14,")"],["isolate",-4,5,19,25,27,""]],skippedNodes:[0],repeatNodeCount:4,tokenData:"0r~RyOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mqr#rrs%jst&Qtv#rvw&hwx)zxy*byz*xz{+`{}#r}!O+v!O!P-]!P!Q#r!Q![+v![!]+v!]!_#r!_!`-s!`!c#r!c!}+v!}#O.Z#O#P#r#P#Q.q#Q#R#r#R#S+v#S#T#r#T#o+v#o#p/X#p#q#r#q#r0Z#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vQ#wTUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rQ$ZSO#q#r#r;'S#r;'S;=`$g<%lO#rQ$jP;=`<%l#rR$t[UQvPOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mq#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR%qTyPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&XTaPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&oXUQWPOp'[pq#rq!]'[!]!^#r!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R'aXUQOp'[pq#rq!]'[!]!^'|!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R(TTVPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR(gXOp'[pq#rq!]'[!]!^'|!^#q'[#q#r)S#r;'S'[;'S;=`)t<%lO'[P)VUOp)Sq!])S!]!^)i!^;'S)S;'S;=`)n<%lO)SP)nOVPP)qP;=`<%l)SR)wP;=`<%l'[R*RTzPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR*iT^PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+PT_PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+gThPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+}b[PUQO}#r}!O+v!O!Q#r!Q![+v![!]+v!]!c#r!c!}+v!}#R#r#R#S+v#S#T#r#T#o+v#o#q#r#q#r$W#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vR-YP;=`<%l+vR-dTwPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR-zTUQbPO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.bTZPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.xT]PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/^VUQO#o#r#o#p/s#p#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/zTSPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#r~0^TO#q#r#q#r0m#r;'S#r;'S;=`$g<%lO#r~0rOR~",tokenizers:[d,W,C,T,f,0,1],topRules:{Content:[0,2],Attribute:[1,9]},tokenPrec:0}),V=i.parser.configure({top:"SingleExpression"}),Q=A.configure({props:[R({Text:r.content,Is:r.definitionOperator,AttributeName:r.attributeName,"AttributeValue ExpressionAttributeValue StatementAttributeValue":r.attributeValue,Entity:r.character,InvalidEntity:r.invalid,"BoundAttributeName/Identifier":r.attributeName,"EventName/Identifier":r.special(r.attributeName),"ReferenceName/Identifier":r.variableName,"DirectiveName/Identifier":r.keyword,"{{ }}":r.brace,"( )":r.paren,"[ ]":r.bracket,"# '*'":r.punctuation})]}),o={parser:V},w={parser:i.parser},U=Q.configure({wrap:l((O,e)=>O.name=="InterpolationContent"?o:null)}),y=Q.configure({wrap:l((O,e)=>{var a;return O.name=="InterpolationContent"?o:O.name!="AttributeInterpolation"?null:((a=O.node.parent)===null||a===void 0?void 0:a.name)=="StatementAttributeValue"?w:o}),top:"Attribute"}),E={parser:U},N={parser:y},s=g();function S(O){return O.configure({wrap:l(z)},"angular")}const k=S(s.language);function z(O,e){switch(O.name){case"Attribute":return/^[*#(\[]|\{\{/.test(e.read(O.from,O.to))?N:null;case"Text":return E}return null}function G(O={}){let e=s;if(O.base){if(O.base.language.name!="html"||!(O.base.language instanceof q))throw new RangeError("The base option must be the result of calling html(...)");e=O.base}return new P(e.language==s.language?k:S(e.language),[e.support,e.language.data.of({closeBrackets:{brackets:["[","{",'"']},indentOnInput:/^\s*[\}\]]$/})])}export{G as angular,k as angularLanguage};

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI</title>
<script type="module" crossorigin src="/assets/index-DgMg835f.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-jd0TJS39.css">
<script type="module" crossorigin src="/assets/index-BgJuLk5j.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BRCY9Cdd.css">
</head>
<body>
<div id="app"></div>

View File

@ -1,5 +1,14 @@
<template>
<div :id="containerId" ref="container" @click="handleContainerClick"></div>
<div :id="containerId" ref="container" @click="handleContainerClick">
<!-- Container for dynamically injected HTML -->
<div ref="htmlContentContainer"></div>
<!-- Conditionally render the Vue ImageAlbumViewer component -->
<ImageAlbumViewer
v-if="showAlbumViewer"
:images="albumImages"
:key="`album-${instanceId}`"
/>
</div>
</template>
<script>
@ -9,6 +18,9 @@ import ImageAlbumViewer from './ImageAlbumViewer.vue'; // Adjust path if needed
export default {
name: 'DynamicUIRenderer',
components: {
ImageAlbumViewer, // Register the child component
},
props: {
ui: {
type: String,
@ -18,28 +30,36 @@ export default {
type: String,
required: true
}
// Removed discussion_id prop, as it will be in the HTML data attribute
},
data() {
return {
containerId: `dynamic-ui-${this.instanceId}`,
albumImages: [], // Store images for the album viewer
albumViewerInstance: null, // To keep track of the mounted album component
injectedStyleElements: [], // To keep track of injected styles for cleanup
// containerId is computed, moved to computed section
albumImages: [], // Reactive state for album images
showAlbumViewer: false, // Reactive state to control v-if
injectedStyleElements: [], // Keep track of injected styles
};
},
computed: {
...mapState(['clientId']), // Map client_id from Vuex store
// Compute containerId based on instanceId prop
containerId() {
return `dynamic-ui-${this.instanceId}`;
},
},
watch: {
ui: {
immediate: true,
immediate: true, // Run on component mount
handler(newValue, oldValue) {
// Only re-render if the UI actually changed
if (newValue !== oldValue || this.$refs.container?.innerHTML === '') {
// Only re-render if the UI actually changed or if the container is empty
// Use $refs here as they are available after the initial render (due to immediate: true)
const htmlContainer = this.$refs.htmlContentContainer;
if (newValue !== oldValue || !htmlContainer || htmlContainer.innerHTML === '') {
console.log(`UI prop changed for instance ${this.instanceId}`);
// Cleanup must happen *before* rendering new content
this.cleanupDynamicContent();
// Use $nextTick to ensure DOM is updated after cleanup before rendering
this.$nextTick(() => {
this.cleanupDynamicContent(); // Clean up previous dynamic elements before rendering new
this.renderContent();
});
}
@ -48,36 +68,37 @@ export default {
},
beforeUnmount() {
this.cleanupDynamicContent(); // Ensure cleanup when component is destroyed
// Remove the main click listener
this.$refs.container?.removeEventListener('click', this.handleContainerClick);
// No need to remove listener manually, Vue handles it on the root element
},
methods: {
renderContent() {
console.log(`Rendering content for instance ${this.instanceId}...`);
const container = this.$refs.container;
if (!container) {
console.error(`Container ref not found for instance ${this.instanceId}`);
const targetContainer = this.$refs.htmlContentContainer; // Access ref via this.$refs
if (!targetContainer) {
// This check might be less likely to fail here compared to setup,
// as refs are generally available in methods called after mount.
console.error(`HTML content container ref not found for instance ${this.instanceId}`);
return;
}
// Clear previous content safely
container.innerHTML = '';
this.albumImages = []; // Reset album images
// Clear previous content (already done in cleanup, but good practice)
targetContainer.innerHTML = '';
let imagesForAlbum = []; // Local variable for processing
this.showAlbumViewer = false; // Reset viewer flag
const parser = new DOMParser();
const doc = parser.parseFromString(this.ui, 'text/html');
// Use this.ui to access the prop
const doc = parser.parseFromString(this.ui || '', 'text/html');
// --- 1. Inject Scoped CSS ---
const styles = doc.head.getElementsByTagName('style'); // Check head first
const styles = doc.head.getElementsByTagName('style');
Array.from(styles).forEach(style => this.injectScopedCss(style.textContent));
const bodyStyles = doc.body.getElementsByTagName('style'); // Also check body
const bodyStyles = doc.body.getElementsByTagName('style');
Array.from(bodyStyles).forEach(style => this.injectScopedCss(style.textContent));
// --- 2. Process HTML Body ---
const processedNodes = [];
let albumPlaceholderNeeded = false;
// Convert NodeList to Array for easier manipulation
const nodesToProcess = Array.from(doc.body.childNodes);
nodesToProcess.forEach(node => {
@ -86,125 +107,70 @@ export default {
if (node.tagName === 'IMG' && node.classList.contains('album')) {
const src = node.getAttribute('src');
if (src) {
this.albumImages.push(src);
imagesForAlbum.push(src); // Add to local list
albumPlaceholderNeeded = true;
}
// Don't add the original img.album node directly
return; // Skip appending this node
}
// --- Special Handling: Clickable Image POST ---
// Use a specific class like 'clickable-post' and data attributes for flexibility
// Example HTML: <img src="path/img.jpg" class="clickable-post" data-endpoint="/post_to_personality" data-payload-key="img_path">
if (node.tagName === 'IMG' && node.classList.contains('clickable-post')) {
// Add necessary data attributes if they were in onclick="post_to_personality"
// This part is tricky if relying solely on onclick. Best practice is to use data attributes.
// Assuming HTML is updated to use data attributes as shown above.
if (!node.dataset.endpoint) node.dataset.endpoint = '/post_to_personality'; // Default endpoint if not set
if (!node.dataset.payloadKey) node.dataset.payloadKey = 'img_path'; // Default payload key
// The click handling will be done via event delegation (handleContainerClick)
if (!node.dataset.endpoint) node.dataset.endpoint = '/post_to_personality';
if (!node.dataset.payloadKey) node.dataset.payloadKey = 'img_path';
}
// --- Special Handling: Open Folder Link ---
// Example HTML: <a href="#" class="open-folder" data-discussion-id="123">Open Folder</a>
if (node.tagName === 'A' && node.classList.contains('open-folder')) {
// Ensure it has the data-discussion-id attribute.
// Click handling via event delegation.
node.setAttribute('href', '#'); // Prevent navigation
}
}
// Add the node (original or potentially modified) to our list
processedNodes.push(node);
});
// --- 3. Add Album Placeholder if needed ---
if (albumPlaceholderNeeded && this.albumImages.length > 0) {
const albumPlaceholder = document.createElement('div');
// Give it a unique ID for mounting the Vue component
albumPlaceholder.id = `album-placeholder-${this.instanceId}`;
container.appendChild(albumPlaceholder); // Add placeholder first
}
// --- 4. Append Processed Standard HTML Nodes ---
// --- 3. Append Processed Standard HTML Nodes ---
processedNodes.forEach(node => {
// Need to import the node into the current document context before appending
container.appendChild(document.adoptNode(node));
targetContainer.appendChild(document.importNode(node, true));
});
// --- 5. Mount Album Viewer Component ---
if (albumPlaceholderNeeded && this.albumImages.length > 0) {
this.mountAlbumViewer();
// --- 4. Update State for Album Viewer ---
if (albumPlaceholderNeeded && imagesForAlbum.length > 0) {
this.albumImages = imagesForAlbum; // Update reactive data property
this.showAlbumViewer = true; // Update reactive data property
console.log(`Scheduled ImageAlbumViewer rendering for instance ${this.instanceId} with ${imagesForAlbum.length} images.`);
} else {
this.albumImages = [];
this.showAlbumViewer = false;
}
// --- 6. Handle Original Scripts (Use with caution!) ---
// Executing arbitrary scripts can be a security risk and might interfere
// with Vue's reactivity or the event delegation. It's often better to
// handle interactions via the defined patterns (classes/data attributes).
// If absolutely necessary:
// --- 5. Handle Original Scripts (Still use with caution!) ---
// const scripts = doc.body.getElementsByTagName('script');
// Array.from(scripts).forEach(script => {
// try {
// const newScript = document.createElement('script');
// newScript.textContent = script.textContent; // Might need scoping adjustments
// container.appendChild(newScript); // Scripts added this way often don't execute reliably or might execute in global scope
// // For reliable execution, you might need Function constructor or eval, which is risky:
// // try { new Function(script.textContent).call(window); } catch (e) { console.error("Error executing script:", e); }
// } catch (e) {
// console.error("Error processing script tag:", e)
// }
// });
// Array.from(scripts).forEach(script => { /* ... */ });
console.log(`Finished rendering for instance ${this.instanceId}.`);
},
injectScopedCss(css) {
const scopedCss = this.scopeCSS(css);
const scopedCss = this.scopeCSS(css); // Call helper method
const styleElement = document.createElement('style');
styleElement.textContent = scopedCss;
document.head.appendChild(styleElement);
this.injectedStyleElements.push(styleElement); // Keep track for cleanup
this.injectedStyleElements.push(styleElement); // Store ref in data property
},
scopeCSS(css) {
// Basic scoping: prepend container ID to selectors not already scoped deeper
// This regex is basic and might need refinement for complex CSS.
// It tries to target selectors at the start of a rule block.
// Use computed containerId
return css.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, suffix) => {
// Avoid scoping pseudo-elements like ::before directly on the ID, scope the base selector instead
// Avoid scoping keyframes, font-face etc.
selector = selector.trim();
if (selector.startsWith('@') || selector.startsWith(':') || selector.includes('#') || selector.includes('[')) {
// Don't scope if it starts with @ (keyframes, media), is pseudo-element/class only, or already has an ID/attribute selector
return match;
}
// Prepend the ID, handling multiple selectors separated by commas
const scopedSelector = selector.split(',')
.map(part => `#${this.containerId} ${part.trim()}`)
.map(part => `#${this.containerId} ${part.trim()}`) // Scope relative to the main container ID
.join(', ');
return `${scopedSelector}${suffix}`;
});
},
mountAlbumViewer() {
// Ensure placeholder exists
const placeholder = document.getElementById(`album-placeholder-${this.instanceId}`);
if (!placeholder) {
console.error("Album placeholder not found!");
return;
}
// Create and mount the ImageAlbumViewer component
const AlbumViewerComponent = Vue.extend(ImageAlbumViewer);
this.albumViewerInstance = new AlbumViewerComponent({
propsData: {
images: this.albumImages
}
});
this.albumViewerInstance.$mount(placeholder); // Mount it onto the placeholder element
console.log(`Mounted ImageAlbumViewer for instance ${this.instanceId}`);
},
handleContainerClick(event) {
const target = event.target;
@ -213,21 +179,15 @@ export default {
if (clickablePost && clickablePost.dataset.endpoint) {
event.preventDefault();
const endpoint = clickablePost.dataset.endpoint;
const payloadKey = clickablePost.dataset.payloadKey || 'img_path'; // Default key
const payloadKey = clickablePost.dataset.payloadKey || 'img_path';
const src = clickablePost.getAttribute('src');
const payload = { [payloadKey]: src };
console.log(`Posting to ${endpoint} with payload:`, payload);
axios.post(endpoint, payload)
.then(response => {
console.log('Post successful:', response.data);
// Optionally handle success (e.g., show message, update UI)
})
.catch(error => {
console.error(`Error posting to ${endpoint}:`, error);
// Optionally handle error
});
return; // Stop further processing if handled
.then(response => console.log('Post successful:', response.data))
.catch(error => console.error(`Error posting to ${endpoint}:`, error));
return;
}
// --- Handle Open Folder Link ---
@ -235,6 +195,7 @@ export default {
if (openFolderLink && openFolderLink.dataset.discussionId) {
event.preventDefault();
const discussionId = openFolderLink.dataset.discussionId;
// Access clientId from computed properties (mapped from Vuex)
if (!this.clientId) {
console.error("Client ID not found in Vuex store.");
alert("Error: Client information is missing.");
@ -243,60 +204,38 @@ export default {
console.log(`Posting to /open_discussion_folder with client_id: ${this.clientId}, discussion_id: ${discussionId}`);
axios.post('/open_discussion_folder', { client_id: this.clientId, discussion_id: discussionId })
.then(response => {
console.log('Open folder request successful:', response.data);
// Handle success (maybe response indicates folder opened)
})
.catch(error => {
console.error('Error opening folder:', error);
// Handle error (e.g., show error message)
});
return; // Stop further processing
.then(response => console.log('Open folder request successful:', response.data))
.catch(error => console.error('Error opening folder:', error));
return;
}
// Add more delegated event handlers here if needed...
},
cleanupDynamicContent() {
console.log(`Cleaning up dynamic content for instance ${this.instanceId}`);
// Unmount and destroy the album viewer Vue instance if it exists
if (this.albumViewerInstance) {
try {
this.albumViewerInstance.$destroy();
// Remove the placeholder or container element if needed, check if $el exists first
if (this.albumViewerInstance.$el && this.albumViewerInstance.$el.parentNode) {
this.albumViewerInstance.$el.parentNode.removeChild(this.albumViewerInstance.$el);
}
} catch (e) {
console.error("Error destroying album viewer instance:", e);
}
this.albumViewerInstance = null;
}
// Reset reactive data - this hides the ImageAlbumViewer via v-if
this.showAlbumViewer = false;
this.albumImages = [];
// Remove injected stylesheets
this.injectedStyleElements.forEach(styleElement => {
if (styleElement.parentNode) {
if (styleElement && styleElement.parentNode) {
styleElement.parentNode.removeChild(styleElement);
}
});
this.injectedStyleElements = [];
this.injectedStyleElements = []; // Clear the tracking array
// Clear container content (already done at the start of renderContent, but good practice)
const container = this.$refs.container;
if (container) {
// container.innerHTML = ''; // Be careful if renderContent is called immediately after
// Clear dynamically injected HTML content
const htmlContainer = this.$refs.htmlContentContainer;
if (htmlContainer) {
htmlContainer.innerHTML = '';
}
console.log(`Finished cleanup for instance ${this.instanceId}.`);
}
}
};
</script>
<style scoped>
/* Add any styles specific to the container itself, if needed */
/* For example: */
/* div[id^="dynamic-ui-"] {
border: 1px dashed lightgray;
padding: 5px;
margin-bottom: 10px;
} */
/* Add any styles specific to the main container itself, if needed */
</style>

View File

@ -433,7 +433,7 @@ export default defineComponent({
sender: msgObj.sender, message_type: msgObj.message_type, sender_type: msgObj.sender_type, content: msgObj.content || (msgObj.sender_type === this.senderTypes.SENDER_TYPES_AI ? "" : ""),
id: msgObj.id, discussion_id: msgObj.discussion_id, parent_id: msgObj.parent_id, binding: msgObj.binding, model: msgObj.model, personality: msgObj.personality,
created_at: msgObj.created_at, finished_generating_at: msgObj.finished_generating_at, rank: msgObj.rank || 0, ui: msgObj.ui, steps: [], parameters: msgObj.parameters,
metadata: msgObj.metadata || [], open: msgObj.open, status_message: msgObj.sender_type === this.senderTypes.SENDER_TYPES_AI ? "Generating..." : "Sent",
nb_tokens: msgObj.nb_tokens?msgObj.nb_tokens:0,metadata: msgObj.metadata || [], open: msgObj.open, status_message: msgObj.sender_type === this.senderTypes.SENDER_TYPES_AI ? "Generating..." : "Sent",
};
this.discussionArr.push(newMessage);
if (this.discussionArr.length === 2 && (!this.currentDiscussion.title || this.currentDiscussion.title === "untitled") && newMessage.sender_type === this.senderTypes.SENDER_TYPES_USER) {