git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Various changes to Docs for Pursuit

* Add packageName function, as a small convenience * Remove HTML generation from Language.PureScript.Docs It's moving into Pursuit server for now. * parameterize the Language.PureScript.Docs.Types.Package type so that packages with and without an uploader have different types, allowing stronger guarantees.

commit213cfc3742697283d8ba8f126ac8a013266460b9 authorHarry Garrood <harry@garrood.me> dateSun 3 May 2015, 11:45 (11 years ago) parent580d96c
5 files changed+80−273
psc-publish/Main.hs+2−2 purescript.cabal+2−8 src/Language/PureScript/Docs/AsHtml.hs−219 src/Language/PureScript/Docs/Types.hs+76−24 src/Language/PureScript/Docs/Utils/HtmlHelpers.hs−20
psc-publish/Main.hs+2−2
@@ -103,9 +103,9 @@ preparePackage' = do
103103 let declaredDeps = map fst (bowerDependencies pkgMeta ++ bowerDevDependencies pkgMeta)
104104 pkgResolvedDependencies <- getResolvedDependencies declaredDeps
105105
106− let pkgUploader = Nothing
106+ let pkgUploader = D.NotYetKnown
107107
108− return D.UploadedPackage{..}
108+ return D.Package{..}
109109
110110getModulesAndBookmarks :: PrepareM ([D.Bookmark], [D.RenderedModule])
111111getModulesAndBookmarks = do
purescript.cabal+2−8
@@ -40,14 +40,10 @@ library
4040 aeson >= 0.8 && < 0.9,
4141 vector -any,
4242 bower-json >= 0.7,
43− aeson-better-errors >= 0.5,
43+ aeson-better-errors >= 0.7,
4444 bytestring -any,
4545 text -any,
46− split -any,
47− lucid -any,
48− blaze-html -any,
49− data-default -any,
50− cheapskate -any
46+ split -any
5147 exposed-modules: Language.PureScript
5248 Language.PureScript.AST
5349 Language.PureScript.AST.Binders
@@ -131,9 +127,7 @@ library
131127 Language.PureScript.Docs.RenderedCode.Types
132128 Language.PureScript.Docs.RenderedCode.Render
133129 Language.PureScript.Docs.AsMarkdown
134− Language.PureScript.Docs.AsHtml
135130 Language.PureScript.Docs.ParseAndDesugar
136− Language.PureScript.Docs.Utils.HtmlHelpers
137131 Language.PureScript.Docs.Utils.MonoidExtras
138132
139133 Control.Monad.Unify
src/Language/PureScript/Docs/AsHtml.hsdeleted−219
@@ -1,219 +0,0 @@
1−{-# LANGUAGE RecordWildCards #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
4−{-# LANGUAGE ViewPatterns #-}
5−
6−-- | Functions for rendering generated documentation from PureScript code as
7−-- HTML.
8−
9−module Language.PureScript.Docs.AsHtml (
10− HtmlOutput(..),
11− packageAsHtml
12−) where
13−
14−import Control.Arrow (second)
15−import Control.Category ((>>>))
16−import Data.Char (toUpper)
17−import Data.Ord (comparing)
18−import Data.Monoid (mconcat)
19−import Data.Foldable (for_)
20−import Data.List (intercalate, find, sortBy)
21−import qualified Data.DList as DList
22−import Data.List.Split (splitOn)
23−import Data.Default (def)
24−import Data.Version
25−import qualified Data.Map as M
26−
27−import qualified Data.Text as T
28−
29−import Lucid hiding (for_)
30−import qualified Text.Blaze.Html as H
31−import qualified Text.Blaze.Html.Renderer.Text as H
32−import qualified Cheapskate
33−
34−import System.FilePath ((</>))
35−
36−import Web.Bower.PackageMeta hiding (Version)
37−
38−import qualified Language.PureScript as P
39−
40−import Language.PureScript.Docs.Types
41−import Language.PureScript.Docs.RenderedCode hiding (sp)
42−import Language.PureScript.Docs.Utils.HtmlHelpers
43−
44−data LinksContext = LinksContext
45− { ctxGithub :: (GithubUser, GithubRepo)
46− , ctxBookmarks :: [Bookmark]
47− , ctxResolvedDependencies :: [(PackageName, Version)]
48− }
49− deriving (Show, Eq, Ord)
50−
51−-- | A LinksContext with the current module name.
52−type LinksContext' = (LinksContext, P.ModuleName)
53−
54−data DocLink
55− -- | A link to a declaration in the same module; in this case, only the title
56− -- is needed to generate the link.
57− = SameModule String
58−
59− -- | A link to a declaration in a different module, but still in the current
60− -- package; we need to store the current module, the other declaration's
61− -- module, and the declaration title.
62− | LocalModule P.ModuleName P.ModuleName String
63−
64− -- | A link to a declaration in a different package. We store: current module
65− -- name, name of the other package, version of the other package, name of
66− -- the module in the other package that the declaration is in, and
67− -- declaration title.
68− | DepsModule P.ModuleName PackageName Version P.ModuleName String
69− deriving (Show, Eq, Ord)
70−
71−data HtmlOutput = HtmlOutput
72− { htmlIndex :: [(Maybe Char, Html ())]
73− , htmlModules :: [(P.ModuleName, Html ())]
74− }
75− deriving (Show)
76−
77−packageAsHtml :: UploadedPackage -> HtmlOutput
78−packageAsHtml UploadedPackage{..} = HtmlOutput indexFile modules
79− where
80− indexFile = renderIndex ctx
81− modules = map (moduleAsHtml ctx) pkgModules
82− ctx = LinksContext pkgGithub pkgBookmarks pkgResolvedDependencies
83−
84−moduleAsHtml :: LinksContext -> RenderedModule -> (P.ModuleName, Html ())
85−moduleAsHtml ctx RenderedModule{..} = (mn, html)
86− where
87− mn = P.moduleNameFromString rmName
88− ctx' = (ctx, mn)
89− html = do
90− h1_ $ do
91− text "module "
92− strong_ (text rmName)
93− for_ rmComments renderComments
94− for_ rmDeclarations (declAsHtml ctx')
95−
96−renderIndex :: LinksContext -> [(Maybe Char, Html ())]
97−renderIndex LinksContext{..} = go ctxBookmarks
98− where
99− go = takeLocals
100− >>> groupIndex getIndex renderEntry
101− >>> map (second (ul_ . mconcat))
102−
103− getIndex (_, ((toUpper -> c) :_))
104− | c `elem` ['A'..'Z'] = Just c
105− | otherwise = Nothing
106− getIndex _ = Nothing
107−
108− renderEntry (mn, title) =
109− li_ $ do
110− let url = T.pack ((filePathFor mn `relativeTo` "index") ++ "#" ++ title)
111− code_ (a_ [href_ url] (text title))
112− sp
113− text ("(" ++ show mn ++ ")")
114−
115− groupIndex :: Ord i => (a -> Maybe i) -> (a -> b) -> [a] -> [(Maybe i, [b])]
116− groupIndex f g =
117− map (second DList.toList) . M.toList . foldr go' M.empty . sortBy (comparing f)
118− where
119− go' x = insertOrAppend (f x) (g x)
120− insertOrAppend idx val m =
121− let cur = M.findWithDefault DList.empty idx m
122− new = DList.snoc cur val
123− in M.insert idx new m
124−
125−declAsHtml :: LinksContext' -> RenderedDeclaration -> Html ()
126−declAsHtml ctx RenderedDeclaration{..} = do
127− a_ [name_ (T.pack rdTitle), href_ (T.pack ('#' : rdTitle))] $
128− h2_ (code_ (text rdTitle))
129− para "decl" (code_ (codeAsHtml ctx rdCode))
130− renderChildren ctx rdChildren
131− case rdComments of
132− Just cs -> renderComments cs
133− Nothing -> return ()
134− for_ rdSourceSpan (linkToSource ctx)
135−
136−renderChildren :: LinksContext' -> [RenderedChildDeclaration] -> Html ()
137−renderChildren _ [] = return ()
138−renderChildren ctx xs = go xs
139− where
140− go = ul_ . mapM_ (li_ . code_ . codeAsHtml ctx . rcdCode)
141−
142−codeAsHtml :: LinksContext' -> RenderedCode -> Html ()
143−codeAsHtml ctx = outputWith elemAsHtml
144− where
145− elemAsHtml (Syntax x) = withClass "syntax" (text x)
146− elemAsHtml (Ident x) = withClass "ident" (text x)
147− elemAsHtml (Ctor x mn) = linkToConstructor ctx x mn (withClass "ctor" (text x))
148− elemAsHtml (Kind x) = text x
149− elemAsHtml (Keyword x) = withClass "keyword" (text x)
150− elemAsHtml Space = text " "
151−
152−getLink :: LinksContext' -> String -> ContainingModule -> Maybe DocLink
153−getLink (LinksContext{..}, curMn) ctor' containingMod = do
154− let bookmark' = (fromContainingModule curMn containingMod, ctor')
155− bookmark <- find ((bookmark' ==) . ignorePackage) ctxBookmarks
156−
157− case containingMod of
158− ThisModule -> return (SameModule ctor')
159− OtherModule destMn ->
160− case bookmark of
161− Local _ -> return (LocalModule curMn destMn ctor')
162− FromDep pkgName _ -> do
163− pkgVersion <- lookup pkgName ctxResolvedDependencies
164− return (DepsModule curMn pkgName pkgVersion destMn ctor')
165−
166−renderLink :: DocLink -> Html () -> Html ()
167−renderLink (SameModule x) = linkTo ('#' : x)
168−renderLink (LocalModule srcMn destMn x) =
169− let uri = filePathFor destMn `relativeTo` filePathFor srcMn
170− in linkTo (uri ++ "#" ++ x)
171−renderLink (DepsModule srcMn pkgName pkgVersion destMn x) =
172− let relativeTo' = relativeToOtherPackage pkgName pkgVersion
173− uri = filePathFor destMn `relativeTo'` filePathFor srcMn
174− in linkTo (uri ++ "#" ++ x)
175−
176−linkToConstructor :: LinksContext' -> String -> ContainingModule -> Html () -> Html ()
177−linkToConstructor ctx ctor' containMn =
178− maybe id renderLink (getLink ctx ctor' containMn)
179−
180−linkToSource :: LinksContext' -> P.SourceSpan -> Html ()
181−linkToSource (LinksContext{..}, _) (P.SourceSpan name start end) =
182− linkTo (concat
183− [githubBaseUrl, "/tree/master/", relativeToBase name, "#", fragment])
184− (text "Source")
185− where
186− (P.SourcePos startLine _) = start
187− (P.SourcePos endLine _) = end
188− (GithubUser user, GithubRepo repo) = ctxGithub
189−
190− relativeToBase = intercalate "/" . dropWhile (/= "src") . splitOn "/"
191− githubBaseUrl = concat ["https://github.com/", user, "/", repo]
192− fragment = "L" ++ show startLine ++ "-L" ++ show endLine
193−
194−-- TODO: use GitHub API instead?
195−renderComments :: String -> Html ()
196−renderComments = toHtml . H.renderHtml . H.toHtml . Cheapskate.markdown def . T.pack
197−
198−-- | if `to` and `from` are both files in the current package, generate a
199−-- FilePath for `to` relative to `from`.
200−relativeTo :: FilePath -> FilePath -> FilePath
201−relativeTo to from = go (splitOn "/" to) (splitOn "/" from)
202− where
203− go (x : xs) (y : ys) | x == y = go xs ys
204− go xs ys = intercalate "/" $ replicate (length ys - 1) ".." ++ xs
205−
206−-- | Generate a FilePath for module documentation for a module in the current
207−-- package.
208−filePathFor :: P.ModuleName -> FilePath
209−filePathFor (P.ModuleName parts) = go parts
210− where
211− go [] = "index.html"
212− go (x : xs) = show x </> go xs
213−
214−-- | Like `relativeTo`, but in the case where `to` is in another package.
215−relativeToOtherPackage :: PackageName -> Version -> FilePath -> FilePath -> FilePath
216−relativeToOtherPackage name (showVersion -> vers) to from =
217− intercalate "/" (dots ++ [runPackageName name, vers] ++ splitOn "/" to)
218− where
219− dots = replicate (length from - 1) ".."
src/Language/PureScript/Docs/Types.hs+76−24
@@ -1,6 +1,7 @@
11{-# LANGUAGE RecordWildCards #-}
22{-# LANGUAGE OverloadedStrings #-}
33{-# LANGUAGE TupleSections #-}
4+{-# LANGUAGE RankNTypes #-}
45
56module Language.PureScript.Docs.Types
67 ( module Language.PureScript.Docs.Types
@@ -10,6 +11,7 @@ module Language.PureScript.Docs.Types
1011
1112import Control.Arrow (first, (***))
1213import Control.Applicative ((<$>), (<*>))
14+import Data.Functor ((<$))
1315import Data.Char
1416import Data.Maybe (mapMaybe)
1517import Data.Version
@@ -18,6 +20,7 @@ import qualified Data.Aeson as A
1820import Data.Aeson.BetterErrors
1921import Text.ParserCombinators.ReadP (readP_to_S)
2022import Data.Text (Text)
23+import Data.ByteString.Lazy (ByteString)
2124import qualified Data.Text as T
2225
2326import Web.Bower.PackageMeta hiding (Version)
@@ -32,17 +35,35 @@ import Language.PureScript.Docs.RenderedCode as ReExports
3235--------------------
3336-- Types
3437
35−data UploadedPackage = UploadedPackage
38+data Package a = Package
3639 { pkgMeta :: PackageMeta
3740 , pkgVersion :: Version
3841 , pkgModules :: [RenderedModule]
3942 , pkgBookmarks :: [Bookmark]
4043 , pkgResolvedDependencies :: [(PackageName, Version)]
4144 , pkgGithub :: (GithubUser, GithubRepo)
42− , pkgUploader :: Maybe GithubUser
45+ , pkgUploader :: a
4346 }
4447 deriving (Show, Eq, Ord)
4548
49+data NotYetKnown = NotYetKnown
50+
51+type UploadedPackage = Package NotYetKnown
52+type VerifiedPackage = Package GithubUser
53+
54+verifyPackage :: GithubUser -> UploadedPackage -> VerifiedPackage
55+verifyPackage verifiedUser Package{..} =
56+ Package pkgMeta
57+ pkgVersion
58+ pkgModules
59+ pkgBookmarks
60+ pkgResolvedDependencies
61+ pkgGithub
62+ verifiedUser
63+
64+packageName :: Package a -> PackageName
65+packageName = bowerName . pkgMeta
66+
4667data RenderedModule = RenderedModule
4768 { rmName :: String
4869 , rmComments :: Maybe String
@@ -92,7 +113,7 @@ newtype GithubRepo
92113 = GithubRepo { runGithubRepo :: String }
93114 deriving (Show, Eq, Ord)
94115
95−data UploadedPackageError
116+data PackageError
96117 = ErrorInPackageMeta BowerError
97118 | InvalidVersion
98119 | InvalidDeclarationType
@@ -124,17 +145,46 @@ ignorePackage (FromDep _ x) = x
124145----------------------
125146-- Parsing
126147
127−asUploadedPackage :: Parse UploadedPackageError UploadedPackage
128−asUploadedPackage =
129− UploadedPackage <$> key "packageMeta" asPackageMeta .! ErrorInPackageMeta
130− <*> key "version" asVersion
131− <*> key "modules" (eachInArray asRenderedModule)
132− <*> key "bookmarks" asBookmarks .! ErrorInPackageMeta
133− <*> key "resolvedDependencies" asResolvedDependencies
134− <*> key "github" asGithub
135− <*> keyMay "uploader" (GithubUser <$> asString)
136−
137−asVersion :: Parse UploadedPackageError Version
148+parseUploadedPackage :: ByteString -> Either (ParseError PackageError) UploadedPackage
149+parseUploadedPackage = parse asUploadedPackage
150+
151+parseVerifiedPackage :: ByteString -> Either (ParseError PackageError) VerifiedPackage
152+parseVerifiedPackage = parse asVerifiedPackage
153+
154+asPackage :: (forall e. Parse e a) -> Parse PackageError (Package a)
155+asPackage uploader =
156+ Package <$> key "packageMeta" asPackageMeta .! ErrorInPackageMeta
157+ <*> key "version" asVersion
158+ <*> key "modules" (eachInArray asRenderedModule)
159+ <*> key "bookmarks" asBookmarks .! ErrorInPackageMeta
160+ <*> key "resolvedDependencies" asResolvedDependencies
161+ <*> key "github" asGithub
162+ <*> key "uploader" uploader
163+
164+asUploadedPackage :: Parse PackageError UploadedPackage
165+asUploadedPackage = asPackage asNotYetKnown
166+
167+asNotYetKnown :: Parse e NotYetKnown
168+asNotYetKnown = NotYetKnown <$ asNull
169+
170+instance A.FromJSON NotYetKnown where
171+ parseJSON = toAesonParser' asNotYetKnown
172+
173+asVerifiedPackage :: Parse PackageError VerifiedPackage
174+asVerifiedPackage = asPackage asGithubUser
175+
176+asGithubUser :: Parse e GithubUser
177+asGithubUser = GithubUser <$> asString
178+
179+instance A.FromJSON GithubUser where
180+ parseJSON = toAesonParser' asGithubUser
181+
182+instance A.FromJSON a => A.FromJSON (Package a) where
183+ -- TODO: actual error display
184+ parseJSON = toAesonParser (T.pack . show)
185+ (asPackage fromAesonParser)
186+
187+asVersion :: Parse PackageError Version
138188asVersion = withString (maybe (Left InvalidVersion) Right . parseVersion')
139189
140190parseVersion' :: String -> Maybe Version
@@ -143,13 +193,13 @@ parseVersion' str =
143193 [(vers, "")] -> Just vers
144194 _ -> Nothing
145195
146−asRenderedModule :: Parse UploadedPackageError RenderedModule
196+asRenderedModule :: Parse PackageError RenderedModule
147197asRenderedModule =
148198 RenderedModule <$> key "name" asString
149199 <*> key "comments" (perhaps asString)
150200 <*> key "declarations" (eachInArray asDeclaration)
151201
152−asDeclaration :: Parse UploadedPackageError RenderedDeclaration
202+asDeclaration :: Parse PackageError RenderedDeclaration
153203asDeclaration =
154204 RenderedDeclaration <$> key "title" asString
155205 <*> key "comments" (perhaps asString)
@@ -157,7 +207,7 @@ asDeclaration =
157207 <*> key "sourceSpan" (perhaps asSourceSpan)
158208 <*> key "children" (eachInArray asRenderedChildDeclaration)
159209
160−asRenderedChildDeclaration :: Parse UploadedPackageError RenderedChildDeclaration
210+asRenderedChildDeclaration :: Parse PackageError RenderedChildDeclaration
161211asRenderedChildDeclaration =
162212 RenderedChildDeclaration <$> key "title" asString
163213 <*> key "comments" (perhaps asString)
@@ -167,7 +217,7 @@ asRenderedChildDeclaration =
167217 where
168218 p .!! err = p .! const err
169219
170−asRenderedChildDeclarationType :: Parse UploadedPackageError RenderedChildDeclarationType
220+asRenderedChildDeclarationType :: Parse PackageError RenderedChildDeclarationType
171221asRenderedChildDeclarationType =
172222 withString (maybe (Left InvalidDeclarationType) Right .
173223 flip lookup childDeclarationTypes)
@@ -188,7 +238,7 @@ asBookmark =
188238 build Nothing = Local
189239 build (Just pn) = FromDep pn
190240
191−asResolvedDependencies :: Parse UploadedPackageError [(PackageName, Version)]
241+asResolvedDependencies :: Parse PackageError [(PackageName, Version)]
192242asResolvedDependencies =
193243 eachInObjectWithKey (mapLeft ErrorInPackageMeta . parsePackageName . T.unpack) asVersion
194244 where
@@ -207,8 +257,8 @@ asSourceSpan = P.SourceSpan <$> key "name" asString
207257---------------------
208258-- ToJSON instances
209259
210−instance A.ToJSON UploadedPackage where
211− toJSON UploadedPackage{..} =
260+instance A.ToJSON a => A.ToJSON (Package a) where
261+ toJSON Package{..} =
212262 A.object $
213263 [ "packageMeta" .= pkgMeta
214264 , "version" .= showVersion pkgVersion
@@ -218,9 +268,11 @@ instance A.ToJSON UploadedPackage where
218268 (T.pack . showVersion)
219269 pkgResolvedDependencies
220270 , "github" .= pkgGithub
221− ] ++ case pkgUploader of
222− Just u -> [ "uploader" .= u ]
223− Nothing -> []
271+ , "uploader" .= pkgUploader
272+ ]
273+
274+instance A.ToJSON NotYetKnown where
275+ toJSON _ = A.Null
224276
225277instance A.ToJSON RenderedModule where
226278 toJSON RenderedModule{..} =
src/Language/PureScript/Docs/Utils/HtmlHelpers.hsdeleted−20
@@ -1,20 +0,0 @@
1−
2−module Language.PureScript.Docs.Utils.HtmlHelpers where
3−
4−import Data.String
5−import Lucid
6−
7−text :: String -> Html ()
8−text = toHtml
9−
10−sp :: Html ()
11−sp = text " "
12−
13−para :: String -> Html () -> Html ()
14−para className content = p_ [class_ (fromString className)] content
15−
16−withClass :: String -> Html () -> Html ()
17−withClass className content = span_ [class_ (fromString className)] content
18−
19−linkTo :: String -> Html () -> Html ()
20−linkTo href inner = a_ [href_ (fromString href)] inner