2

我正在尝试使用 Clojure Enlive lib 做一些简单的事情:我希望页面的顶部菜单根据用户选择的语言(英语或日语)而有所不同。我找不到如何实现这个基本功能。

我有一个包含 2 个部分(每种语言一个)的“template/header.html”模板:

<div class="header en-US">...</div>
<div class="header ja-JP">...</div>

我在模板代码中创建了 2 个相应的片段:

(:require [net.cgrand.enlive-html :as html])
...
(html/defsnippet header-ja-JP "templates/header.html" [:div.header.ja-JP] [])
(html/defsnippet header-en-US "templates/header.html" [:div.header.en-US] [])

现在,当我加载我的主模板 (index.html) 时,我想将我的标题菜单代码填充到我的导航标签中。

下面,参数“lang”的值是“en-US”或“ja-JP”:

(defn process-template
  [lang]
  (let [header-selector  (str “header-“ lang)
        header-content   (@(resolve (symbol header-selector)))]
    (apply str
           (html/emit*
            (html/at
             (html/html-resource "templates/index.html")
             [:nav] (html/content (header-content)))))))

它抛出一个 java.lang.NullPointerException

如果我将最后一行替换为

[:nav] (html/content (header-ja-JP)))))))

或者

[:nav] (html/content (header-en-US)))))))

它工作正常(所以片段工作),但我尝试了很多不同的语法,不能使动态标题基于语言工作。

如果我在 REPL 中手动执行上面的代码(让部分)似乎没问题,标题内容是包含正确内容的 JSON 对象,所以我不明白为什么我得到 NullPointerException。

理想情况下,我认为我应该只有一个片段将语言作为参数并返回相应的 HTML 部分,但也没有设法做到这一点。

我是 Clojure 的新手,所以我可能在这里遗漏了一些明显的东西;如果有人能指出我上面的代码有什么问题,或者用另一种方法来完成这项工作,那就太棒了。

谢谢,奥利维尔

4

2 回答 2

0

(@(resolve (symbol header-selector)))返回一个值。 (resolve (symbol header-selector))返回一个函数。

[:nav] (html/content (header-content)))))))header-content作为函数调用。

替换(@(resolve (symbol header-selector)))(resolve (symbol header-selector))

html/at如果出现其他问题,您可能需要塞进去,我不清楚该怎么html/html-resourceclojure.java.io/file

于 2014-03-03T09:44:18.807 回答
0

If we want to do it differently as cgrand suggests, there are many, many ways to accomplish this. I have a hard time imagining how he'd do it with maps, but I'd do it this way:

(defn process-template [lang]
  (html/select (html/html-snippet
                 "<html>
                    <head></head>
                    <body>
                      <nav>
                        <div class=\"en\"></div>
                        <div class=\"jp\"></div>
                      </nav>
                    </body>
                  </html>") 
        [(keyword (str "div." lang))]))

(apply str (html/emit* (process-template "en")))
=> "<div class=\"en\"></div>"

Of course read it from file instead of HTML in a string. The function plucks out the matching HTML node according to a selector.

于 2014-03-03T11:08:08.143 回答