unisonweb/ui-core

Improve rendering of long string literals

Closed this issue ยท 2 comments

I think #73 fixes can be improved upon.

Since Unison supports multiline string literals, why don't we just convert string literals that:

  1. Are longer than certain length
    can be based on some analytics (if you have one), or just best case scenario where UI is most closely follows original design
  2. Contain line-break characters (\n)
    also can be constrained, like if there's more that 3 line-breaks present

And the nice thing about it (from quick look), is that i can all be solved on the client-side, without any changes on the back-end.

Let me know what you think, @hojberg

Example of potential check

in vanilla javascript

literal.length > 64 && literal.split('\n').length > 3

Real World Examples

Both versions of Unison code are totally valid from the compiler point of view, so Copy and Paste won't be an issue

Taken from #73 (comment)

certificates.ca.hueBridge : '{Exception} SignedCert
certificates.ca.hueBridge =
  do
    "-----BEGIN CERTIFICATE-----\nMIICMjCCAdigAwIBAgIUO7FSLbaxikuXAljzVaurLXWmFw4wCgYIKoZIzj0EAwIw\nOTELMAkGA1UEBhMCTkwxFDASBgNVBAoMC1BoaWxpcHMgSHVlMRQwEgYDVQQDDAty\nb290LWJyaWRnZTAiGA8yMDE3MDEwMTAwMDAwMFoYDzIwMzgwMTE5MDMxNDA3WjA5\nMQswCQYDVQQGEwJOTDEUMBIGA1UECgwLUGhpbGlwcyBIdWUxFDASBgNVBAMMC3Jv\nb3QtYnJpZGdlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjNw2tx2AplOf9x86\naTdvEcL1FU65QDxziKvBpW9XXSIcibAeQiKxegpq8Exbr9v6LBnYbna2VcaK0G22\njOKkTqOBuTCBtjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNV\nHQ4EFgQUZ2ONTFrDT6o8ItRnKfqWKnHFGmQwdAYDVR0jBG0wa4AUZ2ONTFrDT6o8\nItRnKfqWKnHFGmShPaQ7MDkxCzAJBgNVBAYTAk5MMRQwEgYDVQQKDAtQaGlsaXBz\nIEh1ZTEUMBIGA1UEAwwLcm9vdC1icmlkZ2WCFDuxUi22sYpLlwJY81Wrqy11phcO\nMAoGCCqGSM49BAMCA0gAMEUCIEBYYEOsa07TH7E5MJnGw557lVkORgit2Rm1h3B2\nsFgDAiEA1Fj/C3AN5psFMjo0//mrQebo0eKd3aWRx+pQY08mk48=\n-----END CERTIFICATE-----"
      |> Text.toUtf8
      |> decodeCert
      |> Either.toException
certificates.ca.hueBridge : '{Exception} SignedCert
certificates.ca.hueBridge =
  do
    """
    -----BEGIN CERTIFICATE-----
    MIICMjCCAdigAwIBAgIUO7FSLbaxikuXAljzVaurLXWmFw4wCgYIKoZIzj0EAwIw
    OTELMAkGA1UEBhMCTkwxFDASBgNVBAoMC1BoaWxpcHMgSHVlMRQwEgYDVQQDDAty
    b290LWJyaWRnZTAiGA8yMDE3MDEwMTAwMDAwMFoYDzIwMzgwMTE5MDMxNDA3WjA5
    MQswCQYDVQQGEwJOTDEUMBIGA1UECgwLUGhpbGlwcyBIdWUxFDASBgNVBAMMC3Jv
    b3QtYnJpZGdlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjNw2tx2AplOf9x86
    aTdvEcL1FU65QDxziKvBpW9XXSIcibAeQiKxegpq8Exbr9v6LBnYbna2VcaK0G22
    jOKkTqOBuTCBtjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNV
    HQ4EFgQUZ2ONTFrDT6o8ItRnKfqWKnHFGmQwdAYDVR0jBG0wa4AUZ2ONTFrDT6o8
    ItRnKfqWKnHFGmShPaQ7MDkxCzAJBgNVBAYTAk5MMRQwEgYDVQQKDAtQaGlsaXBz
    IEh1ZTEUMBIGA1UEAwwLcm9vdC1icmlkZ2WCFDuxUi22sYpLlwJY81Wrqy11phcO
    MAoGCCqGSM49BAMCA0gAMEUCIEBYYEOsa07TH7E5MJnGw557lVkORgit2Rm1h3B2
    sFgDAiEA1Fj/C3AN5psFMjo0//mrQebo0eKd3aWRx+pQY08mk48=
    -----END CERTIFICATE-----
    """
      |> Text.toUtf8
      |> decodeCert
      |> Either.toException

