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

How can I get special characters using elm-html module?

免责声明:我是 Elm 的新手

我正在摆弄在线 Elm 编辑器,我 运行 遇到了一个问题。我找不到让某些特殊字符(版权、商标等)出现的方法。我试过了:

import Html exposing (text)

main =
  text "©"

所有显示的都是实际文本 ©。我还尝试为其使用 unicode 字符 \u00A9,但最终给我一个语法错误:

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

我发现的唯一方法是实际访问某人的网站,然后 copy/paste 他们的版权符号进入我的应用程序:

import Html exposing (text)

main =
  text "©"

这行得通,但我更希望能够快速输入这些字符,而不必在其他网站上寻找实际符号。在 Elm 中返回 HTML 时是否有 preferred/recommended 获取非转义文本的方法?


编辑:

专用于Mac:

所有这些都在在线编辑器中进行了测试并且有效。这仍然没有解决核心问题,但对于这些特定的特殊字符来说,这是一个很好的注意事项。

您不需要寻找符号,您可以从 this one 这样的列表中获取它们。

如果复制和粘贴太麻烦,您还可以创建一个辅助函数,您可以像这样使用转义字符:

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;" 

我最近创建了一个 Elm package 来解决这个问题。如果您使用 text' "&copy;",它将呈现版权符号 © 而不是转义码。也适用于 "&#169;""&#x000A9;"。希望这对您有所帮助!

这是为什么(故意的)没那么容易

Elm 的 "makers" 不愿意为我们提供将 "special" 字符插入 HTML 文本的方法,这是可以理解的。两个主要原因:

  1. 这会打开一个 "text injection" 漏洞,恶意用户可以在其中插入任何 HTML 标签,甚至 JavaScript 代码,进入网页。想象一下,如果您可以在像 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 "&nbsp;") ] []

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

resString = String.fromChar (Char.fromCode 187)

在Elm字符串和字符中可以直接使用unicode转义码:

我们有一个包含所有特殊字符的 util 模块,例如:

module Utils.SpecialChars exposing (noBreakSpace)

noBreakSpace : Char
noBreakSpace = '\x00A0'

可用作:

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

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