1
0
Fork 0
mirror of https://code.sup39.dev/repos/Wqawg synced 2024-12-27 19:44:50 +09:00

Initial minimal optional per-project wiki

This commit is contained in:
fr33domlover 2016-06-04 06:57:54 +00:00
parent ef810f2854
commit f8e1442e72
10 changed files with 201 additions and 7 deletions

View file

@ -103,6 +103,7 @@ Project
name Text Maybe name Text Maybe
desc Text Maybe desc Text Maybe
nextTicket Int default=1 nextTicket Int default=1
wiki RepoId Maybe
UniqueProject ident sharer UniqueProject ident sharer

View file

@ -99,5 +99,4 @@
/s/#ShrIdent/p/#PrjIdent/t/#Int/d/!reply TicketTopReplyR GET /s/#ShrIdent/p/#PrjIdent/t/#Int/d/!reply TicketTopReplyR GET
/s/#ShrIdent/p/#PrjIdent/t/#Int/d/#Int/reply TicketReplyR GET /s/#ShrIdent/p/#PrjIdent/t/#Int/d/#Int/reply TicketReplyR GET
-- /s/#ShrIdent/p/#PrjIdent/w WikiR GET /s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET
-- /s/#ShrIdent/p/#PrjIdent/w/+Texts WikiPageR GET

View file

@ -62,6 +62,7 @@ import Vervis.Handler.Repo
import Vervis.Handler.Role import Vervis.Handler.Role
import Vervis.Handler.Sharer import Vervis.Handler.Sharer
import Vervis.Handler.Ticket import Vervis.Handler.Ticket
import Vervis.Handler.Wiki
import Vervis.Ssh (runSsh) import Vervis.Ssh (runSsh)

View file

