packages feed

panda 2008.10.26 → 2008.10.27

raw patch · 22 files changed

+234/−181 lines, 22 filesdep +data-defaultdep ~mps

Dependencies added: data-default

Dependency ranges changed: mps

Files

changelog.markdown view
@@ -1,3 +1,10 @@+2008.10.27+-----------++### Feature++* Customizable footer+ 2008.10.26 ----------- 
panda.cabal view
@@ -1,5 +1,5 @@ Name:                 panda-Version:              2008.10.26+Version:              2008.10.27 Build-type:           Simple Synopsis:             A simple static blog engine Description:          A simple static blog engine@@ -14,9 +14,11 @@ data-files:			  readme.markdown, changelog.markdown  library-  build-depends: base, cgi, network, haskell98, old-locale, old-time, directory, filepath, containers, mps >= 2008.10.15, parsedate >= 3000.0.0, rss >= 3000.0.1, xhtml, kibro >= 0.4.1, utf8-string >= 0.3.1, pandoc >= 0.46, MissingH, parsec >= 2, gravatar >= 0.3+  build-depends: base, cgi, network, haskell98, old-locale, old-time, directory, filepath, containers, mps >= 2008.10.25, parsedate >= 3000.0.0, rss >= 3000.0.1, xhtml, kibro >= 0.4.1, utf8-string >= 0.3.1, pandoc >= 0.46, MissingH, parsec >= 2, gravatar >= 0.3, data-default >= 0.2   hs-source-dirs: src/-  exposed-modules:  Panda+  exposed-modules:  +                    Main+                                         Panda.Config.Global                      Panda.Controller.Application@@ -32,12 +34,13 @@                     Panda.Model.Static                     Panda.Model.Tag                     +                    Panda.Type.Extension                     Panda.Type.Pager                     Panda.Type.Reader-                    Panda.Type.Sidebar                     Panda.Type.State+                    Panda.Type.StaticWidget                     Panda.Type.Theme-                    Panda.Type.Extension+                                          Panda.View.Atom.Comment                     Panda.View.Atom.Post@@ -51,16 +54,15 @@                     Panda.View.Control.Static                     Panda.View.Control.Tag                     -                    Panda.View.Widget.Helper                     Panda.View.Widget.Body                     Panda.View.Widget.Footer                     Panda.View.Widget.Head                     Panda.View.Widget.Header+                    Panda.View.Widget.Helper                     Panda.View.Widget.Navigation                     Panda.View.Widget.RSS                     Panda.View.Widget.SearchBar                     Panda.View.Widget.Sidebar                     Panda.View.Widget.Template-                    -                    Main-                    ++                    Panda
readme.markdown view
@@ -1,4 +1,4 @@ ## Panda: a simple blog engine in Haskell  * [Panda homepage](http://www.haskell.org/haskellwiki/Panda)-* [doc](doc/readme)+* Documentation: inside `doc`
src/Panda/Config/Global.hs view
@@ -8,70 +8,105 @@ import Control.Arrow ((>>>), (&&&), (***)) import Data.Maybe import System.Directory+import Data.Default  import Panda.Type.Reader-import Panda.Type.Sidebar-import Panda.Type.Theme+import Panda.Type.StaticWidget+import Panda.Type.Theme ( to_theme ) import Panda.Type.Extension -db_id       = "db"-flat_id     = "."-post_id     = "blog"-config_id   = "config"-tag_id      = "tag"-comment_id  = "comment"-sidebar_id  = "sidebar"-theme_id    = "theme" -db_uri      = db_id-flat_uri    = db_uri / flat_id+db_id          = "db"+flat_id        = "."+post_id        = "blog"+config_id      = "config"+tag_id         = "tag"+comment_id     = "comment"+sidebar_id     = "sidebar"+theme_id       = "theme"+config_file_id = "site.txt" -config_uri  = flat_uri / config_id / "site.txt"-sidebar_uri = flat_uri / config_id / sidebar_id-post_uri    = flat_uri / post_id-tag_uri     = flat_uri / tag_id-comment_uri = flat_uri / comment_id-theme_uri   = flat_uri / config_id / theme_id+db_uri         = db_id+flat_uri       = db_uri / flat_id +config_uri     = flat_uri / config_id / config_file_id+sidebar_uri    = flat_uri / config_id / sidebar_id+footer_uri     = flat_uri / config_id+post_uri       = flat_uri / post_id+tag_uri        = flat_uri / tag_id+comment_uri    = flat_uri / comment_id+theme_uri      = flat_uri / config_id / theme_id +data ConfigData = +    BlogTitle+  | BlogSubtitle+  | HostName+  | AuthorEmail+  | PerPage+  | Navigation+  | Root+  | Sidebar+  | Footer+  | Favicon+  | AnalyticsAccountId+  | Extensions+  | Theme+  | PostDateFormat+  | CommentDateFormat+  | UrlDateFormat+  | UrlDateMatcher+  | UrlTitleSubs+  | UrlDateTitleSeperator+  | Cut+  | SummaryForRoot+  | SummaryForTag+  | SummaryForRss+  deriving (Show)+   -- unsafe, must restart server after changing config file, sorry about that ... -- but these configs are read only, and keep the view pure, so no monad headaches involved. -user_config = parse_config config_uri+user_config   = parse_config config_uri+for' x d      = user_config.lookup (x.show_data) .fromMaybe d+for_int' x d  = for' x d .read :: Int+for_list' x d = for' x d .parse_list+for x         = for' x (x.show_data) -config_for' s d = user_config.lookup s .fromMaybe d-config_for s    = config_for' s s+blog_title    = for BlogTitle+blog_subtitle = for BlogSubtitle+host_name     = for HostName+author_email  = for AuthorEmail -blog_title      = config_for "blog_title"-blog_subtitle   = config_for "blog_subtitle"-host_name       = config_for "host_name"-author_email    = config_for "author_email" +per_page      = for_int' PerPage "7"+navigation    = for_list' Navigation "About" .("Home" :) -per_page        = config_for' "per_page" "7" .read :: Int-navigation      = config_for' "navigation" "About" .parse_list.("Home" :)+panda_url     = "http://www.haskell.org/haskellwiki/Panda" -panda_url       = "http://github.com/nfjinjing/panda" root               | user_root.belongs_to ["/", ""]  = "/"   | otherwise                       =  user_root.("/" /).remove_trailing_slash-  where user_root = config_for' "root" "/"+  where user_root = for' Root "/" -default_reader  = Markdown+default_reader  = def -sidebar = config_for "sidebar" .parse_list .map (sidebar_uri /).select (to_utf8 >>> doesFileExist >>> purify )-  .map (read_sidebar_item default_reader >>> purify)-  -favicon = config_for' "favicon" "/favicon.ico"+load_widget = read_static_widget default_reader >>> purify+sidebar = for_list' Sidebar "" .map (sidebar_uri /).select (to_utf8 >>> doesFileExist >>> purify )+  .map load_widget +footer  = for Footer +  .(footer_uri / ) +  .(\x -> if x.to_utf8.doesFileExist.purify then Just $ load_widget x else Nothing)+  +favicon = for' Favicon "/favicon.ico"  -- extensions-analytics_account_id = config_for "analytics_account_id"-extensions = config_for' "extensions" "search, comment, analytics" .parse_list .to_extensions+analytics_account_id = for AnalyticsAccountId+extensions           = for_list' Extensions "search, comment, analytics" .read_data_list :: [Extension]  -- theme-default_theme = blank_theme-user_theme_name = config_for "theme"-user_theme_uri = (theme_uri / user_theme_name) ++ ".txt"+default_theme   = def+user_theme_name = for Theme+user_theme_uri  = (theme_uri / user_theme_name) ++ ".txt"  theme = if user_theme_uri.doesFileExist.purify   then parse_config user_theme_uri .(("name", user_theme_name) : ) .to_theme@@ -79,19 +114,19 @@    -- custom as_l s                   = "[" ++ s ++ "]"-post_date_format         = config_for' "post_date_format" "%y-%m-%d"-comment_date_format      = config_for' "comment_date_format" "%y-%m-%d %T"-url_date_format          = config_for' "url_date_format" "%y-%m-%d"-url_date_matcher         = config_for' "url_date_matcher" "\\d{2}-\\d{2}-\\d{2}"-url_title_subs           = config_for' "url_title_subs" "" .as_l .read :: [(String, String)]-url_date_title_seperator = config_for' "url_date_title_seperator" " "+post_date_format         = for' PostDateFormat "%y-%m-%d"+comment_date_format      = for' CommentDateFormat "%y-%m-%d %T"+url_date_format          = for' UrlDateFormat "%y-%m-%d"+url_date_matcher         = for' UrlDateMatcher "\\d{2}-\\d{2}-\\d{2}"+url_title_subs           = for' UrlTitleSubs "" .as_l .read :: [(String, String)]+url_date_title_seperator = for' UrlDateTitleSeperator " "  -- summary-cut              = config_for' "cut" "✂-----" .to_utf8+cut              = for' Cut "✂-----" .to_utf8 parse_boolean    = belongs_to ["true", "1", "y", "yes", "yeah"]-summary_for_root = config_for "summary_for_root" .parse_boolean-summary_for_tag  = config_for "summary_for_tag"  .parse_boolean-summary_for_rss  = config_for "summary_for_rss"  .parse_boolean+summary_for_root = for SummaryForRoot .parse_boolean+summary_for_tag  = for SummaryForTag  .parse_boolean+summary_for_rss  = for SummaryForRss  .parse_boolean   
src/Panda/Controller/Application.hs view
@@ -13,7 +13,7 @@  -- env import Panda.Helper.Env hiding (tag, uri)-import Panda.Helper.StateHelper+import Panda.Helper.StateHelper hiding (only_for) import Prelude hiding ((.), (/), (^), id) import qualified Panda.Type.State as S import qualified Panda.Config.Global as G@@ -36,42 +36,39 @@  -- helpers -- liftIO: move to an (u)pper level monad-u = liftIO-blog_regex = G.url_date_matcher--init_post tags x = do-  x.Tag.fill_tag tags.Comment.fill_comment_size.u--tag_list = Tag.list.u+u                = liftIO+blog_regex       = G.url_date_matcher+init_post tags x = x.Tag.fill_tag tags.Comment.fill_comment_size.u+tag_list         = Tag.list.u   -- main controller  pages = -  [ ("$"                  ,index              )-  , ("(\\?.+)?$"          ,index              )-  , ("rss.xml$"           ,index_feed         )-  , (blog_regex           ,blog               )-  , ("static/."           ,static             )-  , ("tag/.*/rss.xml$"    ,tag_feed           )-  , ("tag/."              ,tag                )-  , ("search"             ,route_for_extension Search   $ search             )-  , ("comment/create"     ,route_for_extension Comment  $ comment_create     )+  [ ("$"                  ,index                                  )+  , ("(\\?.+)?$"          ,index                                  )+  , ("rss.xml$"           ,index_feed                             )+  , (blog_regex           ,blog                                   )+  , ("static/."           ,static                                 )+  , ("tag/.*/rss.xml$"    ,tag_feed                               )+  , ("tag/."              ,tag                                    )+  , ("search"             ,only_for Search   $ search             )+  , ("comment/create"     ,only_for Comment  $ comment_create     )   ] .map_fst ((G.root /) >>> ("^" ++))   ++-  [ ("^" ++ G.root ++ "$" ,index              )-  , ("^" ++ G.root ++ "?" ,index              )+  [ ("^" ++ G.root ++ "$" ,index                                  )+  , ("^" ++ G.root ++ "?" ,index                                  )   ]    -route_for_extension ext x = if has_extension ext then x else not_found+only_for ext x = if has_extension ext then x else not_found  index = do   posts <- Post.list.u   p <- paginate posts   tags <- tag_list   let nav = if p.Pager.current == 1 then home_nav else no_navigation-  let state = S.empty { S.uid = G.post_id, S.pager = p, S.tags = tags, S.nav_location = nav }+  let state = def { S.uid = G.post_id, S.pager = p, S.tags = tags, S.nav_location = nav }      posts.mapM (init_post tags) ^ PostV.list state >>= output_html @@ -86,7 +83,7 @@   tags <- tag_list      test_data <- S.mk_human_test .u-  let state = S.empty { S.uid = id, S.tags = tags, S.resource_title = blog.resource_title, S.human_test_data = test_data }+  let state = def { S.uid = id, S.tags = tags, S.resource_title = blog.resource_title, S.human_test_data = test_data }   blog.(init_post tags) ^ PostV.view state comments >>= output_html  @@ -97,7 +94,7 @@      let nav_id = static_page.Static.uid.id_to_resource   let nav   = if nav_id.belongs_to G.navigation then nav_id else no_navigation-  let state = S.empty { S.uid = id, S.tags = tags, S.nav_location = nav, S.resource_title = static_page.resource_title }+  let state = def { S.uid = id, S.tags = tags, S.nav_location = nav, S.resource_title = static_page.resource_title }   StaticV.view state static_page .output_html  tag = do@@ -109,7 +106,7 @@     Just post_set -> do       posts <- post_set.to_list.rsort.mapM (Post.get) .u >>= mapM (init_post tags)       p <- paginate posts-      let state = S.empty { S.uid = id, S.pager = p, S.tags = tags, S.resource_title = tag_name.Tag.resource_title_from_name }+      let state = def { S.uid = id, S.pager = p, S.tags = tags, S.resource_title = tag_name.Tag.resource_title_from_name }       posts.TagV.view state.output_html  tag_feed = do@@ -129,7 +126,7 @@   p <- paginate posts   tags <- tag_list   query <- uri-  let state = S.empty { S.uid = query, S.pager = p, S.tags = tags, S.resource_title = query }+  let state = def { S.uid = query, S.pager = p, S.tags = tags, S.resource_title = query }    posts.mapM (init_post tags) >>= \x -> x.SearchV.view state s.output_html @@ -149,20 +146,19 @@ get_input_data = show_data >>> get_input  check_human = do-  x <- [Comment.LeftNumber, Comment.RightNumber, Comment.Operator, Comment.HumanHack].mapM get_input_data ^ map fromJust-  let [l, r, op, h] = x+  [l, r, op, h] <- [Comment.LeftNumber, Comment.RightNumber, Comment.Operator, Comment.HumanHack].mapM get_input_data ^ map fromJust   return $ S.simple_eval (l.read) (r.read) (op.S.read_op) .is (h.read)  -- create helper, should be refactored to some common aspect check_create =-  [ validate Comment.Author     ( length >>> (> 0))-  , validate Comment.AuthorLink ( const True)-  , validate Comment.Body       ( length >>> (> 0))-  , validate Comment.EmptyField ( empty )-  , validate Comment.LeftNumber ( belongs_to (S.nums.map show))-  , validate Comment.RightNumber ( belongs_to (S.nums.map show))-  , validate Comment.Operator ( belongs_to (S.ops.map S.display_op))-  , validate Comment.HumanHack ( belongs_to (S.nums.map show))+  [ validate Comment.Author       ( length >>> (> 0))+  , validate Comment.AuthorLink   ( const True)+  , validate Comment.Body         ( length >>> (> 0))+  , validate Comment.EmptyField   ( empty )+  , validate Comment.LeftNumber   ( belongs_to (S.nums.map show))+  , validate Comment.RightNumber  ( belongs_to (S.nums.map show))+  , validate Comment.Operator     ( belongs_to (S.ops.map S.display_op))+  , validate Comment.HumanHack    ( belongs_to (S.nums.map show))   , check_human   ] .sequence ^ and @@ -171,4 +167,4 @@   maybe_s <- get_input_data s   case maybe_s of     Nothing -> return False-    Just v -> return $ f v+    Just v  -> return $ f v
src/Panda/Helper/Env.hs view
@@ -18,6 +18,7 @@   , module System.Time   , module System.Directory   , module Data.Foldable+  , module Data.Default ) where    import MPS hiding (base, col, sub, date)@@ -36,3 +37,4 @@ import System.Time import System.Directory import Data.Foldable (find)+import Data.Default
src/Panda/Helper/Helper.hs view
@@ -14,7 +14,7 @@ import Text.XHtml.Strict import Control.Monad hiding (join) import Data.Maybe-import Panda.Type.Pager as Pager hiding (empty)+import Panda.Type.Pager as Pager import MPS hiding (date) import Prelude hiding ((.), (/), (^), id, readFile, writeFile) import Char@@ -23,14 +23,12 @@ import Panda.Type.Reader import System.FilePath.Posix hiding ((<.>)) import System.Time+import Data.Default   (/) = (</>) infixl 5 / -(^) = (<.>)-infixl 9 ^- -- global parse_config_io s = readFile s ^ (\x -> x.filter_comment.lines.map strip .map (split "\\s*=\\s*") .map fill_snd_blank .map tuple2)   where fill_snd_blank [x] = [x,""]@@ -106,18 +104,7 @@   -- generic--starts_with _ [] = False-starts_with (x:xs) (y:ys) | x == y = starts_with xs ys-                          | otherwise = False--ends_with x y = starts_with (x.reverse) (y.reverse)--capitalize (x:xs) = [x].upper ++ xs.lower-camel_case = split "_" >>> map capitalize >>> join'-snake_case = gsub "\\B[A-Z]" "_\\&" >>> lower show_data = show >>> snake_case-   -- class class DataRenderer a where@@ -134,5 +121,3 @@  class Addressable a where     uri :: a -> String-- 
src/Panda/Helper/StateHelper.hs view
@@ -34,7 +34,7 @@ default_parse_date s = s.parse_post_date .fromMaybe default_date  has_extension x = G.extensions.has x-for_extension ext x = if has_extension ext then x else toHtml ""+only_for ext x = if has_extension ext then x else toHtml ""  -- controller paginate = length >>> full_paginate (G.per_page)
src/Panda/Model/Comment.hs view
@@ -44,6 +44,8 @@ instance Datable Comment where   date x  = x.uid.split "/".last.default_parse_date +instance Default Comment where+  def = Comment def def def def def  -- CRUD list_for post_id = do@@ -96,7 +98,7 @@   write_config_io (uid ++ ".meta") meta  -- extra-from_post_id x = Comment (post_id_to_uid x) "" "" "" ""+from_post_id x = def { uid = post_id_to_uid x }  post_id_to_uid x = G.flat_uri / G.comment_id / x.split "/" .last uid_to_post_id x = G.post_id / x.split "/" .last@@ -106,4 +108,4 @@   return $ x { Post.comment_size = size }  gravatar_default_size = size 40-gravatar_link x       = gravatarWith (x.author_email) Nothing gravatar_default_size Nothing+gravatar_link x       = gravatarWith (x.author_email) def gravatar_default_size def
src/Panda/Type/Extension.hs view
@@ -11,6 +11,6 @@   deriving (Show, Read, Eq)  -to_extension s   = s.camel_case.read :: Extension-to_extensions xs = xs.map to_extension+read_data s   = s.camel_case.read+read_data_list xs = xs.map read_data 
src/Panda/Type/Pager.hs view
@@ -1,5 +1,7 @@ module Panda.Type.Pager where-  ++import Data.Default+ data Pager = Pager {   length :: Int,   current :: Int,@@ -9,5 +11,9 @@   previous :: Int   }   deriving (Eq, Show)++instance Default Bool where+  def = False   -empty = Pager 0 0 False False 0 0+instance Default Pager where+  def = Pager def def def def def def
src/Panda/Type/Reader.hs view
@@ -8,9 +8,12 @@ import Text.Pandoc import Control.Arrow ((>>>)) import Text.XHtml.Strict-import Data.Generics+import Data.Default -data Reader = Markdown | RST | HTML | Latex deriving (Show, Eq, Typeable, Data)+data Reader = Markdown | RST | HTML | Latex deriving (Show, Eq)++instance Default Reader where+  def = Markdown  readers =    [ (Markdown,  ["markdown", "md"])
− src/Panda/Type/Sidebar.hs
@@ -1,20 +0,0 @@-module Panda.Type.Sidebar where--import Panda.Helper.Env hiding (body)-import Prelude hiding ((.), (/), (^), id, readFile)-import Panda.Type.Reader--data SidebarItem = SidebarItem-  { name :: String-  , body :: String-  , reader :: Reader-  }-  deriving (Show, Eq)--instance Markable SidebarItem where-  markup x  = render_to_html (x.reader) (x.body)--read_sidebar_item default_reader s = liftM2 (SidebarItem name) body (return reader) where-  body = s.to_utf8.readFile-  reader = s.take_extension.guess_reader.fromMaybe default_reader-  name = s.takeFileName.dropExtension
src/Panda/Type/State.hs view
@@ -7,6 +7,7 @@ import Control.Arrow ((>>>), (&&&), (***)) import MPS import Prelude hiding ((.), (/), (^), id, readFile, writeFile)+import Data.Default  data State = State   -- model state@@ -33,19 +34,22 @@ display_op Minus = "-"  data HumanTestData = HumanTestData -  { left :: Int+  { left  :: Int   , right :: Int-  , op :: Op+  , op    :: Op   } deriving (Show) +instance Default HumanTestData where+  def = HumanTestData def def def+ data Op = Plus | Minus deriving (Show) -empty            = State "" Pager.empty [] "" "" empty_human_test-empty_human_test = HumanTestData 0 0 Plus+instance Default Op where+  def = Plus +instance Default State where+  def = State def def def def def def -(^) = (<.>)-infixl 9 ^  ops = [Plus, Minus] nums = [0, 5, 10, 15, 20]
+ src/Panda/Type/StaticWidget.hs view
@@ -0,0 +1,20 @@+module Panda.Type.StaticWidget where++import Panda.Helper.Env hiding (body)+import Prelude hiding ((.), (/), (^), id, readFile)+import Panda.Type.Reader++data StaticWidget = StaticWidget+  { name :: String+  , body :: String+  , reader :: Reader+  }+  deriving (Show, Eq)++instance Markable StaticWidget where+  markup x  = render_to_html (x.reader) (x.body)++read_static_widget default_reader s = liftM2 (StaticWidget name) body (return reader) where+  body = s.to_utf8.readFile+  reader = s.take_extension.guess_reader.fromMaybe default_reader+  name = s.takeFileName.dropExtension
src/Panda/Type/Theme.hs view
@@ -14,31 +14,34 @@   , css         :: [String]   , js          :: [String]   } deriving (Show, Read)-  ++data ThemeData = +    Name+  | Container+  | Header+  | Navigation+  | Main+  | Sidebar+  | Footer+  | Css+  | Js+  deriving (Eq, Show, Read)+ to_theme xs = Theme -  { name        = at "name"-  , container   = at "container"-  , header      = at "header"-  , navigation  = at "navigation"-  , main        = at "main"-  , sidebar     = at "sidebar"-  , footer      = at "footer"-  , css         = at "css" .css_list-  , js          = at "js"  .js_list+  { name        = at Name+  , container   = at Container+  , header      = at Header+  , navigation  = at Navigation+  , main        = at Main+  , sidebar     = at Sidebar+  , footer      = at Footer+  , css         = at Css .css_list+  , js          = at Js  .js_list   }   where-    at s = xs.lookup s .fromJust-    css_list s = s.parse_list.map (\x -> "/theme/" ++ at "name" ++ "/css/" ++ x ++ ".css")-    js_list s  = s.parse_list.map (\x -> "/theme/" ++ at "name" ++ "/js/" ++ x ++ ".js")-    -blank_theme = Theme-  { name        = ""-  , container   = ""-  , header      = ""-  , navigation  = ""-  , main        = ""-  , sidebar     = ""-  , footer      = ""-  , css         = [""]-  , js          = [""]-  }+    at s = xs.lookup (s.show_data) .fromJust+    css_list s = s.parse_list.map (\x -> "/theme/" ++ at Name ++ "/css/" ++ x ++ ".css")+    js_list s  = s.parse_list.map (\x -> "/theme/" ++ at Name ++ "/js/" ++ x ++ ".js")++instance Default Theme where+  def = Theme def def def def def def def def def
src/Panda/View/Control/Post.hs view
@@ -22,7 +22,7 @@  -- entry view view state xs x = (x.render_data +++ comment_view ).page state-  where comment_view = for_extension Comment $ CommentV.list xs +++ CommentV.create state (x.uid.Comment.from_post_id)+  where comment_view = only_for Comment $ CommentV.list xs +++ CommentV.create state (x.uid.Comment.from_post_id)  -- list view list state = for_current_page p >>> map render >>> (+++ nav p G.root) >>> page state where 
src/Panda/View/Widget/Footer.hs view
@@ -5,7 +5,7 @@ import qualified Panda.Config.Global as G  -footer c = div_class_id c "footer" <<+static_footer c = toHtml   [ toHtml $ copyright   , toHtml $ "2008 "   , toHtml $ G.blog_title@@ -15,3 +15,8 @@   , toHtml $ " using "   , toHtml $ hotlink "http://www.haskell.org/" << "Haskell"   ]+  +custom_footer _ | G.footer.isJust =  G.footer.fromJust.markup+custom_footer x = static_footer x++footer c = div_class_id c "footer" << custom_footer c
src/Panda/View/Widget/RSS.hs view
@@ -14,8 +14,8 @@ -- RSS channel_rss_template = [ RSS.Language "en-us" ] -render_rss x | G.summary_for_rss.is True = x.markup_summary.show-render_rss x | otherwise                 = x.markup.show+render_rss x  | G.summary_for_rss.is True = x.markup_summary.show+              | otherwise                 = x.markup.show  item_rss_template x =    [ Title $ x.Post.title@@ -25,8 +25,11 @@   , PubDate $ x.date   ] -item_uri x = nullURI { uriScheme = "http://", uriPath = host_link (x.uri) }-rss_uri x  = nullURI { uriScheme = "http://", uriPath = host_link x }+instance Default URI where+  def = nullURI++item_uri x = def { uriScheme = "http://", uriPath = host_link (x.uri) }+rss_uri x  = def { uriScheme = "http://", uriPath = host_link x }  rss categary s xs = RSS title  (rss_uri link) title channel_rss_template (xs.take 20 .map item_rss_template)   .rssToXML.showXML
src/Panda/View/Widget/SearchBar.hs view
@@ -6,4 +6,4 @@ import Panda.Type.Extension import Panda.Helper.StateHelper -search_bar = for_extension Search $ div_id "search" << form ! [action (G.root / "search"), method "get"] << thediv << textfield "s"+search_bar = only_for Search $ div_id "search" << form ! [action (G.root / "search"), method "get"] << thediv << textfield "s"
src/Panda/View/Widget/Sidebar.hs view
@@ -6,7 +6,7 @@  import qualified Data.Set as Set import qualified Panda.Config.Global as G-import qualified Panda.Type.Sidebar as Sidebar+import qualified Panda.Type.StaticWidget as Sidebar import Panda.View.Widget.Helper  -- model
src/Panda/View/Widget/Template.hs view
@@ -27,7 +27,7 @@     , div_id "page" << [ div_class (t.T.main) << body_content x, sidebar (t.T.sidebar) state ]     , footer (t.T.footer)     ]-  , for_extension Analytics $ primHtml analytics_snippet+  , only_for Analytics $ primHtml analytics_snippet   ]  template t state x = [html_head state, body t state x]