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 +7/−0
- panda.cabal +8/−6
- src/Main.hs +0/−5
- src/Panda.hs +1/−0
- src/Panda/Config/Global.hs +8/−10
- src/Panda/Controller/Application.hs +6/−7
- src/Panda/Extension/Analytics/T.hs +2/−1
- src/Panda/Helper/Env.hs +7/−5
- src/Panda/Helper/Helper.hs +43/−24
- src/Panda/Helper/PreludeEnv.hs +20/−0
- src/Panda/Helper/StateHelper.hs +5/−6
- src/Panda/Model/Comment.hs +13/−13
- src/Panda/Model/Post.hs +7/−6
- src/Panda/Model/Static.hs +3/−3
- src/Panda/Model/Tag.hs +3/−3
- src/Panda/Type/Extension.hs +1/−2
- src/Panda/Type/Reader.hs +8/−8
- src/Panda/Type/State.hs +7/−6
- src/Panda/Type/StaticWidget.hs +3/−3
- src/Panda/Type/Theme.hs +1/−1
- src/Panda/View/Atom/Comment.hs +2/−5
- src/Panda/View/Atom/Post.hs +1/−2
- src/Panda/View/Atom/Static.hs +1/−0
- src/Panda/View/Atom/Tag.hs +1/−1
- src/Panda/View/Control/Comment.hs +1/−8
- src/Panda/View/Control/Helper.hs +1/−3
- src/Panda/View/Control/Post.hs +1/−1
- src/Panda/View/Control/Search.hs +1/−2
- src/Panda/View/Control/Static.hs +3/−1
- src/Panda/View/Control/Tag.hs +2/−1
- src/Panda/View/Widget/Body.hs +1/−0
- src/Panda/View/Widget/Footer.hs +6/−5
- src/Panda/View/Widget/Head.hs +1/−1
- src/Panda/View/Widget/Header.hs +1/−1
- src/Panda/View/Widget/Helper.hs +1/−1
- src/Panda/View/Widget/Navigation.hs +2/−2
- src/Panda/View/Widget/RSS.hs +1/−2
- src/Panda/View/Widget/SearchBar.hs +1/−1
- src/Panda/View/Widget/Sidebar.hs +1/−1
- src/Panda/View/Widget/Template.hs +3/−4
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
@@ -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
@@ -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)