【问题标题】:How can I render a string with proper formatting in Yesod?如何在 Yesod 中呈现具有正确格式的字符串?
【发布时间】:2020-11-13 16:24:12
【问题描述】:

我使用tabular library 制作了一张表格。我使用这个库制作的表格实际上只是一个带有很多换行符的花哨字符串。我弄清楚如何正确格式化此表的唯一方法是在 repl 中使用 putStr。

如果我只显示字符串,我会返回一个看起来像这样的混乱:

"+-----++-----------+-----------++-------------+-------------+\n|     || memtest 1 | memtest 2 || time test 1 | time test 2 |\n+=====++=

我希望能够在 Yesod Handler Html 中以正确的格式呈现此表。更具体地说,我想从 whamlet 模板中呈现此表。

我曾尝试通过使用pShow 等函数来合并pretty-printing library,但未能成功。我浏览了各种 Yesod 库,但似乎无法确定任何有用的功能。

【问题讨论】:

  • 为什么不使用适当的 HTML 工具来生成表格,而不是通过等宽纯文本? — 到达那里的一个简单技巧就是intercalate将字符串的lines<br> 结合使用,并将结果用作preEscapedString
  • 阅读tabular 描述:It also comes with some default rendering functions for turning those tables into ... HTML。因此,与其将表格呈现为 ASCII,不如将其呈现为适当的 HTML。

标签: haskell yesod


【解决方案1】:

您的两个选项似乎是使用 HTML <pre> 元素按原样呈现 ASCII 表以获得“老式”外观,或者使用 tabular 对 HTML 的支持重新呈现表,获取实际的 HTML <table> 元素。

最简单的方法是使用<pre> 元素进行渲染。在 whamlet 模板中,只需将 ASCII 表插入到模板中即可:

import Yesod
import qualified Text.Tabular as T
import qualified Text.Tabular.AsciiArt as TA

example = T.Table
  (T.Group T.NoLine [T.Header "1", T.Header "2"])
  (T.Group T.SingleLine [T.Header "Table Type", T.Header "HTML Element"])
  [ ["ASCII art", "<pre>"], ["HTML", "<table>"] ]

asciiTable :: String
asciiTable = TA.render id id id example

getAsciiR :: Handler Html
getAsciiR = defaultLayout
  [whamlet|
    <p>My old-school table follows
    <pre>#{asciiTable}
    |]

使用tabular 的HTML 支持有点复杂,主要是因为它使用Text.Html 和手工构建的CSS,它们不直接与Yesod 的小部件和基于blaze 的标记交互。但是,您可以像这样从头开始构建一个小部件:

import Yesod
import qualified Data.Text.Lazy.Builder as B
import qualified Text.Tabular as T
import qualified Text.Tabular.AsciiArt as TA
import qualified Text.Tabular.Html as TH
import qualified Text.Html as H

htmlTable :: Widget
htmlTable = do
  toWidget . preEscapedToMarkup . renderHtml $ tbl
  toWidget . CssBuilder . B.fromString $ TH.defaultCss
  where tbl = TH.render H.stringToHtml H.stringToHtml H.stringToHtml example
        renderHtml h = foldr ($) "" [H.renderHtml' 0 e | e <- H.getHtmlElements h]

然后使用小部件插值 (^{...}) 将其插入到 whamlet 模板中:

getHtmlR :: Handler Html
getHtmlR = defaultLayout
  [whamlet|
    <p>My fancy table follows:
    ^{htmlTable}
    |]

这将给出类似的东西:

完整代码如下。您可以访问localhost:3000/asciilocalhost:3000/html查看结果:

{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE QuasiQuotes           #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeFamilies          #-}

module TableServer where

import qualified Data.Text.Lazy.Builder as B
import qualified Text.Tabular as T
import qualified Text.Tabular.AsciiArt as TA
import qualified Text.Tabular.Html as TH
import qualified Text.Html as H

import Yesod

data Site = Site
mkYesod "Site" [parseRoutes|
  /ascii AsciiR GET
  /html  HtmlR  GET
  |]
instance Yesod Site

example = T.Table
  (T.Group T.NoLine [T.Header "1", T.Header "2"])
  (T.Group T.SingleLine [T.Header "Table Type", T.Header "HTML Element"])
  [ ["ASCII art", "<pre>"], ["HTML", "<table>"] ]

asciiTable :: String
asciiTable = TA.render id id id example

getAsciiR :: Handler Html
getAsciiR = defaultLayout
  [whamlet|
    <p>My old-school table follows
    <pre>#{asciiTable}
    |]

htmlTable :: Widget
htmlTable = do
  toWidget . preEscapedToMarkup . renderHtml $ tbl
  toWidget . CssBuilder . B.fromString $ TH.defaultCss
  where tbl = TH.render H.stringToHtml H.stringToHtml H.stringToHtml example
        renderHtml h = foldr ($) "" [H.renderHtml' 0 e | e <- H.getHtmlElements h]

getHtmlR :: Handler Html
getHtmlR = defaultLayout
  [whamlet|
    <p>My fancy table follows:
    ^{htmlTable}
    |]

main :: IO ()
main = warp 3000 Site

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    • 2015-04-11
    • 2017-09-25
    • 1970-01-01
    相关资源
    最近更新 更多