packages feed

panda 2008.10.27 → 2008.11.6

raw patch · 40 files changed

+185/−151 lines, 40 filesdep ~pandocdep ~utf8-stringPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: pandoc, utf8-string

API changes (from Hackage documentation)

- Panda.Config.Global: AnalyticsAccountId :: ConfigData
- Panda.Config.Global: AuthorEmail :: ConfigData
- Panda.Config.Global: BlogSubtitle :: ConfigData
- Panda.Config.Global: BlogTitle :: ConfigData
- Panda.Config.Global: CommentDateFormat :: ConfigData
- Panda.Config.Global: Cut :: ConfigData
- Panda.Config.Global: Extensions :: ConfigData
- Panda.Config.Global: Favicon :: ConfigData
- Panda.Config.Global: Footer :: ConfigData
- Panda.Config.Global: HostName :: ConfigData
- Panda.Config.Global: Navigation :: ConfigData
- Panda.Config.Global: PerPage :: ConfigData
- Panda.Config.Global: PostDateFormat :: ConfigData
- Panda.Config.Global: Root :: ConfigData
- Panda.Config.Global: Sidebar :: ConfigData
- Panda.Config.Global: SummaryForRoot :: ConfigData
- Panda.Config.Global: SummaryForRss :: ConfigData
- Panda.Config.Global: SummaryForTag :: ConfigData
- Panda.Config.Global: Theme :: ConfigData
- Panda.Config.Global: UrlDateFormat :: ConfigData
- Panda.Config.Global: UrlDateMatcher :: ConfigData
- Panda.Config.Global: UrlDateTitleSeperator :: ConfigData
- Panda.Config.Global: UrlTitleSubs :: ConfigData
- Panda.Config.Global: data ConfigData
- Panda.Config.Global: instance Show ConfigData
- Panda.Helper.Helper: class Addressable a
- Panda.Helper.Helper: class DataRenderer a
- Panda.Helper.Helper: class Datable a
- Panda.Helper.Helper: class Markable a
- Panda.Helper.Helper: class Resource a
- Panda.Helper.Helper: date :: (Datable a) => a -> CalendarTime
- Panda.Helper.Helper: markup :: (Markable a) => a -> Html
- Panda.Helper.Helper: render_data :: (DataRenderer a) => a -> Html
- Panda.Helper.Helper: resource_title :: (Resource a) => a -> String
- Panda.Helper.Helper: uri :: (Addressable a) => a -> String
- Panda.Model.Comment: Author :: CommentData
- Panda.Model.Comment: AuthorEmail :: CommentData
- Panda.Model.Comment: AuthorLink :: CommentData
- Panda.Model.Comment: Body :: CommentData
- Panda.Model.Comment: Comment :: String -> String -> String -> String -> String -> Comment
- Panda.Model.Comment: EmptyField :: SpamFilter
- Panda.Model.Comment: HumanHack :: SpamFilter
- Panda.Model.Comment: LeftNumber :: SpamFilter
- Panda.Model.Comment: Operator :: SpamFilter
- Panda.Model.Comment: PostId :: CommentData
- Panda.Model.Comment: RightNumber :: SpamFilter
- Panda.Model.Comment: author :: Comment -> String
- Panda.Model.Comment: author_email :: Comment -> String
- Panda.Model.Comment: author_link :: Comment -> String
- Panda.Model.Comment: body :: Comment -> String
- Panda.Model.Comment: data Comment
- Panda.Model.Comment: data CommentData
- Panda.Model.Comment: data SpamFilter
- Panda.Model.Comment: instance Datable Comment
- Panda.Model.Comment: instance Default Comment
- Panda.Model.Comment: instance Eq Comment
- Panda.Model.Comment: instance Markable Comment
- Panda.Model.Comment: instance Resource Comment
- Panda.Model.Comment: instance Show Comment
- Panda.Model.Comment: instance Show CommentData
- Panda.Model.Comment: instance Show SpamFilter
- Panda.Model.Comment: uid :: Comment -> String
- Panda.Model.Post: Post :: String -> String -> String -> [String] -> Int -> Reader -> Post
- Panda.Model.Post: body :: Post -> String
- Panda.Model.Post: comment_size :: Post -> Int
- Panda.Model.Post: data Post
- Panda.Model.Post: instance Addressable Post
- Panda.Model.Post: instance Datable Post
- Panda.Model.Post: instance Eq Post
- Panda.Model.Post: instance Markable Post
- Panda.Model.Post: instance Resource Post
- Panda.Model.Post: instance Show Post
- Panda.Model.Post: reader :: Post -> Reader
- Panda.Model.Post: tags :: Post -> [String]
- Panda.Model.Post: title :: Post -> String
- Panda.Model.Post: uid :: Post -> String
- Panda.Model.Static: Static :: String -> String -> Reader -> Static
- Panda.Model.Static: body :: Static -> String
- Panda.Model.Static: data Static
- Panda.Model.Static: instance Eq Static
- Panda.Model.Static: instance Markable Static
- Panda.Model.Static: instance Resource Static
- Panda.Model.Static: instance Show Static
- Panda.Model.Static: reader :: Static -> Reader
- Panda.Model.Static: uid :: Static -> String
- Panda.Model.Tag: Tag :: String -> String -> Set String -> Tag
- Panda.Model.Tag: data Tag
- Panda.Model.Tag: instance Eq Tag
- Panda.Model.Tag: instance Resource Tag
- Panda.Model.Tag: instance Show Tag
- Panda.Model.Tag: name :: Tag -> String
- Panda.Model.Tag: resources :: Tag -> Set String
- Panda.Model.Tag: uid :: Tag -> String
- Panda.Type.Extension: Analytics :: Extension
- Panda.Type.Extension: Comment :: Extension
- Panda.Type.Extension: Search :: Extension
- Panda.Type.Extension: data Extension
- Panda.Type.Extension: instance Eq Extension
- Panda.Type.Extension: instance Read Extension
- Panda.Type.Extension: instance Show Extension
- Panda.Type.Pager: Pager :: Int -> Int -> Bool -> Bool -> Int -> Int -> Pager
- Panda.Type.Pager: current :: Pager -> Int
- Panda.Type.Pager: data Pager
- Panda.Type.Pager: has_next :: Pager -> Bool
- Panda.Type.Pager: has_previous :: Pager -> Bool
- Panda.Type.Pager: instance Default Bool
- Panda.Type.Pager: instance Default Pager
- Panda.Type.Pager: instance Eq Pager
- Panda.Type.Pager: instance Show Pager
- Panda.Type.Pager: length :: Pager -> Int
- Panda.Type.Pager: next :: Pager -> Int
- Panda.Type.Pager: previous :: Pager -> Int
- Panda.Type.Reader: HTML :: Reader
- Panda.Type.Reader: Latex :: Reader
- Panda.Type.Reader: Markdown :: Reader
- Panda.Type.Reader: RST :: Reader
- Panda.Type.Reader: data Reader
- Panda.Type.Reader: instance Default Reader
- Panda.Type.Reader: instance Eq Reader
- Panda.Type.Reader: instance Show Reader
- Panda.Type.State: HumanTestData :: Int -> Int -> Op -> HumanTestData
- Panda.Type.State: Minus :: Op
- Panda.Type.State: Plus :: Op
- Panda.Type.State: State :: String -> Pager -> [Tag] -> String -> String -> HumanTestData -> State
- Panda.Type.State: data HumanTestData
- Panda.Type.State: data Op
- Panda.Type.State: data State
- Panda.Type.State: human_test_data :: State -> HumanTestData
- Panda.Type.State: instance Default HumanTestData
- Panda.Type.State: instance Default Op
- Panda.Type.State: instance Default State
- Panda.Type.State: instance Show HumanTestData
- Panda.Type.State: instance Show Op
- Panda.Type.State: instance Show State
- Panda.Type.State: left :: HumanTestData -> Int
- Panda.Type.State: nav_location :: State -> String
- Panda.Type.State: op :: HumanTestData -> Op
- Panda.Type.State: pager :: State -> Pager
- Panda.Type.State: resource_title :: State -> String
- Panda.Type.State: right :: HumanTestData -> Int
- Panda.Type.State: tags :: State -> [Tag]
- Panda.Type.State: uid :: State -> String
- Panda.Type.StaticWidget: StaticWidget :: String -> String -> Reader -> StaticWidget
- Panda.Type.StaticWidget: body :: StaticWidget -> String
- Panda.Type.StaticWidget: data StaticWidget
- Panda.Type.StaticWidget: instance Eq StaticWidget
- Panda.Type.StaticWidget: instance Markable StaticWidget
- Panda.Type.StaticWidget: instance Show StaticWidget
- Panda.Type.StaticWidget: name :: StaticWidget -> String
- Panda.Type.StaticWidget: reader :: StaticWidget -> Reader
- Panda.Type.Theme: Container :: ThemeData
- Panda.Type.Theme: Css :: ThemeData
- Panda.Type.Theme: Footer :: ThemeData
- Panda.Type.Theme: Header :: ThemeData
- Panda.Type.Theme: Js :: ThemeData
- Panda.Type.Theme: Main :: ThemeData
- Panda.Type.Theme: Name :: ThemeData
- Panda.Type.Theme: Navigation :: ThemeData
- Panda.Type.Theme: Sidebar :: ThemeData
- Panda.Type.Theme: Theme :: String -> String -> String -> String -> String -> String -> String -> [String] -> [String] -> Theme
- Panda.Type.Theme: container :: Theme -> String
- Panda.Type.Theme: css :: Theme -> [String]
- Panda.Type.Theme: data Theme
- Panda.Type.Theme: data ThemeData
- Panda.Type.Theme: footer :: Theme -> String
- Panda.Type.Theme: header :: Theme -> String
- Panda.Type.Theme: instance Default Theme
- Panda.Type.Theme: instance Eq ThemeData
- Panda.Type.Theme: instance Read Theme
- Panda.Type.Theme: instance Read ThemeData
- Panda.Type.Theme: instance Show Theme
- Panda.Type.Theme: instance Show ThemeData
- Panda.Type.Theme: js :: Theme -> [String]
- Panda.Type.Theme: main :: Theme -> String
- Panda.Type.Theme: name :: Theme -> String
- Panda.Type.Theme: navigation :: Theme -> String
- Panda.Type.Theme: sidebar :: Theme -> String
- Panda.View.Atom.Comment: instance DataRenderer Comment
- Panda.View.Atom.Post: Full :: RenderStyle
- Panda.View.Atom.Post: Summary :: RenderStyle
- Panda.View.Atom.Post: data RenderStyle
- Panda.View.Atom.Post: instance DataRenderer Post
- Panda.View.Atom.Static: instance DataRenderer Static
- Panda.View.Atom.Tag: instance DataRenderer Tag
- Panda.View.Widget.RSS: instance Default URI
- Panda.View.Widget.Template: page :: (HTML a) => State -> a -> [Html]

