6

Bug introduced with FormFunction and persisting through Cloud V1.48

CASE:4026150 confirmed


There are few problems when deploying simple FormFunctions: Wolfram Cloud deployment obstacles

E.g. this one will fail completely, (http response code 500)

CloudDeploy[ FormFunction[{{"x", "\[Rule]"} -> "Number"}, # &]]

this on the other hand works well:

CloudDeploy[ FormFunction[{
  {"x", "Kurt Gödel Paul Erdős \[CircleDot]"} ->  "Number"
}, # &]]

While I don't need \[Rule] I need at least -> or a placeholder indicating a problem.

I want to keep strings (no svg/png etc.)

I can replace \[Rule] with -> but I need this to work for \[RuleDelayed], \[Function] and who knows what else.

I can't mindlessly encode the string as ASCII because I will lose greek and other alphabets handling.

What can I do about this?

Kuba
  • 136,707
  • 13
  • 279
  • 740

1 Answers1

3

Didn't realize FormFunction wouldn't work if the label had a non-standard unicode character at all... that's really a pretty dumb bug (and it's definitely a bug).

Here's a way that leverages halirutan's work on building a regex for all web-displayable characters, but which instead only matches Mathematica-specific characters:

rangify[n_Integer] := 
  With[{result = 
     rangifyC[Boole[LetterQ[FromCharacterCode[#]] & /@ Range[n]]]}, 
   If[Length[result] > 0, Partition[result, 2], {}]];
rangifyC = 
  Compile[{{l, _Integer, 1}}, 
   Module[{pos = 1, current = 0, bag = Internal`Bag[Most[{0}]]}, 
    While[pos <= Length[l], current = l[[pos]];
     If[current == 1, Internal`StuffBag[bag, pos];];
     While[l[[pos]] == current, pos++;
      If[pos > Length[l], Break[]];];
     If[current == 1, Internal`StuffBag[bag, pos - 1]]];
    Internal`BagPart[bag, All]]];
toMRange[{n_, n_}] := FromCharacterCode[n];
toMRange[range_] := StringRiffle[FromCharacterCode /@ range, "-"];
toNotRegex[n_Integer] := 
  RegularExpression["[^" <> Map[toMRange, rangify[n]] <> "]"];

mregex =
  toNotRegex[2^16 - 1];

Then we just use this to escape all Mathematica characters:

safeFormFunctionSpec[
   fspec_
   ] :=
  fspec /. s_String :>
    StringReplace[s, 
     bad : mregex :> "\\[" <> CharacterName[bad] <> "]"];
safeFormFunction[fspec_, body_] :=

 FormFunction[safeFormFunctionSpec[fspec], body]

blah

then this works:

CloudDeploy[
 safeFormFunction[
  {
   {"x", "\[Rule]"} -> "Number",
   {"y", "\[WolframLanguageLogo]"} -> "Number",
   {"z", "α"} -> "Number",
   {"a", "♡"} -> "Number"
   },
  Identity
  ],
 "test_form",
 Permissions -> "Public"
 ]

One thing to note: Mathematica's implementation of HTML export is actually even worse than expected. It won't even allow you to use non-Western characters. This is a serious flaw. Try this:

CloudDeploy[
 safeFormFunction[
  {
   {"x", "\[Rule]"} -> "Number",
   {"y", "\[WolframLanguageLogo]"} -> "Number",
   {"z", "α"} -> "Number",
   {"a", "♡"} -> "Number",
   {"b", "사랑"} -> "Number"
   },
  Identity
  ],
 "test_form",
 Permissions -> "Public"
 ]

And you'll see that it quietly fails... really pretty lackluster performance on WRI's part here.

Original: Making characters display in FormPage

So the main issue here is that the font-faces where those characters are defined aren't loaded.

I had to handle this for a tutorial website I developed. If you look most of the way down on this page you'll see the classic "\[Wolf]" though. Took me about a day to figure out how to get it on there.

If we want to get this in the cloud we can use the fonts that I already deployed, linking them in a block immediately preceding the content. This causes for a minor blip before they actually load, but I don't think there's a better way with this stuff.

CloudDeploy[
 FormPage[
  {
   Style[
    "<style>
    @font-face {
        font-family: 'Mathematica';
        src: \
url('https://www.wolframcloud.com/objects/b3m2a1.testing/tutorial/\
theme/fonts/mathematica/Mathematica.eot');
        src: \
url('https://www.wolframcloud.com/objects/b3m2a1.testing/tutorial/\
theme/fonts/mathematica/Mathematica.eot?#iefix') \
format('embedded-opentype'),
         url('https://www.wolframcloud.com/objects/b3m2a1.testing/\
tutorial/theme/fonts/mathematica/Mathematica.woff') format('woff'),
             url('https://www.wolframcloud.com/objects/b3m2a1.testing/\
tutorial/theme/fonts/mathematica/Mathematica.ttf') \
format('truetype');
        font-weight: normal;
    }
    label { font-family: 'Mathematica'}
    </style>",
    "Text"
    ],
   {"x", "\[Rule]"} -> "Number",
   {"y", "\[WolframLanguageLogo]"} -> "Number"
   },
  # &
  ], 
 "test_form",
 Permissions -> "Public"
 ]

And you get the desired result:

blah

b3m2a1
  • 46,870
  • 3
  • 92
  • 239
  • I'm trying to put it in appearance rules for FormFunction but to no avail. My main use case is with FormFunction not a FormPage. – Kuba Mar 07 '18 at 09:26
  • @Kuba FormFunction should work the same. They both use FormObject to build the form. – b3m2a1 Mar 07 '18 at 16:06
  • Does it work the same? – Kuba Mar 07 '18 at 16:26
  • @Kuba didn't realize FormFunction did anything different. As long as you can inject that "<style>...</style>" block before your page you'll be fine. But give me a moment to try to make a workaround. I think this is also a bug as FormFunction didn't used to complain about things like this. – b3m2a1 Mar 07 '18 at 18:03
  • @Kuba I have a workaround that's a bit dissatisfying but valid – b3m2a1 Mar 07 '18 at 18:45