@ -15,14 +15,18 @@
module Vervis.Darcs module Vervis.Darcs
( readSourceView ( readSourceView
, readWikiView
, readChangesView , readChangesView
) )
where where
import Prelude import Prelude hiding (lookup)
import Control.Applicative ((<|>))
import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Except (ExceptT (ExceptT), runExceptT) import Control.Monad.Trans.Except (ExceptT (ExceptT), runExceptT)
import Data.Bool (bool)
import Data.Maybe (listToMaybe, mapMaybe)
import Data.Text (Text) import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8, decodeUtf8With) import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
import Data.Text.Encoding.Error (strictDecode) import Data.Text.Encoding.Error (strictDecode)
@ -52,6 +56,7 @@ import Vervis.Changes
import Vervis.Foundation (Widget) import Vervis.Foundation (Widget)
import Vervis.Readme import Vervis.Readme
import Vervis.SourceTree import Vervis.SourceTree
import Vervis.Wiki (WikiView (..))
dirToAnchoredPath :: [EntryName] -> AnchoredPath dirToAnchoredPath :: [EntryName] -> AnchoredPath
dirToAnchoredPath = AnchoredPath . map (Name . encodeUtf8) dirToAnchoredPath = AnchoredPath . map (Name . encodeUtf8)
@ -91,6 +96,13 @@ itemToSourceView name (SubTree tree) = do
} }
itemToSourceView _name (Stub _load _hash) = error "supposed to be expanded" itemToSourceView _name (Stub _load _hash) = error "supposed to be expanded"
readStubbedTree :: FilePath -> IO (Tree IO)
readStubbedTree path = do
let darcsDir = path </> "_darcs"
(msize, hash) <- readPristineRoot darcsDir
let pristineDir = darcsDir </> "pristine.hashed"
readDarcsHashed pristineDir (msize, hash)
readSourceView readSourceView
:: FilePath :: FilePath
-- ^ Repository path -- ^ Repository path
@ -98,10 +110,7 @@ readSourceView
-- ^ Path in the source tree pointing to a file or directory -- ^ Path in the source tree pointing to a file or directory
-> IO (Maybe (SourceView Widget)) -> IO (Maybe (SourceView Widget))
readSourceView path dir = do readSourceView path dir = do
let darcsDir = path </> "_darcs" stubbedTree <- readStubbedTree path
(msize, hash) <- readPristineRoot darcsDir
let pristineDir = darcsDir </> "pristine.hashed"
stubbedTree <- readDarcsHashed pristineDir (msize, hash)
msv <- if null dir msv <- if null dir
then do then do
let items = listImmediate stubbedTree let items = listImmediate stubbedTree
@ -118,6 +127,56 @@ readSourceView path dir = do
for mitem $ itemToSourceView (last dir) for mitem $ itemToSourceView (last dir)
return $ renderSources dir <$> msv return $ renderSources dir <$> msv
readWikiView
:: (EntryName -> EntryName -> Maybe Text)
-- ^ Page name predicate. Returns 'Nothing' for a file which isn't a page.
-- For a page file, returns 'Just' the page name, which is the filename
-- with some parts possibly removed or added. For example, you may wish to
-- remove any extensions, replace underscores with spaces and so on.
-> (EntryName -> Bool)
-- ^ Main page predicate. This is used to pick a top-level page to display
-- as the wiki root page.
-> FilePath
-- ^ Repository path.
-> [EntryName]
-- ^ Path in the source tree pointing to a file. The last component doesn't
-- have to be the full name of the file though, but it much match the page
-- predicate for the actual file to be found.
-> IO (Maybe WikiView)
readWikiView isPage isMain path dir = do
stubbedTree <- readStubbedTree path
let (parent, ispage, mfile) =
if null dir
then
( []
, bool Nothing (Just Nothing) . isMain
, Nothing
)
else
( init dir
, maybe Nothing (Just . Just) . isPage lst
, Just $ Name $ encodeUtf8 lst
)
where
lst = last dir
anch = dirToAnchoredPath parent
matchBlob f (n, (File (Blob load _))) = f (nameToText n) load
matchBlob _ _ = Nothing
matchBlob' f (File (Blob load _)) = Just $ f load
matchBlob' _ _ = Nothing
page name load = (,) load . Just <$> ispage name
matchP = listToMaybe . mapMaybe (matchBlob page) . listImmediate
matchF t = mfile >>= lookup t >>= matchBlob' (flip (,) Nothing)
expandedTree <- expandPath stubbedTree anch
let mpage = case find expandedTree anch of
Nothing -> Nothing
Just (File _) -> Nothing
Just (Stub _ _) -> error "supposed to be expanded"
Just (SubTree tree) -> matchP tree <|> matchF tree
mkview Nothing b = WikiViewRaw b
mkview (Just mt) b = WikiViewPage mt b
for mpage $ \ (load, mmtitle) -> mkview mmtitle <$> load
readChangesView readChangesView
:: FilePath :: FilePath
-- ^ Repository path -- ^ Repository path

View file

@ -38,6 +38,7 @@ newProjectAForm sid = Project
<*> aopt textField "Name" Nothing <*> aopt textField "Name" Nothing
<*> aopt textField "Description" Nothing <*> aopt textField "Description" Nothing
<*> pure 1 <*> pure 1
<*> pure Nothing
newProjectForm :: SharerId -> Form Project newProjectForm :: SharerId -> Form Project
newProjectForm = renderDivs . newProjectAForm newProjectForm = renderDivs . newProjectAForm

View file

@ -391,3 +391,5 @@ instance YesodBreadcrumbs App where
, Just $ , Just $
TicketMessageR shar proj num cnum TicketMessageR shar proj num cnum
) )
WikiPageR shr prj _page -> ("Wiki", Just $ ProjectR shr prj)

View file