Files

changelog.markdown view
@@ -1,3 +1,10 @@+2008.11.6+----------++### Fix++* Work with utf8-string 0.3.2+ 2008.10.27 ----------- 
panda.cabal view
@@ -1,5 +1,5 @@ Name:                 panda-Version:              2008.10.27+Version:              2008.11.6 Build-type:           Simple Synopsis:             A simple static blog engine Description:          A simple static blog engine@@ -14,11 +14,12 @@ data-files:			  readme.markdown, changelog.markdown  library-  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+  ghc-options: -Wall -fno-warn-missing-signatures -fno-warn-name-shadowing -fno-warn-orphans -fno-warn-type-defaults+  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.2, pandoc, parsec >= 2, MissingH, gravatar >= 0.3, data-default >= 0.2   hs-source-dirs: src/   exposed-modules:  -                    Main-                    +                    Panda+  other-modules:                     Panda.Config.Global                      Panda.Controller.Application@@ -27,6 +28,7 @@                      Panda.Helper.Env                     Panda.Helper.Helper+                    Panda.Helper.PreludeEnv                     Panda.Helper.StateHelper                      Panda.Model.Comment@@ -64,5 +66,5 @@                     Panda.View.Widget.SearchBar                     Panda.View.Widget.Sidebar                     Panda.View.Widget.Template--                    Panda+  +  
− src/Main.hs
@@ -1,5 +0,0 @@-module Main where--import Panda--main = panda
src/Panda.hs view
@@ -7,4 +7,5 @@ import Panda.Controller.Application import Kibro +panda :: IO () panda = startKibro pages
src/Panda/Config/Global.hs view
@@ -1,16 +1,14 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Panda.Config.Global where  import Panda.Helper.Helper-import MPS-import Prelude hiding ((.), (/), (^), id, readFile)+import Panda.Helper.PreludeEnv -import System.FilePath hiding ((<.>))-import Control.Arrow ((>>>), (&&&), (***))+import Control.Arrow ((>>>)) import Data.Maybe-import System.Directory import Data.Default -import Panda.Type.Reader import Panda.Type.StaticWidget import Panda.Type.Theme ( to_theme ) import Panda.Type.Extension@@ -90,12 +88,12 @@ default_reader  = def  load_widget = read_static_widget default_reader >>> purify-sidebar = for_list' Sidebar "" .map (sidebar_uri /).select (to_utf8 >>> doesFileExist >>> purify )+sidebar = for_list' Sidebar "" .map (sidebar_uri /).select (file_exist >>> purify )   .map load_widget  footer  = for Footer    .(footer_uri / ) -  .(\x -> if x.to_utf8.doesFileExist.purify then Just $ load_widget x else Nothing)+  .(\x -> if x.file_exist.purify then Just $ load_widget x else Nothing)    favicon = for' Favicon "/favicon.ico" @@ -108,7 +106,7 @@ user_theme_name = for Theme user_theme_uri  = (theme_uri / user_theme_name) ++ ".txt" -theme = if user_theme_uri.doesFileExist.purify+theme = if user_theme_uri.file_exist.purify   then parse_config user_theme_uri .(("name", user_theme_name) : ) .to_theme   else default_theme   @@ -122,7 +120,7 @@ url_date_title_seperator = for' UrlDateTitleSeperator " "  -- summary-cut              = for' Cut "✂-----" .to_utf8+cut              = for' Cut "✂-----" parse_boolean    = belongs_to ["true", "1", "y", "yes", "yeah"] summary_for_root = for SummaryForRoot .parse_boolean summary_for_tag  = for SummaryForTag  .parse_boolean
src/Panda/Controller/Application.hs view
@@ -3,9 +3,10 @@ -- views are pure functions.  -- a note on encoding:--- IOs are in utf-8 filter, internally use bytes+-- uniform utf-8 enforced by custom io wrapper -{-# OPTIONS -fno-monomorphism-restriction #-}+{-# LANGUAGE NoMonomorphismRestriction#-}+{-# LANGUAGE NoImplicitPrelude #-}  module Panda.Controller.Application where @@ -14,7 +15,6 @@ -- env import Panda.Helper.Env hiding (tag, uri) 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 import qualified Panda.Type.Pager as Pager@@ -28,7 +28,6 @@  -- view import qualified Panda.View.Control.Post as PostV-import qualified Panda.View.Widget.Template as T import qualified Panda.View.Control.Static as StaticV import qualified Panda.View.Control.Tag as TagV import qualified Panda.View.Control.Search as SearchV@@ -132,8 +131,8 @@  comment_create = do   post_id <- input_with_default (show_data Comment.PostId) (G.post_id / "nothing")-  exists <- (G.flat_uri / post_id.to_utf8) .doesFileExist .u-  let valid_path = equalFilePath G.post_id (takeDirectory post_id)+  exists <- (G.flat_uri / post_id) .file_exist .u +  let valid_path = equalFilePath G.post_id (takeDirectory post_id)    checked <- check_create      if [checked, valid_path, exists].and@@ -141,7 +140,7 @@       inputs >>= (Comment.create >>> u)     else       return ()-  redirect $ (post_id.Post.id_to_uri.to_utf8).urlEncode+  redirect $ (post_id.Post.id_to_uri.u2b).urlEncode  get_input_data = show_data >>> get_input 
src/Panda/Extension/Analytics/T.hs view
@@ -1,7 +1,8 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Panda.Extension.Analytics.T where  import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Config.Global as G  analytics_snippet = 
src/Panda/Helper/Env.hs view
@@ -1,8 +1,10 @@+{-# LANGUAGE NoImplicitPrelude #-}+ -- this sets some scoping for every module, which prevents importing -- common modules in every file  module Panda.Helper.Env  (-    module MPS                 +    module Panda.Helper.PreludeEnv   , module Control.Monad          , module Control.Arrow          , module Data.List           @@ -21,16 +23,16 @@   , module Data.Default ) where   -import MPS hiding (base, col, sub, date)-import Control.Monad hiding (join)+import Panda.Helper.PreludeEnv hiding (FilePath)+import Control.Monad (liftM2, liftM3, liftM4, liftM5)  import Control.Arrow ((>>>), (&&&), (***))-import Data.List hiding (find)+import Data.List (isSuffixOf, isInfixOf, sortBy, intersperse)  import Network.URI import Network.CGI hiding (Html) import System.Locale import System.Time.Parse import Panda.Helper.Helper-import Data.Maybe+import Data.Maybe (fromMaybe, fromJust, isJust, isNothing) import System.FilePath hiding ((<.>)) import System.IO.UTF8 (readFile, writeFile) import Text.XHtml.Strict hiding (select)
src/Panda/Helper/Helper.hs view
@@ -2,58 +2,63 @@ -- for this project, more general helpers are usually moved -- to MPS package, for multi-project usage -{-# OPTIONS -fno-monomorphism-restriction #-}+{-# LANGUAGE NoMonomorphismRestriction#-}+{-# LANGUAGE NoImplicitPrelude #-}  module Panda.Helper.Helper where +import Panda.Helper.PreludeEnv+import qualified MPS as MPS import System.IO.UTF8 (readFile, writeFile) import Network.URI import Network.CGI-import System.FilePath.Posix ((</>))-import Control.Arrow ((>>>), (&&&))-import Text.XHtml.Strict+import Control.Arrow ((>>>))+import Text.XHtml.Strict hiding (p) import Control.Monad hiding (join) import Data.Maybe-import Panda.Type.Pager as Pager-import MPS hiding (date)-import Prelude hiding ((.), (/), (^), id, readFile, writeFile)+import qualified Panda.Type.Pager as Pager import Char-import Data.List+import Data.List hiding (length) import qualified Data.List as L  import Panda.Type.Reader import System.FilePath.Posix hiding ((<.>)) import System.Time-import Data.Default-+import System.Directory +(/) :: FilePath -> FilePath -> FilePath (/) = (</>) infixl 5 /  -- global-parse_config_io s = readFile s ^ (\x -> x.filter_comment.lines.map strip .map (split "\\s*=\\s*") .map fill_snd_blank .map tuple2)+parse_config_io s = read_file s ^ (\x -> x.filter_comment.lines.map strip .map (split "\\s*=\\s*") .map fill_snd_blank .map tuple2)   where fill_snd_blank [x] = [x,""]         fill_snd_blank xs = xs-parse_config = parse_config_io >>> purify -write_config_io s xs = xs.map(\(x, y) -> x ++ " = " ++ y) .join "\n" .writeFile s+parse_config         = parse_config_io >>> purify+write_config_io s xs = xs.map(\(x, y) -> x ++ " = " ++ y) .join "\n" .write_file s  -- model take_extension = takeExtension >>> split "\\." >>> last+drop_known_extension s+  | s.take_extension.belongs_to exts = dropExtension s+  | otherwise = s+  where exts = readers.only_snd.join'  -- controller-raw_uri = requestURI ^ (uriPath >>> urlDecode >>> tail >>> remove_trailing_slash >>> from_utf8 )+raw_uri = requestURI ^ (uriPath >>> urlDecode >>> tail >>> remove_trailing_slash )+ remove_trailing_slash s = if s.last.is '/' then s.init else s-  + params = do   query_string <- requestURI ^ uriQuery    case query_string of-    '?':s -> s.formDecode .map_snd unescape_unicode_xml.return-    otherwise -> return []+    '?':s -> s.formDecode .map_snd ( unescape_unicode_xml ) .return+    _ -> return []  inputs = getInputs ^ map_snd (strip >>> unescape_unicode_xml) -param_with_default s d = params ^ (lookup s >>> fromMaybe d )-input_with_default s d = inputs ^ (lookup s >>> fromMaybe d )+param_with_default s d = get_param s ^ fromMaybe d+input_with_default s d = get_input s ^ fromMaybe d  get_param s = params ^ lookup s get_input s = inputs ^ lookup s@@ -61,19 +66,19 @@ just_param s = get_param s ^ fromJust just_input s = get_input s ^ fromJust -full_paginate length total = liftM5 ( Pager length ) current has_next has_previous next previous where+full_paginate length total = liftM5 ( Pager.Pager length ) current has_next has_previous next previous where   current      = param_with_default "page" "1" ^ read-  has_next     = current ^ ( (* length) >>> (< total.fromIntegral) )+  has_next     = current ^ ( (* length) >>> (< total.from_i) )   has_previous = current ^ (> 1)   next         = current ^ (+ 1)-  previous     = current ^ (+ (-1) )+  previous     = current ^ (+ (-1))   for_current_page p xs = xs.drop ((p.Pager.current - 1) * p.Pager.length) .take (p.Pager.length)  -- id: /type/resoruce-id_to_type id     = id.split "/" .first-id_to_resource id = id.split "/" .tail.join "/"+id_to_type x     = x.split "/" .first+id_to_resource x = x.split "/" .tail.join "/" no_navigation     = "" home_nav          = "Home" @@ -121,3 +126,17 @@  class Addressable a where     uri :: a -> String++++-- io+b2u        = from_utf8+u2b        = to_utf8++read_file  = readFile+write_file = writeFile+ls x       = MPS.ls (x.u2b) ^ map b2u+mkdir_p    = u2b >>> createDirectoryIfMissing True++file_exist = u2b >>> doesFileExist+dir_exist = u2b >>> doesDirectoryExist
+ src/Panda/Helper/PreludeEnv.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE NoImplicitPrelude #-}++module Panda.Helper.PreludeEnv  (+    module MPS+  , module Prelude+  , split+  , gsub+  , match+) where++import Prelude hiding ((.), (/), (^), id, span, readFile, writeFile)+import MPS hiding (base, col, sub, date, ls, match, gsub, split)+import qualified MPS as MPS++-- io for statehelper+b2u        = from_utf8+u2b        = to_utf8+split x y  = MPS.split (x.u2b) (y.u2b) .map b2u+gsub x y z = MPS.gsub (x.u2b) (y.u2b) (z.u2b) .b2u+match x y  = MPS.match (x.u2b) (y.u2b)
src/Panda/Helper/StateHelper.hs view
@@ -1,14 +1,13 @@ -- trying to merge this helper with the generic one results in cyclic imports -{-# OPTIONS -fno-monomorphism-restriction #-}+{-# LANGUAGE NoMonomorphismRestriction#-}+{-# LANGUAGE NoImplicitPrelude #-}  module Panda.Helper.StateHelper where  import Panda.Helper.Env import qualified Panda.Config.Global as G-import Prelude hiding ((.), (/), (^), id) - -- G.root = /blog -- raw_uri = blog/x -- full_uri = /blog/x@@ -17,7 +16,7 @@   | G.root.is "/" = s   | otherwise     = s.slice (G.root.length) (s.length) -uri = raw_uri ^ remove_root+uri = raw_uri ^ b2u ^ remove_root -- uri = raw_uri  @@ -41,6 +40,6 @@  cut       = G.cut cut_re    = "^\\s*" ++ cut-match_cut = to_utf8 >>> match cut_re+match_cut = match cut_re is_cut    = match_cut >>> isJust-split_cut = to_utf8 >>> split cut_re+split_cut = split cut_re
src/Panda/Model/Comment.hs view
@@ -1,12 +1,12 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Panda.Model.Comment where  -- env import Panda.Helper.Env hiding (title, body, size, path, meta)-import Prelude hiding ((.), (/), (^), id, readFile, writeFile) import qualified Panda.Config.Global as G import Panda.Type.Reader import qualified Panda.Model.Post as Post-import System.Directory import Panda.Helper.StateHelper import Network.Gravatar @@ -49,34 +49,34 @@  -- CRUD list_for post_id = do-  has_comments <- doesDirectoryExist d+  has_comments <- dir_exist d   if has_comments-    then ls d ^ reject (match "\\.meta$" >>> isJust) ^ rsort ^ map (G.comment_id / r /) >>= mapM (from_utf8 >>> get)+    then ls d ^ reject (isSuffixOf ".meta") ^ rsort ^ map (G.comment_id / r /) >>= mapM get     else return []   where     d = (G.comment_uri / r)-    r = post_id.id_to_resource.to_utf8+    r = post_id.id_to_resource -path id = G.flat_uri / id.to_utf8+path id = G.flat_uri / id meta = (++ ".meta")  get id = do-  meta_exists <- id.path.meta.doesFileExist+  meta_exists <- id.path.meta.file_exist   if meta_exists     then get_from_new_format id     else get_from_old_format id  get_from_new_format id = do-  body <- id.path.readFile+  body <- id.path.read_file   meta <- id.path.meta.parse_config_io   let at s         = meta.lookup (s.show_data) .fromJust   let author       = at Author   let author_email = at AuthorEmail   let author_link  = at AuthorLink-  return $ Comment id author body author_email author_link+  return $ Comment id author body author_email author_link   get_from_old_format id = do-  xs <- id.path.readFile ^ lines+  xs <- id.path.read_file ^ lines   let author = xs.first   let author_email = ""   let author_link = xs.drop 2.first@@ -89,11 +89,11 @@   let post_id     = at PostId    timestamp <- ( getClockTime >>= toCalendarTime ) ^ format_date G.comment_date_format-  let comment_path = post_id_to_uid post_id .to_utf8-  createDirectoryIfMissing True comment_path+  let comment_path = post_id_to_uid post_id +  mkdir_p comment_path      let uid = comment_path / timestamp-  writeFile uid body+  write_file uid body   let meta = [Author, AuthorLink, AuthorEmail] .labeling at .map_fst show_data   write_config_io (uid ++ ".meta") meta 
src/Panda/Model/Post.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE NoImplicitPrelude #-}+ -- what about the performance? -- Haskell takes care of that, since IOs are also lazy. -- Posts are not read unless specifically required, i.e. after pagination@@ -7,7 +9,6 @@ -- env import Panda.Helper.Env hiding (match, title, body, date) import qualified MPS as MPS-import Prelude hiding ((.), (/), (^), id, readFile) import qualified Panda.Config.Global as G import Panda.Type.Reader import Panda.Helper.StateHelper hiding (uri)@@ -36,12 +37,12 @@   uri = uid >>> id_to_uri  -- CRUD-list = ls G.post_uri ^ map from_utf8 ^ rsort ^ map (G.post_id /) >>= mapM get+list = ls G.post_uri ^ rsort ^ map (G.post_id /) >>= mapM get  get id        = liftM4 (Post id (get_title id) ) (get_body id) (return []) (return 0) (return $ get_reader id) get_extension = takeExtension-get_title id  = id.words.tail.unwords.dropExtension-get_body id   = (G.flat_uri / id.to_utf8) .readFile+get_title id  = id.words.tail.unwords.drop_known_extension+get_body id   = (G.flat_uri / id) .read_file get_reader id = id.take_extension.guess_reader.fromMaybe G.default_reader get_date id   = id.words.first.split "/".last.default_parse_date @@ -49,7 +50,7 @@ search "" = return [] search s  = list ^ filter (match s) -summary = body >>> split_cut >>> first >>> from_utf8+summary = body >>> split_cut >>> first full x | x.body.match_cut.isNothing = x.body full x = ( xs.takeWhile not_cut ++ xs.dropWhile not_cut .tail ).unlines where   not_cut = is_cut >>> not@@ -65,7 +66,7 @@   ext = id.get_extension  uri_to_id s = G.post_id / (d ++ " " ++ t) where-  (raw_d, (prefix, title_with_sep)) = s.MPS.match G.url_date_matcher.fromJust.fst+  (raw_d, (_, title_with_sep)) = s.MPS.match G.url_date_matcher.fromJust.fst   raw_t = title_with_sep.drop (G.url_date_title_seperator.length)   t = G.url_title_subs.map (\(a,b) -> gsub b a) .inject raw_t apply   d = raw_d.parse_date G.url_date_format .fromJust.format_date G.post_date_format
src/Panda/Model/Static.hs view
@@ -1,8 +1,8 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Model.Static where  -- env import Panda.Helper.Env hiding (match, body)-import Prelude hiding ((.), (/), (^), id, readFile) import qualified Panda.Config.Global as G import Panda.Type.Reader @@ -21,8 +21,8 @@    -- CRUD get id        = liftM2 (Static id) (get_body id) (return $ get_reader id)-get_title     = id_to_resource >>> dropExtension-get_body id   = (G.flat_uri / id.to_utf8) .readFile+get_title     = id_to_resource >>> drop_known_extension+get_body id   = (G.flat_uri / id) .read_file get_reader id = id.take_extension.guess_reader.fromMaybe G.default_reader  title = uid >>> get_title
src/Panda/Model/Tag.hs view
@@ -1,10 +1,10 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Model.Tag where  import qualified Panda.Model.Post as Post  -- env import Panda.Helper.Env hiding (name)-import Prelude hiding ((.), (/), (^), id, readFile) import qualified Data.Set as S import qualified Panda.Config.Global as G @@ -20,11 +20,11 @@   resource_title = uid >>> spaced_url  -- CRUD-list             = ls G.tag_uri ^ map from_utf8 ^ map (G.tag_id /) >>= mapM get+list             = ls G.tag_uri ^ map (G.tag_id /) >>= mapM get  get id           = get_resources id ^ Tag id (get_name id) get_name id      = id.split "/" .tail.join'-get_resources id = (G.flat_uri / id.to_utf8) .readFile+get_resources id = (G.flat_uri / id) .read_file   ^ filter_comment ^ lines ^ map (G.post_id / ) ^ to_set  resource_title_from_name = name_to_id >>> spaced_url
src/Panda/Type/Extension.hs view
@@ -1,8 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Type.Extension where  import Panda.Helper.Env hiding (body)-import Prelude hiding ((.), (/), (^), id, readFile)-  data Extension =      Comment
src/Panda/Type/Reader.hs view
@@ -1,9 +1,8 @@-{-# OPTIONS -XDeriveDataTypeable #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Panda.Type.Reader where -import MPS  -import Prelude hiding ((.), (/), (^), id)+import Panda.Helper.PreludeEnv import qualified Data.Map as Map import Text.Pandoc import Control.Arrow ((>>>))@@ -22,19 +21,20 @@   , (Latex,     ["tex", "latex"])   ] -gen_lookup (r, xs) = xs.labeling (const r)-reader_map         = readers.map gen_lookup.join'.to_h-guess_reader ext   = reader_map.Map.lookup ext +reader_map  = readers.map gen_lookup.join'.to_h+  where gen_lookup (r, xs) = xs.labeling (const r) -to_html r      = r defaultParserState >>> writeHtml defaultWriterOptions+guess_reader ext = reader_map.Map.lookup ext +to_html r = r defaultParserState >>> writeHtml defaultWriterOptions+ -- this list can go on, as long as there is a library that does -- the convertion. pretty extensible, isn't it.+rr :: Reader -> String -> Html rr Markdown    = to_html readMarkdown rr RST         = to_html readRST rr HTML        = primHtml rr Latex       = to_html readLaTeX  render_to_html = rr-
src/Panda/Type/State.hs view
@@ -1,12 +1,12 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Type.State where  import qualified Panda.Type.Pager as Pager import Panda.Model.Tag import Random (randomRs, mkStdGen) import System.Time-import Control.Arrow ((>>>), (&&&), (***))-import MPS-import Prelude hiding ((.), (/), (^), id, readFile, writeFile)+import Control.Arrow ((>>>))+import Panda.Helper.PreludeEnv import Data.Default  data State = State@@ -24,7 +24,7 @@  show_left   = human_test_data >>> left >>> show show_right  = human_test_data >>> right >>> show-show_op     = human_test_data >>> op >>> display_op where+show_op     = human_test_data >>> op >>> display_op  read_op "+" = Plus read_op "-" = Minus@@ -58,12 +58,13 @@   mk_human_test = do-  seed <- (getClockTime >>= toCalendarTime) ^ ctPicosec ^ fromIntegral-  let (a,b,c) = randomRs (0,100) (mkStdGen seed) .in_group_of 3 .map make_sample .dropWhile (good_test >>> not) .first+  seed <- (getClockTime >>= toCalendarTime) ^ ctPicosec ^ from_i+  let (a,b,c) = randomRs (0,100) (mkStdGen seed) .in_group_of 3 .map make_sample .lb good_test .first   return $ HumanTestData a b c    where     make_sample [a,b,c] = ((get_num a), (get_num b), (get_op c))+    make_sample _ = error "human test sample fail"     good_test = splash3 simple_eval >>> belongs_to nums     get_num n = nums.at (n `mod` (nums.length))     get_op  n = ops.at (n `mod` (ops.length))
src/Panda/Type/StaticWidget.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Type.StaticWidget where  import Panda.Helper.Env hiding (body)-import Prelude hiding ((.), (/), (^), id, readFile) import Panda.Type.Reader  data StaticWidget = StaticWidget@@ -15,6 +15,6 @@   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+  body = s.read_file   reader = s.take_extension.guess_reader.fromMaybe default_reader-  name = s.takeFileName.dropExtension+  name = s.takeFileName.drop_known_extension
src/Panda/Type/Theme.hs view
@@ -1,6 +1,6 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.Type.Theme where -import Prelude hiding ((.)) import Panda.Helper.Env hiding (name, header)  data Theme = Theme
src/Panda/View/Atom/Comment.hs view
@@ -1,13 +1,10 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Atom.Comment where-  + import Panda.Helper.Env hiding (title)-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Config.Global as G import Panda.Helper.StateHelper import Panda.Type.State hiding (uid)---- view-import qualified Panda.View.Atom.Tag as Tag  -- model import Panda.Model.Comment hiding (create)
src/Panda/View/Atom/Post.hs view
@@ -1,8 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Atom.Post where    import Panda.Helper.Env hiding (name, title)-import Prelude hiding ((.), (/), (^), id, span)-import qualified Panda.Config.Global as G import Panda.Helper.StateHelper hiding (uri)  -- view
src/Panda/View/Atom/Static.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Atom.Static where    import Panda.Helper.Env
src/Panda/View/Atom/Tag.hs view
@@ -1,9 +1,9 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Atom.Tag where    import Panda.Helper.Env hiding (name) import Panda.Model.Tag import qualified Panda.Config.Global as G-import Prelude hiding ((/))  instance DataRenderer Tag where   render_data = name >>> tag_link
src/Panda/View/Control/Comment.hs view
@@ -1,17 +1,10 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Control.Comment where    import Panda.Helper.Env hiding (body, date)-import Prelude hiding ((.), (/), (^), id, span)-import qualified Panda.Type.State as State -import Panda.Model.Comment hiding (create)-import qualified Panda.Model.Post as Post- -- view-import Panda.View.Control.Helper-import Panda.View.Widget.Template import Panda.View.Atom.Comment as Comment-  -- api styled_entry alt x = li ! [theclass alt] << x.render_data
src/Panda/View/Control/Helper.hs view
@@ -1,11 +1,9 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Control.Helper where  import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span)    import Panda.Type.Pager as Pager-import qualified Panda.Config.Global as G-  nav p r =    [ div_class "alignleft" << nav_previous p r
src/Panda/View/Control/Post.hs view
@@ -1,8 +1,8 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Control.Post where  -- env import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span)  import qualified Panda.Type.State as State import qualified Panda.Config.Global as G
src/Panda/View/Control/Search.hs view
@@ -1,12 +1,11 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Control.Search where    import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Type.State as State import qualified Panda.Config.Global as G  -- view-import Panda.View.Atom.Post import Panda.View.Control.Helper import Panda.View.Widget.Template 
src/Panda/View/Control/Static.hs view
@@ -1,7 +1,9 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Panda.View.Control.Static where    import Panda.Helper.Env-import Panda.View.Atom.Static+import Panda.View.Atom.Static () import Panda.View.Widget.Template  view state = render_data >>> page state
src/Panda/View/Control/Tag.hs view
@@ -1,7 +1,8 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Panda.View.Control.Tag where    import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Type.State as State import qualified Panda.Config.Global as G 
src/Panda/View/Widget/Body.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Body where  -- env
src/Panda/View/Widget/Footer.hs view
@@ -1,11 +1,11 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Footer where    import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Config.Global as G  -static_footer c = toHtml+static_footer = toHtml   [ toHtml $ copyright   , toHtml $ "2008 "   , toHtml $ G.blog_title@@ -16,7 +16,8 @@   , toHtml $ hotlink "http://www.haskell.org/" << "Haskell"   ]   -custom_footer _ | G.footer.isJust =  G.footer.fromJust.markup-custom_footer x = static_footer x+custom_footer +  | G.footer.isJust =  G.footer.fromJust.markup+  | otherwise = static_footer -footer c = div_class_id c "footer" << custom_footer c+footer c = div_class_id c "footer" << custom_footer
src/Panda/View/Widget/Head.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Head where  import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Config.Global as G import Panda.Type.Theme hiding (header) import qualified Panda.Type.State as S
src/Panda/View/Widget/Header.hs view
@@ -5,7 +5,7 @@ import qualified Panda.Config.Global as G import Panda.View.Widget.SearchBar -header c state =+header c =   div_class_id c "header" <<      [ search_bar     , site_name
src/Panda/View/Widget/Helper.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Helper where  import Panda.Helper.Env-import Prelude hiding ((.), (/), (^), id, span)    import qualified Panda.Config.Global as G import qualified Panda.Type.State as State
src/Panda/View/Widget/Navigation.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Navigation where    import Panda.Helper.Env hiding (header)-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Config.Global as G import qualified Panda.Type.State as State @@ -16,4 +16,4 @@   link x = if x == home_nav then home_link else static_link x  home_link     = hotlink G.root << home_nav-static_link s = hotlink (G.root / "static" / s) << s.dropExtension+static_link s = hotlink (G.root / "static" / s) << s.drop_known_extension
src/Panda/View/Widget/RSS.hs view
@@ -1,10 +1,9 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.RSS where  -- env import Panda.Helper.Env -- hiding (Language)-import Prelude hiding ((.), (/), (^), id) import qualified Panda.Config.Global as G-import qualified Panda.Type.Pager as Pager import Text.RSS import qualified Text.RSS as RSS 
src/Panda/View/Widget/SearchBar.hs view
@@ -1,8 +1,8 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.SearchBar where    import Panda.Helper.Env hiding (header) import qualified Panda.Config.Global as G-import Prelude hiding ((/)) import Panda.Type.Extension import Panda.Helper.StateHelper 
src/Panda/View/Widget/Sidebar.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Sidebar where  import Panda.Helper.Env hiding (rss_link)-import Prelude hiding ((.), (/), (^), id, span) import qualified Panda.Type.State as State  import qualified Data.Set as Set
src/Panda/View/Widget/Template.hs view
@@ -1,5 +1,5 @@-{-# OPTIONS -fno-monomorphism-restriction #-}-+{-# LANGUAGE NoMonomorphismRestriction#-}+{-# LANGUAGE NoImplicitPrelude #-} module Panda.View.Widget.Template (page) where  import Panda.View.Widget.Head@@ -13,7 +13,6 @@ import qualified Panda.Type.Theme as T  import Panda.Helper.Env hiding (header, body)-import Prelude hiding ((.), (/), (^), id, span)  -- extension import Panda.Extension.Analytics.T@@ -22,7 +21,7 @@  body t state x = Html.body <<    [ div_class (t.T.container) << -    [ header (t.T.header) state+    [ header (t.T.header)     , navigation (t.T.navigation) state     , div_id "page" << [ div_class (t.T.main) << body_content x, sidebar (t.T.sidebar) state ]     , footer (t.T.footer)