Taken from @rlmark/cloudDoodles/code/releases/1.0.0/latest/terms/assets/indexHtml

assets.indexHtml : Text
assets.indexHtml =
  "<!DOCTYPE html>\n  <html lang=\"en\">\n  <head>\n      <meta charset=\"UTF-8\">\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n      <title>Unison Doodles</title>\n      <link rel=\"stylesheet\" href=\"styles.css\">\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class =\"row bg-primary text-white text-center py-5\">\n        <h1 class=\"display-1\">๐ŸŽจ</h1>\n        <h1 class=\"display-4 fw-bold\">Unison Doodles</h1>\n        <p class=\"lead\">This test app was written with the Unison Cloud</p>\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col pt-5\">\n          <h2>๐Ÿง‘\8205๐ŸŽจ Draw something</h2>\n        </div>\n      </div>\n\n      <div class=\"row row-cols-2 g-1\">\n\n        <div class=\"col col-sm pt-2\">\n          <canvas id =\"doodle-canvas-primary\" class=\"workspace doodle-canvas\"></canvas>\n          <div id=\"canvas-palette\" class=\"palette\">\n            <div class=\"inkwell p-2\" data-color=\"black\"></div>\n            <div class=\"inkwell p-2\" data-color=\"red\"></div>\n            <div class=\"inkwell p-2\" data-color=\"orange\"></div>\n            <div class=\"inkwell p-2\" data-color=\"yellow\"></div>\n            <div class=\"inkwell p-2\" data-color=\"green\"></div>\n            <div class=\"inkwell p-2\" data-color=\"blue\"></div>\n            <div class=\"inkwell p-2\" data-color=\"purple\"></div>\n          </div>\n        </div>\n\n        <div class=\"col col-sm px-3\">\n          <form id=\"doodle-form\" onsubmit=\"return false\">\n            <div class=\"form-group pb-3\">\n              <label for =\"title\">Title</label>\n              <input type=\"text\" class=\"form-control\" id=\"title\" name=\"title\" placeholder=\"Enter title\">\n              <small id=\"titleHelp\" class=\"form-text text-muted\">Give your drawing a title</small>\n            </div>\n            <div class=\"form-group pb-3\">\n              <label for=\"author\">Author</label>\n              <input type=\"text\" class=\"form-control\" id=\"author\" name=\"author\" placeholder=\"Enter name\">\n              <small id=\"authorHelp\" class=\"form-text text-muted\">Who made this work of art?</small>\n              <div class=\"button-group py-3\">\n                <button id=\"save-doodle\" type=\"submit\" class=\"btn btn-info\">Save</button>\n                <button id=\"clear-doodle\" type=\"reset\" class=\"btn btn-warning\">Clear</button>\n              </div>\n            </div>\n          </form>\n        </div>\n\n      </div>\n\n    <div class=\"container pt-5\">\n      <div id=\"doodle-log-holder\" class=\"row row-cols-1\">\n            <h2>๐Ÿ–ผ Gallery</h2>\n            <h3>Everyone's work is here for now!</h3>\n            <div class=\"album py-5 px-5 bg-light\">\n              <div id=\"doodle-log\" class=\"row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3\"></div>\n            </div>\n      </div>\n    </div>\n    <script src=\"./script.js\"></script>\n    <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\" crossorigin=\"anonymous\">\n    </div>\n  </body>\n</html>"
