diff --git a/Examples/Asteroids/Asteroids.wls b/Examples/Asteroids/Asteroids.wls index 0e72298..59c1937 100644 --- a/Examples/Asteroids/Asteroids.wls +++ b/Examples/Asteroids/Asteroids.wls @@ -55,6 +55,9 @@ WLJS`PM`Repositories[{ Github -> "https://github.com/JerryI/wljs-inputs" -> "dev" }] +$DefaultSerializer = ExportByteArray[#, "ExpressionJSON"]& + + (* import libs data *) Map[Function[path, Block[{System`$RemotePackageDirectory = FileNameJoin[{"wljs_packages", FileNameSplit[path] // First}]}, diff --git a/Examples/Balls/Balls.wls b/Examples/Balls/Balls.wls index 0e72298..59c1937 100644 --- a/Examples/Balls/Balls.wls +++ b/Examples/Balls/Balls.wls @@ -55,6 +55,9 @@ WLJS`PM`Repositories[{ Github -> "https://github.com/JerryI/wljs-inputs" -> "dev" }] +$DefaultSerializer = ExportByteArray[#, "ExpressionJSON"]& + + (* import libs data *) Map[Function[path, Block[{System`$RemotePackageDirectory = FileNameJoin[{"wljs_packages", FileNameSplit[path] // First}]}, diff --git a/Examples/WLJSBasicDyn/WLJSBasicDyn.wls b/Examples/WLJSBasicDyn/WLJSBasicDyn.wls index fad09bf..445b324 100755 --- a/Examples/WLJSBasicDyn/WLJSBasicDyn.wls +++ b/Examples/WLJSBasicDyn/WLJSBasicDyn.wls @@ -61,6 +61,9 @@ WLJS`PM`Repositories[{ Github -> "https://github.com/JerryI/wljs-inputs" -> "dev" }] +$DefaultSerializer = ExportByteArray[#, "ExpressionJSON"]& + + (* import libs data *) Map[Function[path, Block[{System`$RemotePackageDirectory = FileNameJoin[{"wljs_packages", FileNameSplit[path] // First}]}, diff --git a/Examples/WebUISidebar/Server.wls b/Examples/WebUISidebar/Server.wls index 2befe87..830eb08 100644 --- a/Examples/WebUISidebar/Server.wls +++ b/Examples/WebUISidebar/Server.wls @@ -55,6 +55,9 @@ Get[FileNameJoin[{Directory[]//ParentDirectory//ParentDirectory,"Kernel", "WebUI < "https://github.com/JerryI/wljs-interpreter" -> "dev" }] diff --git a/Examples/WebUITodo/Server.wls b/Examples/WebUITodo/Server.wls index 0cc24a3..e1dee67 100644 --- a/Examples/WebUITodo/Server.wls +++ b/Examples/WebUITodo/Server.wls @@ -19,7 +19,7 @@ PacletRepositories[{ RandomWord[]; -$DefaultSerializer = ExportByteArray[#, "ExpressionJSON"]& + (* Here you can configure *) ENV = <| @@ -57,6 +57,9 @@ Get[FileNameJoin[{Directory[]//ParentDirectory//ParentDirectory,"Kernel", "WebUI < "https://github.com/JerryI/wljs-interpreter" -> "dev" }] diff --git a/Kernel/WLX.wl b/Kernel/WLX.wl index 7099dad..e79fd6c 100644 --- a/Kernel/WLX.wl +++ b/Kernel/WLX.wl @@ -17,47 +17,57 @@ ProcessString[pstr_String, OptionsPattern[]] := Module[{str, open, close, singul (* three types of HTML tags *) {open, close, singular} = parseTags[str]; - (* parse all tokens *) - tokens = SortBy[ - Join[tokenizer[#, 1, str] & /@ open, tokenizer[#, 0, str] & /@ singular, - tokenizer[#, -1, str] & /@ close], #["pos"][[1]] &]; + If[Length[open] > 0 || Length[close] > 0 || Length[singular] > 0, + (* parse all tokens *) + tokens = SortBy[ + Join[tokenizer[#, 1, str] & /@ open, tokenizer[#, 0, str] & /@ singular, + tokenizer[#, -1, str] & /@ close], #["pos"][[1]] &]; - fetchInnerText[tokens, str, OptionValue["Trimmer"], commentsList]; - tokens = Join[tokens, fetchInnerText[tokens, str, OptionValue["Trimmer"], commentsList]]; - tokens = SortBy[tokens, #["pos"][[1]] &]; - + fetchInnerText[tokens, str, OptionValue["Trimmer"], commentsList]; + tokens = Join[tokens, fetchInnerText[tokens, str, OptionValue["Trimmer"], commentsList]]; + tokens = SortBy[tokens, #["pos"][[1]] &]; - (* build AST tree *) - tree = ast[tokens, str]; + - (* generate rules of string replacement *) - placeholders = {generatePlaceholders[tree]}//Flatten; + (* build AST tree *) + tree = ast[tokens, str]; + If[FailureQ[tree], Return[$Failed] ]; + (* generate rules of string replacement *) + placeholders = {generatePlaceholders[tree]}//Flatten; - (* generate sanitized list of expressions *) - pureWLCode = ToExpression[#, InputForm, Hold2] & /@ SplitExpression[ - With[{rules = Values[placeholders]}, - StringReplacePart[str, rules[[All, 1]], rules[[All, 2]]] - ] - ]; - (* construct WL expression from WLX *) - map = (ToExpression[#[[2, 1]]] -> constructWL[#[[1]]]) & /@ placeholders; - map = With[{expr = #[[2]]}, #[[1]]->Hold2[expr]] & /@ map; + (* generate sanitized list of expressions *) + pureWLCode = ToExpression[#, InputForm, Hold2] & /@ SplitExpression[ + With[{rules = Values[placeholders]}, + StringReplacePart[str, rules[[All, 1]], rules[[All, 2]]] + ] + ]; - (* restore dangerous functions *) - - map = map //. {FakeFlatten -> Flatten, StringRiffleFake -> StringRiffle, - StringJoinFake -> StringJoin, FakeBlock -> Block, FakeHold[x_] :> x, - ToStringFake -> ToStringRiffle - }; + (* construct WL expression from WLX *) + map = (ToExpression[#[[2, 1]]] -> constructWL[#[[1]]]) & /@ placeholders; + map = With[{expr = #[[2]]}, #[[1]]->Hold2[expr]] & /@ map; - - (* hydrate with WLX the original code again *) + (* restore dangerous functions *) + + map = map //. {FakeFlatten -> Flatten, StringRiffleFake -> StringRiffle, + StringJoinFake -> StringJoin, FakeBlock -> Block, FakeHold[x_] :> x, + ToStringFake -> ToStringRiffle + }; - pureWLCode = pureWLCode /. map /. escapedCode; + + (* hydrate with WLX the original code again *) + pureWLCode = pureWLCode /. map /. escapedCode; + , + (* normal WL code with no tags*) + pureWLCode = ToExpression[#, InputForm, Hold2] & /@ SplitExpression[ + pstr + ]; + ]; + + (* EXIT::1 *) @@ -203,9 +213,15 @@ TokenGroup[{Token[A___], TokenGroup[B_], n___}] := TokenGroup[Flatten[{Token[A], (* i :> WL *) +ast::nonballanced = "Non ballanced: ``"; + ast[tokens_List, original_String] := Module[{level = 0, index = 1, bra, depth, head, exp = {}, last = {}, group, tail}, - + + If[AnyTrue[tokens, FailureQ], + Return[$Failed]; + ]; + (* bra stands for the level of hierarch. *) bra = 0; depth = 0; If[Length[tokens] == 0, Return[Null]]; @@ -215,7 +231,11 @@ ast[tokens_List, original_String] := If[Length[tokens] > 1, (* process the rest independently *) - Return[TokenGroup[Flatten[{Token["Singular", head], ast[Drop[tokens, 1], original]}]]], + With[{processed = ast[Drop[tokens, 1], original]}, + If[FailureQ[processed], Return[processed] ]; + Return[TokenGroup[Flatten[{Token["Singular", head], processed}] ] ] + ] + , (* return that one *) Return[Token["Singular", head]]]; @@ -237,6 +257,7 @@ ast[tokens_List, original_String] := (* extract the entire expression undeneath *) exp = Take[tokens, i]; last = Drop[tokens, i]; + tail = t; Break[]; @@ -257,17 +278,36 @@ ast[tokens_List, original_String] := exp = If[depth > 0, (* if it contains subexpressions *) + If[Length[exp] == 0, + Message[ast::nonballanced, StringTemplate["tag `` at ``"][head["head"], head["pos"] ] ]; + Return[$Failed]; + ]; + + + Token["Nested", head, tail, - ast[Drop[Drop[exp, 1], -1], original]] + ast[Drop[Drop[exp, 1], -1], original] + ] , (* if not *) - Token["Normal", head, tail] + + If[!AssociationQ[tail], + Message[ast::nonballanced, StringTemplate["tag `` at `` probably is not closed"][head["head"], head["pos"] ] ]; + Return[$Failed]; + ]; + + Token["Normal", head, tail] ]; (* parse the rest *) If[Length[last] > 0, - TokenGroup[Flatten[{exp, ast[last, original]}]] + With[{processed = ast[last, original]}, + If[FailureQ[processed], Return[processed] ]; + + TokenGroup[Flatten[{exp, processed}] ] + ] + , exp ] diff --git a/PacletInfo.wl b/PacletInfo.wl index a1459d0..e89e893 100644 --- a/PacletInfo.wl +++ b/PacletInfo.wl @@ -7,7 +7,7 @@ PacletObject[ "Creator" -> "Kirill Vasin", "License" -> "GPL-3.0-only", "PublisherID" -> "JerryI", - "Version" -> "2.0.5", + "Version" -> "2.0.6", "WolframVersion" -> "13+", "Extensions" -> { {