diff --git a/examples/pdf-service.nrm b/examples/pdf-service.nrm index d3c1451..ebf5ac9 100644 --- a/examples/pdf-service.nrm +++ b/examples/pdf-service.nrm @@ -1,4 +1,6 @@ +type html = text; + service pdf-service ( # A microservice which renders a PDF from the given URI or HTML. @@ -9,6 +11,6 @@ service pdf-service ( binary render-html ( # Renders a PDF from the given HTML text. - text html, + html html, ), ); diff --git a/nirum.cabal b/nirum.cabal index 6946b8c..5a02741 100644 --- a/nirum.cabal +++ b/nirum.cabal @@ -122,6 +122,7 @@ test-suite spec , Nirum.PackageSpec , Nirum.ParserSpec , Nirum.Targets.PythonSpec + , Nirum.Targets.DocsSpec , Nirum.TargetsSpec , Nirum.VersionSpec , Util diff --git a/src/Nirum/Targets/Docs.hs b/src/Nirum/Targets/Docs.hs index 91707a1..5b58884 100644 --- a/src/Nirum/Targets/Docs.hs +++ b/src/Nirum/Targets/Docs.hs @@ -10,7 +10,7 @@ import Data.Map.Strict (Map, union) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8) import System.FilePath ((>)) -import Text.Blaze (preEscapedToMarkup) +import Text.Blaze (ToMarkup (preEscapedToMarkup)) import Text.Blaze.Html.Renderer.Utf8 (renderHtml) import Text.Hamlet (Html, shamlet) @@ -25,7 +25,9 @@ import Nirum.Constructs.Identifier ( Identifier import Nirum.Constructs.Module (Module (Module, docs)) import Nirum.Constructs.ModulePath (ModulePath) import Nirum.Constructs.Name (Name (facialName)) +import qualified Nirum.Constructs.Service as S import qualified Nirum.Constructs.TypeDeclaration as TD +import qualified Nirum.Constructs.TypeExpression as TE import Nirum.Docs ( Block (Heading) , filterReferences ) @@ -63,37 +65,49 @@ makeUri modulePath' = T.intercalate "/" $ map toNormalizedText (toList modulePath') ++ ["index.html"] -module' :: BoundModule Docs -> Html -module' docsModule = [shamlet| +layout :: ToMarkup m => Package Docs -> m -> Html -> Html +layout Package { metadata = md } title body = [shamlet| $doctype 5
-#{path}
- $forall (ident, decl) <- types'
- #{showKind decl} #{toNormalizedText ident}
+ #{body}
+|]
+
+typeExpression :: BoundModule Docs -> TE.TypeExpression -> Html
+typeExpression _ expr = [shamlet|#{typeExpr expr}|]
+ where
+ typeExpr :: TE.TypeExpression -> Html
+ typeExpr expr' = [shamlet|
+$case expr'
+ $of TE.TypeIdentifier ident
+ #{toCode ident}
+ $of TE.OptionModifier type'
+ #{typeExpr type'}?
+ $of TE.SetModifier elementType
+ {#{typeExpr elementType}}
+ $of TE.ListModifier elementType
+ [#{typeExpr elementType}]
+ $of TE.MapModifier keyType valueType
+ {#{typeExpr keyType}: #{typeExpr valueType}}
+|]
+
+module' :: BoundModule Docs -> Html
+module' docsModule = layout pkg path $ [shamlet|
+ #{path}
+ $forall (ident, decl) <- types'
+
+ #{typeDecl docsModule ident decl}
|]
where
- md :: Metadata Docs
- md = metadata $ boundPackage docsModule
+ pkg :: Package Docs
+ pkg = boundPackage docsModule
path :: T.Text
path = toCode $ modulePath docsModule
- showKind :: TD.TypeDeclaration -> T.Text
- showKind TD.ServiceDeclaration {} = "service"
- showKind TD.TypeDeclaration { TD.type' = type'' } = case type'' of
- TD.Alias {} -> "alias"
- TD.UnboxedType {} -> "unboxed"
- TD.EnumType {} -> "enum"
- TD.RecordType {} -> "record"
- TD.UnionType {} -> "union"
- TD.PrimitiveType {} -> "primitive"
- showKind TD.Import {} = "import"
types' :: [(Identifier, TD.TypeDeclaration)]
types' = [ (facialName $ DE.name decl, decl)
| decl <- DES.toList $ types docsModule
@@ -102,40 +116,108 @@ $doctype 5
_ -> True
]
+typeDecl :: BoundModule Docs -> Identifier -> TD.TypeDeclaration -> Html
+typeDecl mod' ident
+ TD.TypeDeclaration { TD.type' = TD.Alias cname } = [shamlet|
+ type #{toNormalizedText ident}
+
= #{typeExpression mod' cname}
+|]
+typeDecl mod' ident
+ TD.TypeDeclaration { TD.type' = TD.UnboxedType innerType } = [shamlet|
+
unboxed #{toNormalizedText ident}
+
(#{typeExpression mod' innerType})
+|]
+typeDecl _ ident
+ TD.TypeDeclaration { TD.type' = TD.EnumType members } = [shamlet|
+
enum #{toNormalizedText ident}
+
+ $forall decl <- DES.toList members
+ #{nameText $ DE.name decl}
+|]
+typeDecl mod' ident
+ TD.TypeDeclaration { TD.type' = TD.RecordType fields } = [shamlet|
+ record #{toNormalizedText ident}
+
+ $forall fieldDecl@(TD.Field _ fieldType _) <- DES.toList fields
+ #{nameText $ DE.name fieldDecl}
+ - #{typeExpression mod' fieldType}
+|]
+typeDecl mod' ident
+ TD.TypeDeclaration { TD.type' = TD.UnionType tags } = [shamlet|
+
union #{toNormalizedText ident}
+ $forall tagDecl@(TD.Tag _ fields _) <- DES.toList tags
+
+ #{nameText $ DE.name tagDecl}
+
+ $forall fieldDecl@(TD.Field _ fieldType _) <- DES.toList fields
+ -
+
#{nameText $ DE.name fieldDecl}
+ - #{typeExpression mod' fieldType}
+|]
+typeDecl _ ident
+ TD.TypeDeclaration { TD.type' = TD.PrimitiveType {} } = [shamlet|
+
primitive #{toNormalizedText ident}
+|]
+typeDecl mod' ident
+ TD.ServiceDeclaration { TD.service = S.Service methods } = [shamlet|
+ service #{toNormalizedText ident}
+ $forall methodDecl@(S.Method _ params ret err _) <- DES.toList methods
+
+ #{nameText $ DE.name methodDecl}
+ #{typeExpression mod' ret}
+ $maybe errType <- err
+
#{typeExpression mod' errType}
+
+ $forall paramDecl@(S.Parameter _ paramType _) <- DES.toList params
+ -
+
#{nameText $ DE.name paramDecl}
+ - #{typeExpression mod' paramType}
+|]
+typeDecl _ _ TD.Import {} =
+ error ("It shouldn't happen; please report it to Nirum's bug tracker:\n" ++
+ "https://github.com/spoqa/nirum/issues")
+
+nameText :: Name -> T.Text
+nameText = toNormalizedText . facialName
+
+showKind :: TD.TypeDeclaration -> T.Text
+showKind TD.ServiceDeclaration {} = "service"
+showKind TD.TypeDeclaration { TD.type' = type'' } = case type'' of
+ TD.Alias {} -> "alias"
+ TD.UnboxedType {} -> "unboxed"
+ TD.EnumType {} -> "enum"
+ TD.RecordType {} -> "record"
+ TD.UnionType {} -> "union"
+ TD.PrimitiveType {} -> "primitive"
+showKind TD.Import {} = "import"
+
contents :: Package Docs -> Html
-contents Package { metadata = md, modules = ms } = [shamlet|
-$doctype 5
-
-
-
-
Package docs
-
- $forall Author { name = name' } <- authors md
-
-
- Modules
-
- $forall (modulePath', mod) <- MS.toAscList ms
- -
-
-
#{toCode modulePath'}
- $maybe tit <- moduleTitle mod
- — #{tit}
-
-
-
- $if 1 < length (authors md)
- Authors
- $else
- Author
- $forall Author { name = n, uri = u, email = e } <- authors md
- $maybe uri' <- u
- #{n}
- $nothing
- $maybe email' <- e
- #{n}
- $nothing
- #{n}
+contents pkg@Package { metadata = md
+ , modules = ms
+ } = layout pkg ("Package docs" :: T.Text) [shamlet|
+Modules
+
+ $forall (modulePath', mod) <- MS.toAscList ms
+ -
+
+
#{toCode modulePath'}
+ $maybe tit <- moduleTitle mod
+ — #{tit}
+
+