@ -0,0 +1,76 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- Copying is an act of love. Please copy, reuse and share.
-
- The author(s) have dedicated all copyright and related and neighboring
- rights to this software to the public domain worldwide. This software is
- distributed without any warranty.
-
- You should have received a copy of the CC0 Public Domain Dedication along
- with this software. If not, see
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Vervis.Handler.Wiki
( getWikiPageR
)
where
import Prelude
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import Data.Traversable (for)
import Database.Persist (Entity (..), getJust)
import Text.Blaze.Html (Html)
import Yesod.Core (defaultLayout)
import Yesod.Core.Content (toContent, typeOctet)
import Yesod.Core.Handler (setMessage, redirect, notFound, sendResponse)
import Yesod.Persist.Core (runDB, getBy404)
import Text.FilePath.Local (breakExt)
import Vervis.Darcs
import Vervis.Foundation
import Vervis.MediaType
import Vervis.Model
import Vervis.Model.Ident
import Vervis.Model.Repo
import Vervis.Path (askRepoDir)
import Vervis.Render (renderSourceBL)
import Vervis.Settings (widgetFile)
import Vervis.Wiki
getWikiPageR :: ShrIdent -> PrjIdent -> [Text] -> Handler Html
getWikiPageR shr prj path = do
m <- runDB $ do
Entity sid _ <- getBy404 $ UniqueSharer shr
Entity _ j <- getBy404 $ UniqueProject prj sid
for (projectWiki j) $ \ rid -> do
r <- getJust rid
s <- getJust $ repoSharer r
return (sharerIdent s, repoIdent r, repoVcs r)
case m of
Nothing -> do
setMessage "This project doesnt have a wiki."
redirect $ ProjectR shr prj
Just (s, r, v) -> do
root <- askRepoDir s r
case v of
VCSDarcs -> do
let ispage name file =
let (b, e) = breakExt file
in if e == "md" && b == name
then Just b
else Nothing
ismain = (== "README.md")
mwv <- liftIO $ readWikiView ispage ismain root path
case mwv of
Nothing -> notFound
Just (WikiViewRaw b) ->
sendResponse (typeOctet, toContent b)
Just (WikiViewPage mt b) -> do
let page = renderSourceBL Markdown b
defaultLayout $(widgetFile "wiki")
VCSGit -> error "Not implemented yet"

35
src/Vervis/Wiki.hs Normal file
View file

@ -0,0 +1,35 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- Copying is an act of love. Please copy, reuse and share.
-
- The author(s) have dedicated all copyright and related and neighboring
- rights to this software to the public domain worldwide. This software is
- distributed without any warranty.
-
- You should have received a copy of the CC0 Public Domain Dedication along
- with this software. If not, see
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Vervis.Wiki
( WikiView (..)
)
where
import Prelude
import Data.Text (Text)
import qualified Data.ByteString.Lazy as BL (ByteString)
import Text.FilePath.Local (breakExt)
import Vervis.Foundation (Widget)
import Vervis.MediaType (chooseMediaType)
import Vervis.Readme (renderReadme)
import Vervis.Render (renderSourceBL)
data WikiView
= WikiViewPage (Maybe Text) BL.ByteString
| WikiViewRaw BL.ByteString

18
templates/wiki.hamlet Normal file
View file

@ -0,0 +1,18 @@
$# This file is part of Vervis.
$#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
$#
$# ♡ Copying is an act of love. Please copy, reuse and share.
$#
$# The author(s) have dedicated all copyright and related and neighboring
$# rights to this software to the public domain worldwide. This software is
$# distributed without any warranty.
$#
$# You should have received a copy of the CC0 Public Domain Dedication along
$# with this software. If not, see
$# <http://creativecommons.org/publicdomain/zero/1.0/>.
$maybe title <- mt
<h2>#{title}
^{page}

View file

@ -113,6 +113,7 @@ library
Vervis.Handler.Role Vervis.Handler.Role
Vervis.Handler.Sharer Vervis.Handler.Sharer
Vervis.Handler.Ticket Vervis.Handler.Ticket
Vervis.Handler.Wiki
Vervis.Import Vervis.Import
Vervis.Import.NoFoundation Vervis.Import.NoFoundation
Vervis.MediaType Vervis.MediaType
@ -136,6 +137,7 @@ library
Vervis.Widget.Discussion Vervis.Widget.Discussion
Vervis.Widget.Repo Vervis.Widget.Repo
Vervis.Widget.Sharer Vervis.Widget.Sharer
Vervis.Wiki
-- other-modules: -- other-modules:
default-extensions: TemplateHaskell default-extensions: TemplateHaskell
QuasiQuotes QuasiQuotes