如何使用elm-html模块获取特殊字符?

20

免责声明:我对 Elm 完全没有了解

我正在使用在线的 Elm 编辑器,但是遇到了一个问题。我无法找到一种方法来显示某些特殊字符(版权、商标等)。我已经尝试过:

import Html exposing (text)

main =
  text "©"

出现的只有实际文本©。我还尝试使用它的Unicode字符\u00A9,但最终导致了语法错误:

所有显示的只是实际文本©。我也试图使用它的Unicode字符\u00A9,但最终导致语法错误:

(line 1, column 16): unexpected "u" expecting space, "&" or escape code

我发现的唯一方法是实际访问某个网站并将其版权符号复制/粘贴到我的应用程序中:

import Html exposing (text)

main =
  text "©"

这样做是有效的,但我更希望能够快速输入这些字符而不必在其他网站上寻找实际符号。在 Elm 中返回 HTML 时,有没有推荐的方法来获取非转义文本?


编辑:

特别是对于 Mac:

  • 选项+g 给出 ©
  • 选项+2 给出
  • 选项+r 给出 ®

这些都在在线编辑器中进行了测试并且可以正常工作。这仍然没有解决核心问题,但这只是一些关于这些特定特殊字符的好东西。

5个回答

22

为什么这样做(故意)不那么容易

Elm的“创作者”理所当然地不愿意给我们一种插入“特殊”字符到HTML文本的方法,有两个主要原因:

  1. 这将打开一个“文本注入”漏洞,恶意用户可以将任何HTML标签,甚至JavaScript代码插入Web页面。想象一下,如果你在Stack Overflow这样的论坛网站上这样做,你可以诱骗任何阅读你贡献的人在他们的浏览器中执行你选择的代码。
  2. Elm努力生成最优DOM更新。这仅适用于Elm知道其内容的标签,而不是包含标签的文本。当人们在Elm程序中插入包含HTML标签的文本时,最终会出现无法优化的DOM部分。

然而它如何可能

话虽如此,Elm用户社区已经找到了一个漏洞来解决这个问题。由于上述原因,这并不推荐,尤其是如果您的文本是非常量的,即来自程序外部的源。尽管如此,人们仍然希望做到这一点,因此我将记录下来以节省其他人挖掘一切并使其正常工作的麻烦:

  1. 如果您还没有它,
    import Json.Encode exposing (string)
    这在包elm-lang/core中,所以它应该已经是您的依赖项。
  2. 同样,
    import Html.Attributes exposing (property)
  3. 最后,创建一个具有property "innerHTML"和JSON值表示您的文本的标签,例如:
    span [ property "innerHTML" (string " ") ] []

4
虽然我不再使用 Elm,但这是一个很好的解释如何“黑客式”地解决问题,但为什么不应该那样做。我认为这是对原始问题的适当回应。谢谢,希望这能帮助其他对此感到好奇的人。 - Sam
对于熟悉React的人来说,这类似于使用dangerouslySetInnerHTML属性。 - Roshambo

13

我发现有更好的解决方案:你可以将Unicode中的特殊字符转换为char,然后从char创建一个字符串:

resString = String.fromChar (Char.fromCode 187)

8
你可以直接在 Elm 字符串和字符中使用 Unicode 转义码:
我们有一个工具模块,其中包含所有特殊字符,例如:
module Utils.SpecialChars exposing (noBreakSpace)

noBreakSpace : Char
noBreakSpace = '\x00A0'

以下是可用于的:

let
  emptyLabel = String.fromChar noBreakSpace
in
label []
    [ span [ ] [ text emptyLabel ]
    ]

这将呈现一个<span>&nbsp;</span>

3
在更新版本的 Elm 中,这将会变成 noBreakSpace = '\u{00A0}' - ravuya

3

我最近创建了一个Elm包,可以解决这个问题。如果你使用text' "&copy;",它将呈现版权符号©,而不是转义代码。也适用于"&#169;""&#x000A9;"。希望这能帮到你!


1
Jason,你在这方面的辛勤工作真是令人赞叹!看起来非常实用。但是我觉得通过解释实体来解决Html.text的问题有点笨拙。我会继续寻找更加“优雅”的解决方案。 - Carl Smotricz

2

您无需寻找符号,可以从类似这个列表中获取它们。

如果复制和粘贴太麻烦,您也可以创建一个帮助函数来使用您的转义字符,例如:

import Html exposing (..) 
import String

htmlDecode str = 
  let 
    replace (s1, s2) src= String.join s2 <| String.split s1 src    
    chrmap = 
      [ ("&reg;", "®")
      , ("&copy;", "©" )
      ] 
  in  
    List.foldl replace str chrmap

main = text <| htmlDecode "hello &copy;" 

谢谢。我想当我说“寻找”时有点夸张了 :) 。虽然这是一个不错的辅助函数,但它并不能真正解决从另一个网站复制/粘贴实际版权符号(或任何其他不在键盘上的符号)到我的代码中的问题。但这个辅助函数的最大优点是我只需要复制/粘贴一次。然后我就可以在我的应用程序中使用通常被HTML识别的普通字符串。 - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接