assets.indexHtml : Text
assets.indexHtml = 
  """
  <!DOCTYPE html>
  <html lang=\"en\">
    <head>
        <meta charset=\"UTF-8\">
        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
        <title>Unison Doodles</title>
        <link rel=\"stylesheet\" href=\"styles.css\">
    </head>
    <body>
      <div class=\"container\">
        <div class =\"row bg-primary text-white text-center py-5\">
          <h1 class=\"display-1\">๐ŸŽจ</h1>
          <h1 class=\"display-4 fw-bold\">Unison Doodles</h1>
          <p class=\"lead\">This test app was written with the Unison Cloud</p>
        </div>
        <div class=\"row\">
          <div class=\"col pt-5\">
            <h2>๐Ÿง‘\8205๐ŸŽจ Draw something</h2>
          </div>
        </div>
        <div class=\"row row-cols-2 g-1\">
          <div class=\"col col-sm pt-2\">
            <canvas id =\"doodle-canvas-primary\" class=\"workspace doodle-canvas\"></canvas>
            <div id=\"canvas-palette\" class=\"palette\">
              <div class=\"inkwell p-2\" data-color=\"black\"></div>
              <div class=\"inkwell p-2\" data-color=\"red\"></div>
              <div class=\"inkwell p-2\" data-color=\"orange\"></div>
              <div class=\"inkwell p-2\" data-color=\"yellow\"></div>
              <div class=\"inkwell p-2\" data-color=\"green\"></div>
              <div class=\"inkwell p-2\" data-color=\"blue\"></div>
              <div class=\"inkwell p-2\" data-color=\"purple\"></div>
            </div>
          </div>
          <div class=\"col col-sm px-3\">
            <form id=\"doodle-form\" onsubmit=\"return false\">
              <div class=\"form-group pb-3\">
                <label for =\"title\">Title</label>
                <input type=\"text\" class=\"form-control\" id=\"title\" name=\"title\" placeholder=\"Enter title\">
                <small id=\"titleHelp\" class=\"form-text text-muted\">Give your drawing a title</small>
              </div>
              <div class=\"form-group pb-3\">
                <label for=\"author\">Author</label>
                <input type=\"text\" class=\"form-control\" id=\"author\" name=\"author\" placeholder=\"Enter name\">
                <small id=\"authorHelp\" class=\"form-text text-muted\">Who made this work of art?</small>
                <div class=\"button-group py-3\">
                  <button id=\"save-doodle\" type=\"submit\" class=\"btn btn-info\">Save</button>
                  <button id=\"clear-doodle\" type=\"reset\" class=\"btn btn-warning\">Clear</button>
                </div>
              </div>
            </form>
          </div>
        </div>
      <div class=\"container pt-5\">
        <div id=\"doodle-log-holder\" class=\"row row-cols-1\">
              <h2>๐Ÿ–ผ Gallery</h2>
              <h3>Everyone's work is here for now!</h3>
              <div class=\"album py-5 px-5 bg-light\">
                <div id=\"doodle-log\" class=\"row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3\"></div>
              </div>
        </div>
      </div>
      <script src=\"./script.js\"></script>
      <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC\" crossorigin=\"anonymous\">
      </div>
    </body>
  </html>
  """

This is actually a pretty printer bug. These are entered with the multiline string syntax and likely still looks like that locally, but sometimes aren't printed with the multiline syntax. See Cody's comment here: unisonweb/unison#4392 (comment)

I'd rather we fix that original bug if we can, even though this is simple to fix in the frontend (I think its best to not diverge on rendering capabilities between the 2 interfaces). Definitely should re-evaluate that if we can get to the pretty printing issue in a timely manner.

cc @ChrisPenner

Oh, i haven't seen that issue/comment, sorry.

Agree, systemic fix would be much better than "hacky" solution i've proposed :)

Feel free to close this one then.