Haskell 如何制作nicEditor snaplet?(几个问题)
下面的示例定义了一个snaplet,用于将NiceEditor绑定到textarea。以下问题不仅与下面的示例有关,而且可能与其他类似案例有关Haskell 如何制作nicEditor snaplet?(几个问题),haskell,haskell-snap-framework,Haskell,Haskell Snap Framework,下面的示例定义了一个snaplet,用于将NiceEditor绑定到textarea。以下问题不仅与下面的示例有关,而且可能与其他类似案例有关 新手能否遵循以下说明(如何澄清) 如何使示例使用更少的步骤或更简单?(是否可以使用与以下内容大致相同的内容?) 这使用了解释拼接。如果可能,snaplet是否也应提供编译拼接 snaplet可能会为典型情况提供一个或多个默认处理程序。处理程序可以在下面的“SnapNic.hs”中定义。一些回调机制给用户,然后呢 -- {-#语言模板haskell} {-
{-#语言模板haskell}
{-#语言重载字符串}
------------------------------------------------------------------------------
--|本模块定义了nicEditor snaplet,这只是一个简短的示例,
--如何将Snaplet与接头一起定义。
--许可证:BSD3。
--下面是一些简单的说明,如何使用或尝试:
--
-- 1. 制作一个目录,我们将使用下面的“netry”,去那里。
--初始化项目,例如“snap init default”。
-- 2. 将此文件作为SnapNic.hs复制到netry/src目录。
-- 3. 将“导入SnapNic”添加到Site.hs和Application.hs
-- 4. 将“,_niced::Snaplet Nicsnap”添加到Application.hs中的数据应用程序
--
-- 5. 添加“n我不是新手,所以我无法回答你的第一个问题,但我对其他一些问题有一些想法和答案。首先,如果你真的希望这是一个严肃的snaplet(用于教学或实际使用)您可能应该将其添加到cabal项目中。这将从您的说明中删除步骤2。接下来,Snaplet可以定义自己的路由。您可以通过调用函数在初始值设定项中执行此操作。这将删除步骤8。Snaplet还可以提供自己的文件系统资源,这些资源将复制到任何使用您可以使用此功能取消步骤10,并提供默认配置文件。有关如何执行此操作的详细信息,请参阅snaplet教程末尾的部分
目前,这可能是关于如何使用snaplet提供的大多数功能的黑客攻击的最好例子。如果你想让它成为一个真正强大的通用snaplet供其他人使用,那么你肯定应该包括解释拼接和编译拼接。我最近在snap包中添加了一些,使它更容易o编写在编译或解释拼接模式下自动工作的通用Snaplet。这些代码还没有被破解,但我可能很快就会发布
我还一直致力于更全面地利用snaplet API的大部分功能。与snaplet postgresql simple不同,此snaplet定义了模板和拼接。它仍在开发中,但已经演示了大部分功能。剩下的工作将主要是完善和健壮性。再次感谢在中!我不得不多次阅读文件系统数据部分,并且在使用cabal时遇到了一些困难。现在它似乎可以安装,并且我可以像其他库一样使用。接下来,接下来的问题是,在我做了一些清理之后,如何处理这个包。(这应该放到github吗?)另一个问题是,现在路由需要在地址的末尾加上/-char。如何让它也接受一个地址而不加上/-char?如果你认为其他人可以从中受益,那么通常的方法是将它放在github和hackage上。没有更多信息,我无法回答第二个问题。我认为你玩这个游戏很好有了snaplet,但我可能还要补充一点,这可能不是snaplet的最佳应用程序。在我看来,您只需使用
标记,就可以在模板中更灵活地完成大部分工作。我倾向于为需要更多haskell代码且无法单独在模板中完成的事情编写snaplet。
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
------------------------------------------------------------------------------
-- | This module defines nicEditor snaplet, just a short example to show,
-- how snaplets can be defined together with splices.
-- License: BSD3.
-- Here are hopefully easy instructions, how to use or try:
--
-- 1. Make a directory, we'll use "netry" below, go there.
-- Initialize a project, e.g. "snap init default".
-- 2. Copy this file to netry/src-directory as SnapNic.hs.
-- 3. Add "import SnapNic" to Site.hs and to Application.hs
-- 4. Add ", _niced :: Snaplet Nicsnap" to data App in Application.hs
--
-- 5. Add "n <- nestSnaplet "niced" niced nicsnapInit" to
-- app :: SnapletInit App App in Site.hs.
-- 6. Add "addNicEditSplices n" to the same function as in step 5.
-- 7. Change the return-line of the same function as in step 5:
-- "return $ App h s a n"
-- that is, add "n" into the end. We need this because of step 4.
--
-- 8. Make route, e.g. ", ("/netext", with auth handleNEtext)" to
-- routes-function in Site.hs
--
-- 9. And then add handler into Site.hs:
-- handleNEtext :: Handler App v ()
-- handleNEtext = method GET handleForm <|> method POST handleFormSubmit
-- where
-- handleForm = render "textedit"
-- handleFormSubmit = do
-- p <- getParam "ots"
-- writeText "Submitting text from textarea...\n"
-- writeText (T.pack (show p))
--
-- 10. Last, add the following 2 templates to "netry/snaplets/heist/templates".
-- (This could be made simpler, but this works as an example of apply-tag.)
-- textedit.tpl:
-- <apply template="base">
-- <apply template="_textedit" />
-- </apply>
-- _textedit.tpl:
-- <h2>Your nic editor</h2>
-- <form method="post" action="netext">
-- <neTA/>
-- <button name="ne" value="ne" type="Submit">Send text</button>
-- </form>
-- <neScript/>
--
-- 11. Compile everything "cabal install -fdevelopment". After that,
-- if everything compiled, "netry -p 8000", start your browser and go
-- to "localhost:8000/netext".
--
-- TODO! This could use the config-files at least for some parameters, and more
-- tags,please. Tags could use some attributes (for example, size parameters
-- could be given as attributes of tags)...
--
module SnapNic
( Nicsnap (..)
, nicsnapInit
, addNicEditSplices
) where
------------------------------------------------------------------------------
import Control.Lens (makeLenses, view, (^.))
import qualified Data.Text as T (Text, append, pack)
import Data.Maybe (fromJust, fromMaybe)
import Snap.Core (MonadSnap)
import Snap.Snaplet (Snaplet
, makeSnaplet
, snapletValue
, SnapletInit
, Initializer
)
import Snap.Snaplet.Heist (HasHeist, addSplices)
import qualified Text.XmlHtml as X (Node (Element, TextNode))
import qualified Heist.Interpreted as I (Splice)
------------------------------------------------------------------------------
-- | Nicsnap has fields that can be used to set some basic properties.
-- The editor can have a title and its size can be set. Javascript can be
-- local or remote.
data Nicsnap = Nicsnap
{ _nicsnap :: T.Text -- title
, _areaSize :: (Int,Int) -- rows, cols
, _areaRef :: T.Text -- how to apply nicEditors?
-- (This may not be sufficient in order to refer in some other way, TODO!)
, _localR :: Maybe T.Text -- local route to nicEdit.js
, _webR :: T.Text -- route to nicEdit's javascript source.
}
makeLenses ''Nicsnap -- makes webR and other lenses
------------------------------------------------------------------------------
-- | Configurations are given here. This could use config-files...
-- What other things to configure?
-- If you want to make a local copy of the nicEdit, then add a static route
-- to the "routes"-function.
nicsnapInit :: SnapletInit b Nicsnap
nicsnapInit = makeSnaplet "nicsnap" "NicEditor snaplet " Nothing $ do
let m = "Nic editor title"
aS = (20,80)::(Int,Int) -- rows, cols
aR = "nicEditors.allTextAreas" -- TODO! We need to be able to tell,
-- which textareas have editors in a page.
lR = Nothing
-- lR = Just "/nicEdit.js"
-- If localR is nothing, then webR is used with the following addr.
wR = "http://js.nicedit.com/nicEdit-latest.js"
return $ Nicsnap m aS aR lR wR
------------------------------------------------------------------------------
-- | Internal, this makes the script-tag.
-- Input could be e.g. txt = "/nicEdit.js"
srcElem :: T.Text -> X.Node
srcElem txt = X.Element "script"
[("src",txt),("type","text/javascript")] []
-- | Internal, this makes the script-tag. At the moment this changes all
-- textareas to niceditors, if the example input below is used. TODO!...
-- Input could be e.g. txt = "nicEditors.allTextAreas"
srcOnLoad :: T.Text -> X.Node
srcOnLoad txt = X.Element "script" [("type","text/javascript")]
[X.TextNode (T.append (T.append "bkLib.onDomLoaded(" txt) ");")]
-- | Internal, used to define "divs", where we give a label and size to
-- textarea. Also ids and names.
-- TODO! ids and names could be parameters.
divLabelTX :: T.Text -> T.Text -> T.Text -> X.Node
divLabelTX title r c = X.Element "div" [("class", "required")]
[ X.Element "label" [("for","ots")]
[X.TextNode title]
, X.Element "textarea"
[("id","ots"), ("name","ots"), ("cols",c), ("rows",r)]
[X.TextNode " "]
]
-- | Internal, this can be used in splice-definition.
-- TODO! ids and names could be parameters, too.
nicTextAreaAdd :: MonadSnap m => T.Text -> (Int,Int) -> I.Splice m
nicTextAreaAdd title (r,c) = return [divLabelTX
title
(T.pack . show $ r)
(T.pack . show $ c)]
-- | Add script-tags to web page with splice that tell, what javascript
-- library to use...
nicEditAdd :: MonadSnap m => T.Text -> T.Text -> I.Splice m
nicEditAdd src edElems = return (srcElem src : [srcOnLoad edElems])
------------------------------------------------------------------------------
-- | Get the route to the javascript library that is applied (either local
-- library or construct a link to a web address).
nicRoute :: Nicsnap -> T.Text
nicRoute ns = let mlR = ns ^. localR in fromMaybe (ns ^. webR) mlR
------------------------------------------------------------------------------
-- | neTextAreaTag and neScripTag are used in addSplices to define the tags
-- to be used in templates.
-- What other tags could be useful? Maybe a way to add a nicEditor directly
-- with one or more button bind to it ("send", "clear", etc). TODO!
neTextAreaTag = "neTA" :: T.Text
neScriptTag = "neScript" :: T.Text
-- | Make the tags to be used in templates. At the moment, only the above
-- tags are defined.
addNicEditSplices :: HasHeist b => Snaplet Nicsnap -> Initializer b v ()
addNicEditSplices n = let m = view snapletValue n in addSplices
[(neTextAreaTag, nicTextAreaAdd (m ^. nicsnap) (m ^. areaSize))
,(neScriptTag, nicEditAdd (nicRoute m) (m ^. areaRef) )
]
------------------------------------------------------------------------------