dhall-docs (empty) → 0.0.1
raw patch · 40 files changed
+2868/−0 lines, 40 filesdep +HaXmldep +basedep +bytestringsetup-changed
Dependencies added: HaXml, base, bytestring, containers, dhall, dhall-docs, directory, doctest, file-embed, filepath, lucid, megaparsec, mmark, mtl, optparse-applicative, path, path-io, pretty, prettyprinter, tar, tasty, tasty-silver, text
Files
- CHANGELOG.md +3/−0
- LICENSE +27/−0
- Setup.hs +2/−0
- dhall-docs.cabal +133/−0
- dhall-docs/Main.hs +6/−0
- doctest/Main.hs +18/−0
- src/Dhall/Docs.hs +132/−0
- src/Dhall/Docs/Core.hs +435/−0
- src/Dhall/Docs/Embedded.hs +45/−0
- src/Dhall/Docs/Html.hs +298/−0
- src/Dhall/Docs/Markdown.hs +32/−0
- src/Dhall/Docs/Store.hs +48/−0
- src/Dhall/data/dhall-icon.svg +1/−0
- src/Dhall/data/index.css +244/−0
- src/Dhall/data/index.js +36/−0
- tasty/Main.hs +65/−0
- tasty/data/golden/IndexesExample.dhall.html +77/−0
- tasty/data/golden/InvalidMarkdown.dhall.html +82/−0
- tasty/data/golden/MarkdownExample.dhall.html +141/−0
- tasty/data/golden/Pair.dhall.html +134/−0
- tasty/data/golden/a/b.dhall.html +57/−0
- tasty/data/golden/a/b/c.dhall.html +61/−0
- tasty/data/golden/a/b/c/a.dhall.html +65/−0
- tasty/data/golden/a/b/c/index.html +47/−0
- tasty/data/golden/a/b/index.html +49/−0
- tasty/data/golden/a/index.html +45/−0
- tasty/data/golden/deep/nested/folder/index.html +65/−0
- tasty/data/golden/deep/nested/folder/my-even.dhall.html +246/−0
- tasty/data/golden/index.html +99/−0
- tasty/data/golden/package.dhall.html +64/−0
- tasty/data/package/IndexesExample.dhall +6/−0
- tasty/data/package/InvalidMarkdown.dhall +15/−0
- tasty/data/package/MarkdownExample.dhall +41/−0
- tasty/data/package/Pair.dhall +11/−0
- tasty/data/package/ShouldBeIgnored.dhall +4/−0
- tasty/data/package/a/b.dhall +5/−0
- tasty/data/package/a/b/c.dhall +5/−0
- tasty/data/package/a/b/c/a.dhall +5/−0
- tasty/data/package/deep/nested/folder/my-even.dhall +12/−0
- tasty/data/package/package.dhall +7/−0
+ CHANGELOG.md view
@@ -0,0 +1,3 @@+0.0.1++* Project skeleton with command line options
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2020 Gabriel Gonzalez+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of its contributors may be+used to endorse or promote products derived from this software without+specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ dhall-docs.cabal view
@@ -0,0 +1,133 @@+Name: dhall-docs+Version: 0.0.1+Cabal-Version: >=1.10+Build-Type: Simple+Tested-With: GHC == 8.6.1+License: BSD3+License-File: LICENSE+Copyright: 2020 Germán Robayo+Author: Germán Robayo+Maintainer: Gabriel439@gmail.com+Bug-Reports: https://github.com/dhall-lang/dhall-haskell/issues+Synopsis: Generate HTML docs from a dhall package+Description:+ Use this package if you want to create HTML documentation from your dhall+ packages:+ .+ * See the "Dhall.Docs" module if you want to use this package as a library+ .+ * Use the @dhall-docs@ program from this package if you want an executable+ .+ The "Dhall.Docs" module also contains instructions for how to use this package+Category: Compiler+Extra-Source-Files:+ CHANGELOG.md+ tasty/data/package/*.dhall+ tasty/data/package/a/*.dhall+ tasty/data/package/a/b/*.dhall+ tasty/data/package/a/b/c/*.dhall+ tasty/data/package/deep/nested/folder/*.dhall+ tasty/data/golden/*.dhall.html+ tasty/data/golden/a/*.dhall.html+ tasty/data/golden/a/b/*.dhall.html+ tasty/data/golden/a/b/c/*.dhall.html+ tasty/data/golden/deep/nested/folder/*.dhall.html+ tasty/data/golden/*.html+ tasty/data/golden/a/*.html+ tasty/data/golden/a/b/*.html+ tasty/data/golden/a/b/c/*.html+ tasty/data/golden/deep/nested/folder/*.html+Data-Files:+ *.css+ *.js+ *.svg+Data-Dir:+ src/Dhall/data++Source-Repository head+ Type: git+ Location: https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-json+++Flag ghci-data-files+ description: To enable use of data-files while running `stack ghci`+ default: False++Library+ Hs-Source-Dirs: src+ Build-Depends:+ base >= 4.9.1.0 && < 5 ,+ bytestring < 0.11,+ containers ,+ directory >= 1.3.0.0 && < 1.4 ,+ dhall >= 1.32.0 ,+ file-embed >= 0.0.10.0 ,+ filepath >= 1.4 && < 1.5 ,+ lucid >= 2.9.12 && < 2.10,+ mmark >= 0.0.7.0 && < 0.8 ,+ megaparsec >= 7 && < 8.1 ,+ path >= 0.7.0 && < 0.8 ,+ path-io >= 1.6.0 && < 1.7 ,+ prettyprinter >= 1.5.1 && < 1.7 ,+ tar >= 0.5.1.0 && < 0.6 ,+ text >= 0.11.1.0 && < 1.3 ,+ mtl >= 2.2.1 && < 2.3 ,+ optparse-applicative >= 0.14.0.0 && < 0.16+ Exposed-Modules:+ Dhall.Docs+ Dhall.Docs.Core+ Other-Modules:+ Dhall.Docs.Embedded+ Dhall.Docs.Html+ Dhall.Docs.Markdown+ Dhall.Docs.Store+ Paths_dhall_docs+ GHC-Options: -Wall+ Default-Language: Haskell2010+ if flag(ghci-data-files)+ Other-Modules: Paths_dhall_docs+ else+ Cpp-Options: "-DEMBED"++Executable dhall-docs+ Hs-Source-Dirs: dhall-docs+ Main-Is: Main.hs+ Build-Depends:+ base ,+ dhall ,+ dhall-docs+ Other-Modules:+ Paths_dhall_docs+ GHC-Options: -Wall+ Default-Language: Haskell2010++Test-Suite doctest+ Type: exitcode-stdio-1.0+ Hs-Source-Dirs: doctest+ Main-Is: Main.hs+ GHC-Options: -Wall+ Build-Depends:+ base ,+ directory,+ filepath < 1.5 ,+ doctest >= 0.7.0 && < 0.18+ Other-Extensions: OverloadedStrings RecordWildCards+ Default-Language: Haskell2010++Test-Suite tasty+ Type: exitcode-stdio-1.0+ Hs-Source-Dirs: tasty+ Main-Is: Main.hs+ Build-Depends:+ base ,+ containers ,+ dhall-docs ,+ HaXml >= 1.25.5 ,+ path ,+ path-io ,+ pretty >= 1.1.1.1,+ tasty < 1.4 ,+ tasty-silver <= 3.1.15 ,+ text+ GHC-Options: -Wall+ Default-Language: Haskell2010
+ dhall-docs/Main.hs view
@@ -0,0 +1,6 @@+module Main where++import qualified Dhall.Docs++main :: IO ()+main = Dhall.Docs.main
+ doctest/Main.hs view
@@ -0,0 +1,18 @@+module Main where++import System.FilePath ((</>))++import qualified GHC.IO.Encoding+import qualified System.Directory+import qualified System.IO+import qualified Test.DocTest++main :: IO ()+main = do+ GHC.IO.Encoding.setLocaleEncoding System.IO.utf8+ pwd <- System.Directory.getCurrentDirectory+ prefix <- System.Directory.makeAbsolute pwd+ Test.DocTest.doctest+ [ "--fast"+ , prefix </> "src"+ ]
+ src/Dhall/Docs.hs view
@@ -0,0 +1,132 @@+{-| This module contains the top level and options parsing of the @dhall-docs@+ executable+-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Dhall.Docs+ ( -- * Options+ Options(..)+ , parserInfoOptions+ , parseOptions++ -- * Execution+ , main+ , defaultMain+ ) where++import Control.Applicative ((<|>))+import Data.Monoid ((<>))+import Data.Text (Text)+import Data.Version (showVersion)+import Dhall.Docs.Core+import Options.Applicative (Parser, ParserInfo)+import Path (Abs, Dir, Path)++import qualified Control.Monad+import qualified Data.Text+import qualified Data.Text.IO as Text.IO+import qualified GHC.IO.Encoding+import qualified Options.Applicative+import qualified Path+import qualified Path.IO+import qualified Paths_dhall_docs as Meta+import qualified System.Directory+import qualified System.Exit+import qualified System.IO++-- | Command line options+data Options+ = Options+ { packageDir :: FilePath -- ^ Directory where your package resides+ , docLink :: FilePath -- ^ Link to the generated documentation+ , resolvePackageName :: Path Abs Dir -> Text+ }+ | Version++-- | `Parser` for the `Options` type+parseOptions :: Parser Options+parseOptions =+ ( Options+ <$> Options.Applicative.strOption+ ( Options.Applicative.long "input"+ <> Options.Applicative.metavar "INPUT"+ <> Options.Applicative.help "Directory of your dhall package" )+ <*> Options.Applicative.strOption+ ( Options.Applicative.long "output-link"+ <> Options.Applicative.metavar "OUTPUT-LINK"+ <> Options.Applicative.help+ ( "Path to the link targeting the directory with the generated "+ <> "documentation. The path needs to not exist or to be a symlink, "+ <> "otherwise the tool won't generate any docs at all"+ )+ <> Options.Applicative.value "./docs" )+ <*> parsePackageNameResolver+ ) <|> parseVersion+ where+ parseVersion =+ Options.Applicative.flag'+ Version+ ( Options.Applicative.long "version"+ <> Options.Applicative.help "Display version"+ )++ parsePackageNameResolver :: Parser (Path Abs Dir -> Text)+ parsePackageNameResolver = fmap f (Options.Applicative.optional p)+ where+ -- Directories on the `path` modules always ends in "/", so we have+ -- to remove last one with `init`+ f Nothing = Data.Text.pack . init . Path.fromRelDir . Path.dirname+ f (Just packageName) = const $ Data.Text.pack packageName++ p = Options.Applicative.strOption+ ( Options.Applicative.long "package-name"+ <> Options.Applicative.metavar "PACKAGE-NAME"+ <> Options.Applicative.help+ ( "Override for the package name seen on HTML "+ <> "navbars. By default, it will extract it from "+ <> "the input"+ )+ )++-- | `ParserInfo` for the `Options` type+parserInfoOptions :: ParserInfo Options+parserInfoOptions =+ let progDesc = "Generate HTML documentation from a dhall package or file" in+ Options.Applicative.info+ (Options.Applicative.helper <*> parseOptions)+ ( Options.Applicative.fullDesc+ <> Options.Applicative.progDesc progDesc+ )+++-- | Default execution of @dhall-docs@ command+defaultMain :: Options -> IO ()+defaultMain = \case+ Options{..} -> do+ GHC.IO.Encoding.setLocaleEncoding System.IO.utf8+ resolvedPackageDir <- Path.IO.resolveDir' packageDir++ outDirExists <- System.Directory.doesPathExist docLink+ Control.Monad.when outDirExists $ do+ isLink <- System.Directory.pathIsSymbolicLink docLink+ if isLink then System.Directory.removeFile docLink+ else die $ "The specified --output-link (" <> Data.Text.pack docLink+ <> ") already exists and it's not a symlink."++ resolvedDocLink <- Path.IO.resolveDir' docLink+ let packageName = resolvePackageName resolvedPackageDir+ generateDocs resolvedPackageDir resolvedDocLink packageName+ Version ->+ putStrLn (showVersion Meta.version)++die :: Text -> IO a+die e = do+ Text.IO.hPutStrLn System.IO.stderr e++ System.Exit.exitFailure++-- | Entry point for the @dhall-docs@ executable+main :: IO ()+main = Options.Applicative.execParser parserInfoOptions >>= defaultMain
+ src/Dhall/Docs/Core.hs view
@@ -0,0 +1,435 @@+{-| Contains all the functions that generate documentation++ We should always try to do as little work as possible in an `IO` context.+ To do so, just wrap your function in `IO` if you need to do I/O operations,+ and make pure functions receive that IO result as an input+-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+-- {-# OPTIONS_GHC -Wno-unused-imports #-}++module Dhall.Docs.Core (generateDocs, generateDocsPure, GeneratedDocs(..)) where++import Control.Monad.Writer.Class (MonadWriter)+import Data.Function (on)+import Data.Map.Strict (Map)+import Data.Monoid ((<>))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Core+ ( Binding (..)+ , Expr (..)+ , Import+ , MultiLet (..)+ , Var (..)+ , denote+ )+import Dhall.Docs.Embedded+import Dhall.Docs.Html+import Dhall.Docs.Markdown+import Dhall.Docs.Store+import Dhall.Parser+ ( Header (..)+ , ParseError (..)+ , exprAndHeaderFromText+ )+import Dhall.Src (Src)+import Path (Abs, Dir, File, Path, Rel, (</>))+import Text.Megaparsec (ParseErrorBundle (..))++import qualified Control.Applicative as Applicative+import qualified Control.Monad+import qualified Control.Monad.Writer.Class as Writer+import qualified Data.ByteString+import qualified Data.Either+import qualified Data.List+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map.Strict as Map+import qualified Data.Maybe+import qualified Data.Maybe as Maybe+import qualified Data.Text+import qualified Data.Text.IO as Text.IO+import qualified Data.Text.Lazy as Text.Lazy+import qualified Dhall.Core+import qualified Lucid+import qualified Path+import qualified Path.IO+import qualified System.FilePath as FilePath+import qualified Text.Megaparsec++-- $setup+-- >>> :set -XQuasiQuotes+-- >>> import Path (reldir)++-- | The result of the doc-generator pure component+data GeneratedDocs a = GeneratedDocs [DocsGenWarning] a++instance Functor GeneratedDocs where+ fmap f (GeneratedDocs w a) = GeneratedDocs w (f a)++instance Applicative GeneratedDocs where+ pure = GeneratedDocs []++ GeneratedDocs w f <*> GeneratedDocs w' a = GeneratedDocs (w <> w') (f a)++instance Monad GeneratedDocs where+ GeneratedDocs w a >>= f =+ let GeneratedDocs w' b = f a+ in GeneratedDocs (w <> w') b++instance MonadWriter [DocsGenWarning] GeneratedDocs where+ tell w = GeneratedDocs w ()++ listen (GeneratedDocs w a) = GeneratedDocs w (a, w)+ pass (GeneratedDocs w (a, f)) = GeneratedDocs (f w) a++data DocsGenWarning+ = InvalidDhall (Text.Megaparsec.ParseErrorBundle Text Void)+ | InvalidMarkdown MarkdownParseError++instance Show DocsGenWarning where+ show (InvalidDhall err) =+ "\n\ESC[1;33mWarning\ESC[0m: Invalid Input\n\n" <>+ Text.Megaparsec.errorBundlePretty err <>+ "... documentation won't be generated for this file"++ show (InvalidMarkdown MarkdownParseError{..}) =+ "\n\ESC[1;33mWarning\ESC[0m: Header comment is not markdown\n\n" <>+ Text.Megaparsec.errorBundlePretty unwrap <>+ "The original non-markdown text will be pasted in the documentation"++-- | Represents a Dhall file that can be rendered as documentation.+-- If you'd like to improve or add features to a .dhall documentation page,+-- add that extra information here.+data DhallFile = DhallFile+ { path :: Path Rel File -- ^ Path of the file+ , expr :: Expr Src Import -- ^ File contents+ , header :: Header -- ^ Parsed `Header` of the file+ , mType :: Maybe (Expr Void Import) -- ^ Type of the parsed expression,+ -- extracted from the source code+ , examples :: [Expr Void Import] -- ^ Examples extracted from assertions+ -- in the file+ }++{-| Takes a list of files paths with their contents and returns the list of+ valid `DhallFile`s.++ Returned files contains all the information to be used on `Html ()`+ generation.++ The result is sorted by `path`+-}+getAllDhallFiles :: [(Path Rel File, Text)] -> GeneratedDocs [DhallFile]+getAllDhallFiles = emitErrors . map toDhallFile . filter hasDhallExtension+ where+ hasDhallExtension :: (Path Rel File, Text) -> Bool+ hasDhallExtension (absFile, _) = case Path.splitExtension absFile of+ Nothing -> False+ Just (_, ext) -> ext == ".dhall"++ toDhallFile :: (Path Rel File, Text) -> Either DocsGenWarning DhallFile+ toDhallFile (relFile, contents) =+ case exprAndHeaderFromText (Path.fromRelFile relFile) contents of+ Right (header, expr) ->+ let denoted = denote expr :: Expr Void Import in+ Right DhallFile+ { path = relFile+ , expr, header+ , mType = extractTypeIfInSource denoted+ , examples = examplesFromAssertions denoted+ }+ Left ParseError{..} ->+ Left $ InvalidDhall unwrap++ emitErrors :: [Either DocsGenWarning DhallFile] -> GeneratedDocs [DhallFile]+ emitErrors errorsOrDhallFiles = do+ let (errors, dhallFiles) = Data.Either.partitionEithers errorsOrDhallFiles+ Writer.tell errors+ let sortedDhallFiles = Data.List.sortBy (compare `on` path) dhallFiles+ return sortedDhallFiles++ bindings :: Expr Void Import -> [Binding Void Import]+ bindings expr = case expr of+ Let b@Binding{} e ->+ let MultiLet bs _ = Dhall.Core.multiLet b e+ in NonEmpty.toList bs+ _ -> []+++ extractTypeIfInSource :: Expr Void Import -> Maybe (Expr Void Import)+ extractTypeIfInSource expr = do+ V name index <- maybeNameInLet expr+ (Binding _ _ _ (Just (_, exprType)) _ _) <-+ getLetBindingWithIndex index $ getLetBindingsWithName name+ return exprType+ where+ -- | For an expression of the form @let x0 = y0 let x1 = y1 ... in e@+ -- where @e@ is a variable, maybeNameInLet returns the variable name.+ maybeNameInLet :: Expr Void Import -> Maybe Var+ maybeNameInLet (Var v@(V _ _)) = Just v+ maybeNameInLet (Let _ e) = maybeNameInLet e+ maybeNameInLet _ = Nothing+++ {-| For an expression of the form @let x0 = y0 x1 = y1 ... in e@+ and a variable name @v@, this returns every @xi@ that is equal to+ v in the reverse order of the source code.++ For example, take a file like this:++ > let x = 1+ > let y = 2+ > let z = 3+ > in x + y + z++ ... this will return the bindings in this order: [z, y, x]++ Only the "global" level of the file is analyzed+ -}+ getLetBindingsWithName :: Text -> [Binding Void Import]+ getLetBindingsWithName name = filter bindName $ reverse $ bindings expr+ where+ bindName (Binding _ x _ _ _ _) = x == name+++ getLetBindingWithIndex :: Int -> [Binding Void Import] -> Maybe (Binding Void Import)+ getLetBindingWithIndex i bs =+ case drop i bs of+ [] -> Nothing+ binding : _ -> Just binding++ examplesFromAssertions :: Expr Void Import -> [Expr Void Import]+ examplesFromAssertions expr = Maybe.mapMaybe fromAssertion values+ where+ values :: [Expr Void Import]+ values = map value $ bindings expr++ fromAssertion :: Expr Void Import -> Maybe (Expr Void Import)+ fromAssertion (Assert e) = Just e+ fromAssertion _ = Nothing++{-| Given a relative path, returns as much @..\/@ misdirections as needed+ to go to @.@++>>> resolveRelativePath [reldir|.|]+""+>>> resolveRelativePath [reldir|a|]+"../"+>>> resolveRelativePath [reldir|a/b/c|]+"../../../"+-}+resolveRelativePath :: Path Rel Dir -> FilePath+resolveRelativePath currentDir =+ case FilePath.dropTrailingPathSeparator $ Path.fromRelDir currentDir of+ "." -> ""+ _ -> "../" <> resolveRelativePath (Path.parent currentDir)++{-| Generates `Text` from the html representation of a `DhallFile`+-}+makeHtml+ :: Text -- ^ Package name+ -> DhallFile -- ^ Parsed header+ -> GeneratedDocs Text+makeHtml packageName DhallFile {..} = do+ let relativeResourcesPath = resolveRelativePath $ Path.parent path+ let strippedHeader = stripCommentSyntax header+ headerAsHtml <-+ case markdownToHtml path strippedHeader of+ Left err -> do+ Writer.tell [InvalidMarkdown err]+ return $ Lucid.toHtml strippedHeader+ Right html -> return html++ let htmlAsText = Text.Lazy.toStrict $ Lucid.renderText $ dhallFileToHtml+ path+ expr+ examples+ headerAsHtml+ DocParams { relativeResourcesPath, packageName }++ return htmlAsText+ where+ stripCommentSyntax :: Header -> Text+ stripCommentSyntax (Header h)+ | Just s <- Data.Text.stripPrefix "--" strippedHeader+ = Data.Text.strip s+ | Just commentPrefixStripped <- Data.Text.stripPrefix "{-" strippedHeader+ , Just commentSuffixStripped <- Data.Text.stripSuffix "-}" commentPrefixStripped+ = Data.Text.strip commentSuffixStripped+ | otherwise = strippedHeader+ where+ strippedHeader = Data.Text.strip h++{-| Create an @index.html@ file on each available folder in the input.++ Each @index.html@ lists the files and directories of its directory. Listed+ directories will be compacted as much as it cans to improve readability.++ For example, take the following directory-tree structure++ > .+ > ├── a+ > │ └── b+ > │ └── c+ > │ └── b.dhall+ > └── a.dhall++ To improve navigation, the index at @./index.html@ should list+ @a/b/c@ and no @index.html@ should be generated inside of `a/` or+ `a/b/`, but yes on `a/b/c/` in the last one there is the @b.dhall@ file+-}+createIndexes :: Text -> [DhallFile] -> [(Path Rel File, Text)]+createIndexes packageName files = map toIndex dirToDirsAndFilesMapAssocs+ where+ -- Files grouped by their directory+ dirToFilesMap :: Map (Path Rel Dir) [DhallFile]+ dirToFilesMap = Map.unionsWith (<>) $ map toMap files+ where+ toMap :: DhallFile -> Map (Path Rel Dir) [DhallFile]+ toMap dhallFile =+ Map.singleton (Path.parent $ path dhallFile) [dhallFile]++ {- This is used to compute the list of exported packages on each folder.+ We try to compress the folders as much as we can. See `createIndexes`+ documentation to get more information.+ -}+ dirToDirsMap :: Map (Path Rel Dir) [Path Rel Dir]+ dirToDirsMap = Map.map removeHereDir $ foldl go initialMap dirs+ where+ -- > removeHeredir [$(mkRelDir "a"), $(mkRelDir ".")]+ -- [$(mkRelDir "a")]+ removeHereDir :: [Path Rel Dir] -> [Path Rel Dir]+ removeHereDir = filter f+ where+ f :: Path Rel Dir -> Bool+ f reldir = Path.parent reldir /= reldir++ dirs :: [Path Rel Dir]+ dirs = Map.keys dirToFilesMap++ initialMap :: Map (Path Rel Dir) [Path Rel Dir]+ initialMap = Map.fromList $ map (,[]) dirs++ go :: Map (Path Rel Dir) [Path Rel Dir] -> Path Rel Dir -> Map (Path Rel Dir) [Path Rel Dir]+ go dirMap d = Map.adjust ([d] <>) (key $ Path.parent d) dirMap+ where+ key :: Path Rel Dir -> Path Rel Dir+ key dir = if dir `Map.member` dirMap then dir else key $ Path.parent dir++ dirToDirsAndFilesMapAssocs :: [(Path Rel Dir, ([DhallFile], [Path Rel Dir]))]+ dirToDirsAndFilesMapAssocs = Map.assocs $ Map.mapWithKey f dirToFilesMap+ where+ f :: Path Rel Dir -> [DhallFile] -> ([DhallFile], [Path Rel Dir])+ f dir dhallFiles = case dirToDirsMap Map.!? dir of+ Nothing -> fileAnIssue "dirToDirsAndFilesMapAssocs"+ Just dirs -> (dhallFiles, dirs)++ toIndex :: (Path Rel Dir, ([DhallFile], [Path Rel Dir])) -> (Path Rel File, Text)+ toIndex (indexDir, (dhallFiles, dirs)) =+ (indexDir </> $(Path.mkRelFile "index.html"), Text.Lazy.toStrict $ Lucid.renderText html)+ where+ html = indexToHtml+ indexDir+ (map (\DhallFile{..} -> (stripPrefix $ addHtmlExt path, mType)) dhallFiles)+ (map stripPrefix dirs)+ DocParams { relativeResourcesPath = resolveRelativePath indexDir, packageName }++ stripPrefix :: Path Rel a -> Path Rel a+ stripPrefix relpath =+ if Path.toFilePath relpath == Path.toFilePath indexDir then relpath+ else Data.Maybe.fromMaybe (fileAnIssue "Bug+with+stripPrefix")+ $ Path.stripProperPrefix indexDir relpath++-- | Takes a file and adds an @.html@ file extension to it+addHtmlExt :: Path Rel File -> Path Rel File+addHtmlExt relFile =+ Data.Maybe.fromMaybe (fileAnIssue "addHtmlExt") $ Path.addExtension ".html" relFile++-- | If you're wondering the GitHub query params for issue creation:+-- https://docs.github.com/en/github/managing-your-work-on-github/about-automation-for-issues-and-pull-requests-with-query-parameters+fileAnIssue :: Text -> a+fileAnIssue titleName =+ error $ "\ESC[1;31mError\ESC[0mDocumentation generator bug\n\n" <>++ "Explanation: This error message means that there is a bug in the " <>+ "Dhall Documentation generator. You didn't did anything wrong, but " <>+ "if you would like to see this problem fixed then you should report " <>+ "the bug at:\n\n" <>++ "https://github.com/dhall-lang/dhall-haskell/issues/new?labels=dhall-docs,bug\n\n" <>++ "explaining your issue and add \"" <> Data.Text.unpack titleName <> "\" as error code " <>+ "so we can find the proper location in the source code where the error happened\n\n" <>++ "Please, also include your package in the issue. It can be in:\n\n" <>+ "* A compressed archive (zip, tar, etc)\n" <>+ "* A git repository, preferably with a commit reference"++{-| Generate all of the docs for a package. This function does all the `IO ()`+ related tasks to call `generateDocsPure`+-}+generateDocs+ :: Path Abs Dir -- ^ Input directory+ -> Path Abs Dir -- ^ Link to be created to the generated documentation+ -> Text -- ^ Package name, used in some HTML titles+ -> IO ()+generateDocs inputDir outLink packageName = do+ (_, absFiles) <- Path.IO.listDirRecur inputDir+ contents <- mapM (Text.IO.readFile . Path.fromAbsFile) absFiles+ strippedFiles <- mapM (Path.stripProperPrefix inputDir) absFiles+ let GeneratedDocs warnings docs = generateDocsPure packageName $ zip strippedFiles contents+ mapM_ print warnings+ if null docs then+ putStrLn $+ "No documentation was generated because no file with .dhall " <>+ "extension was found"+ else Path.IO.withSystemTempDir "dhall-docs" $ \tempDir -> do+ copyDataDir tempDir+ mapM_ (writeGenFile tempDir) docs++ outputHash <- makeHashForDirectory tempDir+ outDir <- Applicative.liftA2 (</>)+ getDocsHomeDirectory+ (Path.parseRelDir+ $ show outputHash <> "-" <> Data.Text.unpack packageName)++ Path.IO.copyDirRecur tempDir outDir+ Path.IO.createDirLink outDir outLink+ where+ writeGenFile :: Path Abs Dir -> (Path Rel File, Text) -> IO ()+ writeGenFile outDir (relFile, contents) = do+ Path.IO.ensureDir (outDir </> Path.parent relFile)+ Text.IO.writeFile (Path.fromAbsFile $ outDir </> relFile) contents++ copyDataDir :: Path Abs Dir -> IO ()+ copyDataDir outDir = do+ dataDir <- getDataDir+ Control.Monad.forM_ dataDir $ \(filename, contents) -> do+ let finalPath = Path.fromAbsFile $ outDir </> filename+ Data.ByteString.writeFile finalPath contents++{-| Generates all the documentation of dhall package in a pure way i.e.+ without an `IO` context. This let you generate documentation from a list of+ dhall-files without saving them to the filesystem.++ If you want the `IO` version of this function, check `generateDocs`+-}+generateDocsPure+ :: Text -- ^ Package name+ -> [(Path Rel File, Text)] -- ^ (Input file, contents)+ -> GeneratedDocs [(Path Rel File, Text)]+generateDocsPure packageName inputFiles = go+ where+ go :: GeneratedDocs [(Path Rel File, Text)]+ go = do+ dhallFiles <- getAllDhallFiles inputFiles+ htmls <- mapM (makeHtml packageName) dhallFiles+ let indexes = createIndexes packageName dhallFiles+ return (zip (map (addHtmlExt . path) dhallFiles) htmls <> indexes)+
+ src/Dhall/Docs/Embedded.hs view
@@ -0,0 +1,45 @@+{-| Compile-time generated files, used to put all data-files in the executable+ to make it easy to distribute.+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}++module Dhall.Docs.Embedded (getDataDir) where++import Data.ByteString (ByteString)+import Path (File, Path, Rel)++import qualified Path++#if defined(EMBED)++import Data.FileEmbed (embedDir)++#else++import Paths_dhall_docs hiding (getDataDir)++import qualified Control.Monad+import qualified Data.ByteString as ByteString+import qualified Path.IO++#endif++getDataDir :: IO [(Path Rel File, ByteString)]+#if defined(EMBED)+getDataDir = return $(embedDir "src/Dhall/data") >>= mapM f+ where+ f :: (FilePath, ByteString) -> IO (Path Rel File, ByteString)+ f (filePath, contents) = (,contents) <$> Path.parseRelFile filePath+#else+getDataDir = do+ dir <- Path.parent+ <$> (getDataFileName "src/Dhall/data/index.css" >>= Path.parseAbsFile)+ files <- snd <$> Path.IO.listDir dir+ Control.Monad.forM files $ \file -> do+ contents <- ByteString.readFile $ Path.fromAbsFile file+ return (Path.filename file, contents)++#endif
+ src/Dhall/Docs/Html.hs view
@@ -0,0 +1,298 @@+{-| Functions used to generate HTML from a dhall package.+ You can see this module as logic-less HTML building blocks for the whole+ generator tool.++ There are functions that uses `FilePath` instead of `Path a b`. That is because+ the `Path` module doesn't allows to use ".." on its paths and that is needed+ here to properly link css and images.+-}++{-# LANGUAGE ExtendedDefaultRules #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Dhall.Docs.Html+ ( dhallFileToHtml+ , indexToHtml+ , DocParams(..)+ ) where++import Data.Monoid ((<>))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Core (Expr, Import)+import Dhall.Pretty (Ann (..))+import Dhall.Src (Src)+import Lucid+import Path (Dir, File, Path, Rel)++import qualified Control.Monad+import qualified Data.Foldable+import qualified Data.Text+import qualified Data.Text.Prettyprint.Doc as Pretty+import qualified Data.Text.Prettyprint.Doc.Render.Util.SimpleDocTree as Pretty+import qualified Dhall.Pretty+import qualified Path+import qualified System.FilePath as FilePath++-- $setup+-- >>> :set -XQuasiQuotes+-- >>> import Path (reldir, relfile)++-- | Internal utility to differentiate if a Dhall expr is a type annotation+-- or the whole file+data ExprType = TypeAnnotation | FileContentsExpr+++exprToHtml :: ExprType -> Expr a Import -> Html ()+exprToHtml exprType expr = pre_ $ renderTree prettyTree+ where+ layout = case exprType of+ FileContentsExpr -> Dhall.Pretty.layout+ TypeAnnotation -> typeLayout++ prettyTree = Pretty.treeForm+ $ layout+ $ Dhall.Pretty.prettyExpr expr++ textSpaces :: Int -> Text+ textSpaces n = Data.Text.replicate n (Data.Text.singleton ' ')++ renderTree :: Pretty.SimpleDocTree Ann -> Html ()+ renderTree sds = case sds of+ Pretty.STEmpty -> return ()+ Pretty.STChar c -> toHtml $ Data.Text.singleton c+ Pretty.STText _ t -> toHtml t+ Pretty.STLine i -> br_ [] >> toHtml (textSpaces i)+ Pretty.STAnn ann content -> encloseInTagFor ann (renderTree content)+ Pretty.STConcat contents -> foldMap renderTree contents++ encloseInTagFor :: Ann -> Html () -> Html ()+ encloseInTagFor ann = span_ [class_ classForAnn]+ where+ classForAnn = "dhall-" <> case ann of+ Keyword -> "keyword"+ Syntax -> "syntax"+ Label -> "label"+ Literal -> "literal"+ Builtin -> "builtin"+ Operator -> "operator"++ typeLayout :: Pretty.Doc ann -> Pretty.SimpleDocStream ann+ typeLayout = Pretty.removeTrailingWhitespace . Pretty.layoutSmart opts+ where+ -- this is done so the type of a dhall file fits in a single line+ -- its a safe value, since types in source codes are not that large+ opts :: Pretty.LayoutOptions+ opts = Pretty.defaultLayoutOptions+ { Pretty.layoutPageWidth =+ Pretty.Unbounded+ }+++-- | Params for commonly supplied values on the generated documentation+data DocParams = DocParams+ { relativeResourcesPath :: FilePath -- ^ Relative resource path to the+ -- front-end files+ , packageName :: Text -- ^ Name of the package+ }++-- | Generates an @`Html` ()@ with all the information about a dhall file+dhallFileToHtml+ :: Path Rel File -- ^ Source file name, used to extract the title+ -> Expr Src Import -- ^ Contents of the file+ -> [Expr Void Import] -- ^ Examples extracted from the assertions of the file+ -> Html () -- ^ Header document as HTML+ -> DocParams -- ^ Parameters for the documentation+ -> Html ()+dhallFileToHtml filePath expr examples header params@DocParams{..} =+ doctypehtml_ $ do+ headContents htmlTitle params+ body_ $ do+ navBar params+ mainContainer $ do+ setPageTitle params NotIndex breadcrumb+ copyToClipboardButton htmlTitle+ br_ []+ div_ [class_ "doc-contents"] header+ Control.Monad.unless (null examples) $ do+ h3_ "Examples"+ div_ [class_ "source-code code-examples"] $+ mapM_ (exprToHtml FileContentsExpr) examples+ h3_ "Source"+ div_ [class_ "source-code"] $ exprToHtml FileContentsExpr expr+ where+ breadcrumb = relPathToBreadcrumb filePath+ htmlTitle = breadCrumbsToText breadcrumb++-- | Generates an index @`Html` ()@ that list all the dhall files in that folder+indexToHtml+ :: Path Rel Dir -- ^ Index directory+ -> [(Path Rel File, Maybe (Expr Void Import))] -- ^ Generated files in that directory+ -> [Path Rel Dir] -- ^ Generated directories in that directory+ -> DocParams -- ^ Parameters for the documentation+ -> Html ()+indexToHtml indexDir files dirs params@DocParams{..} = doctypehtml_ $ do+ headContents htmlTitle params+ body_ $ do+ navBar params+ mainContainer $ do+ setPageTitle params Index breadcrumbs+ copyToClipboardButton htmlTitle+ br_ []+ Control.Monad.unless (null files) $ do+ h3_ "Exported files: "+ ul_ $ mconcat $ map listFile files++ Control.Monad.unless (null dirs) $ do+ h3_ "Exported packages: "+ ul_ $ mconcat $ map listDir dirs++ where+ listFile :: (Path Rel File, Maybe (Expr Void Import)) -> Html ()+ listFile (file, maybeType) =+ let fileRef = Data.Text.pack $ Path.fromRelFile file+ itemText = Data.Text.pack $ tryToTakeExt file+ in li_ $ do+ a_ [href_ fileRef] $ toHtml itemText+ Data.Foldable.forM_ maybeType $ \typeExpr -> do+ span_ [class_ "of-type-token"] ":"+ span_ [class_ "dhall-type source-code"] $ exprToHtml TypeAnnotation typeExpr+++ listDir :: Path Rel Dir -> Html ()+ listDir dir =+ let dirPath = Data.Text.pack $ Path.fromRelDir dir in+ li_ $ a_ [href_ (dirPath <> "index.html")] $ toHtml dirPath++ tryToTakeExt :: Path Rel File -> FilePath++ tryToTakeExt file = Path.fromRelFile $ case Path.splitExtension file of+ Nothing -> file+ Just (f, _) -> f++ breadcrumbs = relPathToBreadcrumb indexDir+ htmlTitle = breadCrumbsToText breadcrumbs++copyToClipboardButton :: Text -> Html ()+copyToClipboardButton filePath =+ a_ [class_ "copy-to-clipboard", data_ "path" filePath]+ $ i_ $ small_ "Copy path to clipboard"+++setPageTitle :: DocParams -> HtmlFileType -> Breadcrumb -> Html ()+setPageTitle DocParams{..} htmlFileType breadcrumb =+ h2_ [class_ "doc-title"] $ do+ span_ [class_ "crumb-divider"] "/"+ a_ [href_ $ Data.Text.pack $ relativeResourcesPath <> "index.html"]+ $ toHtml packageName+ breadCrumbsToHtml htmlFileType breadcrumb+++-- | ADT for handling bread crumbs. This is essentially a backwards list+-- See `relPathToBreadcrumb` for more information.+data Breadcrumb+ = Crumb Breadcrumb String+ | EmptyCrumb+ deriving Show++data HtmlFileType = NotIndex | Index++{-| Convert a relative path to a `Breadcrumb`.++>>> relPathToBreadcrumb [reldir|a/b/c|]+Crumb (Crumb (Crumb EmptyCrumb "a") "b") "c"+>>> relPathToBreadcrumb [reldir|.|]+Crumb EmptyCrumb ""+>>> relPathToBreadcrumb [relfile|c/foo.baz|]+Crumb (Crumb EmptyCrumb "c") "foo.baz"+-}+relPathToBreadcrumb :: Path Rel a -> Breadcrumb+relPathToBreadcrumb relPath = foldl Crumb EmptyCrumb splittedRelPath+ where+ filePath = Path.toFilePath relPath++ splittedRelPath :: [String]+ splittedRelPath = case FilePath.dropTrailingPathSeparator filePath of+ "." -> [""]+ _ -> FilePath.splitDirectories filePath++-- | Render breadcrumbs as `Html ()`+breadCrumbsToHtml :: HtmlFileType -> Breadcrumb -> Html ()+breadCrumbsToHtml htmlFileType = go startLevel+ where+ startLevel = case htmlFileType of+ NotIndex -> -1+ Index -> 0++ -- copyBreadcrumbButton :: Html ()+ -- copyBreadcrumbButton =+ -- button_+ -- [ class_ "btn copy-breadcrumb"+ -- , data_ "breadcrumb" $ breadCrumbsToText breadcrumb+ -- ] ""++ go :: Int -> Breadcrumb -> Html ()+ go _ EmptyCrumb = return ()+ go level (Crumb bc name) = do+ go (level + 1) bc+ span_ [class_ "crumb-divider"] $ toHtml ("/" :: Text)+ elem_ [class_ "title-crumb", href_ hrefTarget] $ toHtml name+ where+ hrefTarget = Data.Text.replicate level "../" <> "index.html"+ elem_ = if level == startLevel then span_ else a_+++-- | Render breadcrumbs as plain text+breadCrumbsToText :: Breadcrumb -> Text+breadCrumbsToText EmptyCrumb = ""+breadCrumbsToText (Crumb bc c) = breadCrumbsToText bc <> "/" <> Data.Text.pack c+++-- | nav-bar component of the HTML documentation+navBar+ :: DocParams -- ^ Parameters for doc generation+ -> Html ()+navBar DocParams{..} = div_ [class_ "nav-bar"] $ do++ -- Left side of the nav-bar+ img_ [ class_ "dhall-icon"+ , src_ $ Data.Text.pack $ relativeResourcesPath <> "dhall-icon.svg"+ ]+ p_ [class_ "package-title"] $ toHtml packageName++ div_ [class_ "nav-bar-content-divider"] ""++ -- Right side of the nav-bar+ -- with makeOption [id_ "go-to-source-code"] "Source code"+ with makeOption [id_ "switch-light-dark-mode"] "Switch Light/Dark Mode"+ where+ makeOption = with a_ [class_ "nav-option"]+++headContents :: Text -> DocParams -> Html ()+headContents title DocParams{..} =+ head_ $ do+ title_ $ toHtml title+ stylesheet $ relativeResourcesPath <> "index.css"+ stylesheet "https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ script relativeResourcesPath+ meta_ [charset_ "UTF-8"]++-- | main-container component builder of the HTML documentation+mainContainer :: Html() -> Html ()+mainContainer = div_ [class_ "main-container"]++stylesheet :: FilePath -> Html ()+stylesheet path =+ link_+ [ rel_ "stylesheet"+ , type_ "text/css"+ , href_ $ Data.Text.pack path]++script :: FilePath -> Html ()+script relativeResourcesPath =+ script_+ [ type_ "text/javascript"+ , src_ $ Data.Text.pack $ relativeResourcesPath <> "index.js"]+ ("" :: Text)
+ src/Dhall/Docs/Markdown.hs view
@@ -0,0 +1,32 @@+{-| Contains all utilities related to markdown processing+-}+module Dhall.Docs.Markdown+ ( MarkdownParseError(..)+ , markdownToHtml+ ) where++import Data.Text (Text)+import Lucid+import Path (File, Path, Rel)+import Text.Megaparsec (ParseErrorBundle (..))+import Text.MMark (MMarkErr)++import qualified Path+import qualified Text.MMark as MMark++-- | Wrapper around `MMarkErr` errors+newtype MarkdownParseError = MarkdownParseError+ { unwrap :: ParseErrorBundle Text MMarkErr+ }++{-| Takes a text that could contain markdown and returns the generated HTML.+ If an error occurs while parsing, it also returns the error information.+-}+markdownToHtml+ :: Path Rel File -- ^ Used by `Mmark.parse` for error messages+ -> Text -- ^ Text to parse+ -> Either MarkdownParseError (Html ())+markdownToHtml relFile contents =+ case MMark.parse (Path.fromRelFile relFile) contents of+ Left err -> Left MarkdownParseError { unwrap = err }+ Right mmark -> Right $ MMark.render mmark
+ src/Dhall/Docs/Store.hs view
@@ -0,0 +1,48 @@+{-| Utilities to interact with the dhall-docs home directory+-}+{-# OPTIONS_GHC -Wno-unused-imports #-}+{-# LANGUAGE QuasiQuotes #-}+++module Dhall.Docs.Store (getDocsHomeDirectory, makeHashForDirectory) where++import Dhall.Crypto (SHA256Digest (..), sha256Hash)+import Path (Abs, Dir, Path, Rel)+import Path.IO (XdgDirectory (..))++import qualified Codec.Archive.Tar as Tar+import qualified Codec.Archive.Tar.Entry as Tar.Entry+import qualified Data.ByteString.Lazy+import qualified Data.List+import qualified Path+import qualified Path.IO++{-| Fetches the dhall-docs home directory. If @XDG_DATA_HOME@ env var is+ defined, then @${XDG_DATA_HOME}/dhall-docs@ will be returned. Otherwise,+ "${HOME}/.local/share/dhall-docs"+-}+getDocsHomeDirectory :: IO (Path Abs Dir)+getDocsHomeDirectory = do+ dir <- Path.IO.getXdgDir Path.IO.XdgData $ Just $ [Path.reldir|dhall-docs|]+ Path.IO.ensureDir dir+ return dir++{-| Compute the hash for a directory. It takes into account the hierarchy+ structure of it and the contents of its files, but not the name of the+ actual files.++ This is done by computing the hash of each file and sorting them by its+ absolute file name, and computing the hash of the concatenation of all+ hashes.+-}+makeHashForDirectory :: Path Abs Dir -> IO SHA256Digest+makeHashForDirectory dir = do+ -- Builds a map so key order is preserved between several calls+ files <- Data.List.sort . map Path.fromRelFile . snd+ <$> Path.IO.listDirRecurRel dir++ let setTimeToZero entry = entry{Tar.Entry.entryTime = 0}+ inMemoryTarBytes <- Data.ByteString.Lazy.toStrict . Tar.write . map setTimeToZero+ <$> Tar.pack (Path.fromAbsDir dir) files++ return $ sha256Hash inMemoryTarBytes
+ src/Dhall/data/dhall-icon.svg view
@@ -0,0 +1,1 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="701 377 180 180" width="180pt" height="180pt"><defs><clipPath id="_clipPath_bHCrHBHhrzISq2YnO5draXOg8wrP22Y8"><rect x="701" y="377" width="180" height="180"/></clipPath></defs><g clip-path="url(#_clipPath_bHCrHBHhrzISq2YnO5draXOg8wrP22Y8)"><path d=" M 791 377 C 840.672 377 881 417.328 881 467 C 881 516.672 840.672 557 791 557 C 741.328 557 701 516.672 701 467 C 701 417.328 741.328 377 791 377 Z M 773.725 507.794 C 778.868 506.416 784.161 509.472 785.539 514.615 C 786.917 519.757 783.861 525.051 778.718 526.429 C 773.576 527.807 768.282 524.751 766.904 519.608 C 765.526 514.466 768.582 509.172 773.725 507.794 Z M 825.655 406.546 C 827.502 407.041 828.6 408.943 828.105 410.79 C 827.61 412.637 825.709 413.734 823.862 413.239 L 820.634 412.375 C 820.047 417.121 816.961 443.216 818.245 458.044 C 804.548 469.874 780.875 505.457 780.875 505.457 L 793.315 459.031 C 795.744 458.876 798.412 457.332 799.076 454.852 C 799.909 451.743 798.061 448.542 794.952 447.709 C 791.843 446.876 788.642 448.724 787.809 451.833 C 787.145 454.313 788.683 456.984 790.709 458.332 L 778.269 504.759 C 778.269 504.759 774.975 463.985 769.612 445.012 C 778.328 433.72 788.578 408.768 790.391 404.271 L 787.15 403.403 C 785.303 402.908 784.206 401.006 784.701 399.159 C 785.196 397.312 787.097 396.215 788.944 396.71 L 825.655 406.546 L 825.655 406.546 Z " fill-rule="evenodd" fill="rgb(235,235,235)"/></g></svg>
+ src/Dhall/data/index.css view
@@ -0,0 +1,244 @@+/*+ primary-color: #C4C4C4+ secondary-color: #EBEBEB+ accent-color1: #FFA632+ accent-color2: #008489+ accent-color3: #914669+*/++/******** Common rules ********/++body {+ padding: 0;+ margin: 0;+ background-color: #EBEBEB;+ transition: 0.5s;+}++body * {+ font-family: 'Lato', sans-serif;+}++a {+ transition: 0.5s;+ color: #008489;+}++a:visited {+ color: #914669;+}++a:active {+ color: #FFA632;+}++/******** Markdown specific code ********/++code {+ font-family: 'Fira Code', monospace;+}++blockquote {+ border-left: 9px solid #aaa;+ background-color: #bdbdbd;+ padding: 0.2rem;+ color: #616161;+}++/******** Nav bar **********/++.nav-bar {+ display: flex;+ align-items: center;+ padding: 0.3rem;+ background-color: #484848;+ color: #EBEBEB;+ transition: 0.5s;+}++.nav-bar .dhall-icon {+ max-width: 2.5rem;+ margin: 0.5rem;+}++.nav-bar .package-title {+ font-size: 1.3rem;+ margin: 0;+ margin-left: 1rem;+}++.nav-bar a.nav-option {+ font-size: 1rem;+ height: 100%;+ margin: 0 0.5rem;+ cursor: pointer;+ transition: 0.5s;+ text-decoration: none;+}++.nav-bar a.nav-option:hover {+ text-decoration: underline;+ text-decoration-color: #EBEBEB;+}++.nav-bar a.nav-option:active, .nav-bar a.nav-option, .nav-bar a.nav-option:visited {+ color: #EBEBEB;+}++.nav-bar .nav-bar-content-divider {+ flex: 1;+}++/******** Main content **********/++.main-container {+ padding: 2rem;+ padding-top: 0;+ transition: 0.5s;+}++h2.doc-title span, h2.doc-title a {+ font-family: 'Fira Code', monospace;+}++span.crumb-divider:first-child {+ margin-left: 0;+}++span.crumb-divider {+ margin: 0 0.5rem;+}++a.title-crumb {+ text-decoration: none;+}++a.title-crumb:hover {+ text-decoration: underline;+}++a.copy-to-clipboard {+ margin-top: 0;+ color: #888 !important;+ user-select: none;+ cursor: pointer;+ text-decoration: none;+}++a.copy-to-clipboard:hover {+ text-decoration: underline;+}++h2.doc-title {+ margin-bottom: 0;+}++/******** Source code **********/+++.code-examples > pre {+ padding-top: 0 !important;+ padding-bottom: 0 !important;+}++.source-code {+ padding: 0rem;+}++.source-code pre {+ padding: 1rem;+ font-family: 'Fira Code', monospace;+ color: #333333;+}++.source-code span {+ font-family: 'Fira Code', monospace;+ color: #333333;+}++.source-code span.dhall-keyword {+ color: #0000FF;+ font-weight: bold;+}++.source-code span.dhall-syntax {+ color: #AF00DB;+}++.source-code span.dhall-literal {+ color: #098658;+ font-weight: bold;+}++.source-code span.dhall-builtin {+ color: #267F99;+ font-weight: bold;+}++.dhall-type {+ font-family: 'Fira Code', monospace;+}++.dhall-type pre {+ display: inline;+ padding: 0;+}++span.of-type-token {+ margin-left: 0.5rem;+ margin-right: 0.5rem;+}++/******** Dark mode styling ********/++.dark-mode .main-container {+ color: #EBEBEB;+}++body.dark-mode {+ background-color: #484848;+}++.dark-mode .nav-bar {+ background-color: #5d5d5d;+}++.dark-mode a {+ color: #FFA632;+}++.dark-mode a:visited {+ color: #008489;+}++.dark-mode a:active {+ color: #914669;+}++.dark-mode .source-code pre {+ color: #D4D4D4;+}++.dark-mode .source-code span {+ color: #D4D4D4;+}++.dark-mode .source-code span.dhall-keyword {+ color: #569CD6;+}++.dark-mode .source-code span.dhall-syntax {+ color: #C586C0;+}++.dark-mode .source-code span.dhall-literal {+ color: #B5CEA8;+}++.dark-mode .source-code span.dhall-builtin {+ color: #4EC9B0;+}++.dark-mode a.copy-to-clipboard {+ color: #bdbdbd !important;+}
+ src/Dhall/data/index.js view
@@ -0,0 +1,36 @@+const DARK_MODE_OPT = 'dark-mode'+const DARK_MODE_ACTIVE = 'dark-mode-active'+const DARK_MODE_INACTIVE = 'dark-mode-inactive'++function onReady() {+ if (localStorage.getItem(DARK_MODE_OPT) == DARK_MODE_ACTIVE) {+ document.body.classList.add('dark-mode')+ } else {+ document.body.classList.remove('dark-mode')+ }+ document.getElementById('switch-light-dark-mode')+ .addEventListener('click', () => {+ document.body.classList.toggle('dark-mode')+ if (document.body.classList.contains('dark-mode')) {+ localStorage.setItem(DARK_MODE_OPT, DARK_MODE_ACTIVE)+ } else {+ localStorage.setItem(DARK_MODE_OPT, DARK_MODE_INACTIVE)+ }+ })++ document.querySelectorAll('a.copy-to-clipboard').forEach(node =>+ node.addEventListener('click', () => {+ const temp = document.createElement('input')+ document.body.append(temp)+ temp.value = node.dataset.path+ temp.select()+ document.execCommand("copy");+ temp.remove()+ }))+}++if (document.readyState != 'loading'){+ onReady();+} else {+ document.addEventListener('DOMContentLoaded', onReady);+}
+ tasty/Main.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -Wno-unused-imports #-}++module Main (main) where++import Data.Map.Strict (Map)+import Data.Text (Text)+import Dhall.Docs.Core+import Path (Dir, File, Path, Rel, (</>))+import Test.Tasty (TestTree)++import qualified Control.Monad+import qualified Data.Map.Strict as Map+import qualified Data.Text+import qualified Data.Text.IO as Text.IO+import qualified GHC.IO.Encoding+import qualified Path+import qualified Path.IO+import qualified Test.Tasty+import qualified Test.Tasty.Silver as Silver+import qualified Test.Tasty.Silver.Interactive as Silver+import qualified Text.PrettyPrint as Pretty+import qualified Text.XML.HaXml.Html.Parse as HaXml+import qualified Text.XML.HaXml.Pretty as HaXml++main :: IO ()+main = do+ GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8++ input <- getPackageContents+ let GeneratedDocs _ docs = generateDocsPure "test-package" input+ let docsMap = Map.fromList docs+ Silver.defaultMain $ testTree docsMap++getDirContents :: Path Rel Dir -> IO [(Path Rel File, Text)]+getDirContents dataDir = do+ files <- snd <$> Path.IO.listDirRecurRel dataDir+ Control.Monad.forM files $ \file -> do+ contents <- Text.IO.readFile $ Path.fromRelFile $ dataDir </> file+ return (file, contents)++goldenDir :: Path Rel Dir+goldenDir = $(Path.mkRelDir "./tasty/data/golden")++getPackageContents :: IO [(Path Rel File, Text)]+getPackageContents = getDirContents $(Path.mkRelDir "./tasty/data/package")++testTree :: Map (Path Rel File) Text -> TestTree+testTree docsMap =+ Test.Tasty.testGroup "dhall-docs"+ $ map makeTest $ Map.assocs docsMap+ where+ makeTest :: (Path Rel File, Text) -> TestTree+ makeTest (testFile, text) =+ Silver.goldenVsAction testName goldenFilePath action converter+ where+ goldenFilePath = Path.fromRelFile $ goldenDir </> testFile+ testName = Path.fromRelFile testFile+ action = return prettyHtmlDoc+ converter = Data.Text.pack++ prettyHtmlDoc = Pretty.render+ $ HaXml.document+ $ HaXml.htmlParse testName (Data.Text.unpack text)
+ tasty/data/golden/IndexesExample.dhall.html view
@@ -0,0 +1,77 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/IndexesExample.dhall</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >IndexesExample.dhall</span></h2+ ><a data-path="/IndexesExample.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Checking indexes</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >x</span+ ><br+ /> <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Bool</span+ ><br+ /> <span class="dhall-syntax"+ >=</span+ > <span class="dhall-builtin"+ >True</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >x</span+ ><br+ /> <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Natural</span+ ><br+ /> <span class="dhall-syntax"+ >=</span+ > <span class="dhall-literal"+ >1</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >x@1</span></pre></div></div></body></html>
+ tasty/data/golden/InvalidMarkdown.dhall.html view
@@ -0,0 +1,82 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/InvalidMarkdown.dhall</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >InvalidMarkdown.dhall</span></h2+ ><a data-path="/InvalidMarkdown.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ >Represents an status in our messaging system `+-- look, another line</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >Pair</span+ > <span class="dhall-syntax"+ >=</span+ > ./Pair.dhall<br+ /><br+ /><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >DeliveryStatus</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >Sent</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-label"+ >Pair</span+ > <span class="dhall-builtin"+ >Natural</span+ > <span class="dhall-builtin"+ >Text</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >InProgress</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >InQueue</span+ > <span class="dhall-syntax"+ >></span+ ><br+ /><br+ /><span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >DeliveryStatus</span></pre></div></div></body></html>
+ tasty/data/golden/MarkdownExample.dhall.html view
@@ -0,0 +1,141 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/MarkdownExample.dhall</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >MarkdownExample.dhall</span></h2+ ><a data-path="/MarkdownExample.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><h1 id="heading-1"+ >Heading 1</h1+ >+<h2 id="heading-2"+ >Heading 2</h2+ >+<h3 id="heading-3"+ >Heading 3</h3+ >+<h4 id="heading-4"+ >Heading 4</h4+ >+<h5 id="heading-5"+ >Heading 5</h5+ >+<h6 id="heading-6"+ >Heading 6</h6+ >+<p+ >Message data type for our <em+ >messaging-system</em> config.</p+ >+<pre+ ><code+ >It is similar to the `kafka` message dto.+</code></pre+ >+<p+ >testing again another random text.</p+ >+<p+ ><strong+ >NOTE</strong>: This is really important to know</p+ >+<p+ >This allows you to:</p+ >+<ul+ >+<li+ >+Send messages+</li+ >+<li+ >+Receive messages, knowing that:+<ul+ >+<li+ >+nothing works (?)+</li+ >+<li+ >+weird huh+</li>+</ul>+</li>+</ul+ >+<p+ >As somebody said,</p+ >+<blockquote+ >+<p+ >The best way to code is to not code</p>+</blockquote+ >+<p+ >Here I show you some haskell code</p+ >+<pre+ ><code class="language-haskell"+ >main = putStrLn "dhall rulez"+</code></pre>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-syntax"+ >{</span+ > <span class="dhall-label"+ >remitent</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Text</span+ ><span class="dhall-syntax"+ >,</span+ > <span class="dhall-label"+ >deliveryStatus</span+ > <span class="dhall-syntax"+ >:</span+ > ./DeliveryStatus.dhall<span class="dhall-syntax"+ >,</span+ > <span class="dhall-label"+ >body</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Text</span+ > <span class="dhall-syntax"+ >}</span></pre></div></div></body></html>
+ tasty/data/golden/Pair.dhall.html view
@@ -0,0 +1,134 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/Pair.dhall</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >Pair.dhall</span></h2+ ><a data-path="/Pair.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Just a <em+ >Pair</em> right here</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >Pair</span+ ><br+ /> <span class="dhall-syntax"+ >:</span+ > <span class="dhall-syntax"+ >∀</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >A</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ >∀</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >B</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-builtin"+ >Type</span+ ><br+ /> <span class="dhall-syntax"+ >=</span+ > <span class="dhall-syntax"+ >λ</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >A</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ >λ</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >B</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ >{</span+ > <span class="dhall-label"+ >first</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-label"+ >A</span+ ><span class="dhall-syntax"+ >,</span+ > <span class="dhall-label"+ >second</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-label"+ >B</span+ > <span class="dhall-syntax"+ >}</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >Pair</span></pre></div></div></body></html>
+ tasty/data/golden/a/b.dhall.html view
@@ -0,0 +1,57 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a/b.dhall</title+ ><link href="../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html" class="title-crumb"+ >a</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >b.dhall</span></h2+ ><a data-path="/a/b.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Hi there boys</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >b</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-literal"+ >1</span+ > <span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >b</span></pre></div></div></body></html>
+ tasty/data/golden/a/b/c.dhall.html view
@@ -0,0 +1,61 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a/b/c.dhall</title+ ><link href="../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >a</a+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html" class="title-crumb"+ >b</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >c.dhall</span></h2+ ><a data-path="/a/b/c.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Hi there boys</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >c</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-literal"+ >1</span+ > <span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >c</span></pre></div></div></body></html>
+ tasty/data/golden/a/b/c/a.dhall.html view
@@ -0,0 +1,65 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a/b/c/a.dhall</title+ ><link href="../../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html" class="title-crumb"+ >a</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >b</a+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html" class="title-crumb"+ >c</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >a.dhall</span></h2+ ><a data-path="/a/b/c/a.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Hi there boys</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >a</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-literal"+ >1</span+ > <span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >a</span></pre></div></div></body></html>
+ tasty/data/golden/a/b/c/index.html view
@@ -0,0 +1,47 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a/b/c</title+ ><link href="../../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html" class="title-crumb"+ >a</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >b</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >c</span></h2+ ><a data-path="/a/b/c" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><h3+ >Exported files: </h3+ ><ul+ ><li+ ><a href="a.dhall.html"+ >a.dhall</a></li></ul></div></body></html>
+ tasty/data/golden/a/b/index.html view
@@ -0,0 +1,49 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a/b</title+ ><link href="../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >a</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >b</span></h2+ ><a data-path="/a/b" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><h3+ >Exported files: </h3+ ><ul+ ><li+ ><a href="c.dhall.html"+ >c.dhall</a></li></ul+ ><h3+ >Exported packages: </h3+ ><ul+ ><li+ ><a href="c/index.html"+ >c/</a></li></ul></div></body></html>
+ tasty/data/golden/a/index.html view
@@ -0,0 +1,45 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/a</title+ ><link href="../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >a</span></h2+ ><a data-path="/a" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><h3+ >Exported files: </h3+ ><ul+ ><li+ ><a href="b.dhall.html"+ >b.dhall</a></li></ul+ ><h3+ >Exported packages: </h3+ ><ul+ ><li+ ><a href="b/index.html"+ >b/</a></li></ul></div></body></html>
+ tasty/data/golden/deep/nested/folder/index.html view
@@ -0,0 +1,65 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/deep/nested/folder</title+ ><link href="../../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html" class="title-crumb"+ >deep</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >nested</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >folder</span></h2+ ><a data-path="/deep/nested/folder" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><h3+ >Exported files: </h3+ ><ul+ ><li+ ><a href="my-even.dhall.html"+ >my-even.dhall</a+ ><span class="of-type-token"+ >:</span+ ><span class="dhall-type source-code"+ ><pre+ ><span class="dhall-builtin"+ >Natural</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span></pre></span></li></ul></div></body></html>
+ tasty/data/golden/deep/nested/folder/my-even.dhall.html view
@@ -0,0 +1,246 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/deep/nested/folder/my-even.dhall</title+ ><link href="../../../index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="../../../index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="../../../dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="../../../index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../../index.html" class="title-crumb"+ >deep</a+ ><span class="crumb-divider"+ >/</span+ ><a href="../index.html" class="title-crumb"+ >nested</a+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html" class="title-crumb"+ >folder</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >my-even.dhall</span></h2+ ><a data-path="/deep/nested/folder/my-even.dhall"+ class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >Check if a natural is even or not returning an union data-type</p>+</div+ ><h3+ >Examples</h3+ ><div class="source-code code-examples"+ ><pre+ ><span class="dhall-label"+ >my-even</span+ > <span class="dhall-literal"+ >1</span+ > <span class="dhall-operator"+ >≡</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >odd</span></pre+ ><pre+ ><span class="dhall-label"+ >my-even</span+ > <span class="dhall-literal"+ >2</span+ > <span class="dhall-operator"+ >≡</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >even</span></pre></div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >my-even</span+ ><br+ /> <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Natural</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><br+ /> <span class="dhall-syntax"+ >=</span+ > <span class="dhall-syntax"+ >λ</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >n</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Natural</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ ><br+ /> <span class="dhall-keyword"+ >if</span+ > <span class="dhall-builtin"+ >Natural/even</span+ > <span class="dhall-label"+ >n</span+ > <span class="dhall-keyword"+ >then</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >even</span+ > <span class="dhall-keyword"+ >else</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >odd</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >example0</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-keyword"+ >assert</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-label"+ >my-even</span+ > <span class="dhall-literal"+ >1</span+ > <span class="dhall-operator"+ >≡</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >odd</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >let</span+ > <span class="dhall-label"+ >example0</span+ > <span class="dhall-syntax"+ >=</span+ > <span class="dhall-keyword"+ >assert</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-label"+ >my-even</span+ > <span class="dhall-literal"+ >2</span+ > <span class="dhall-operator"+ >≡</span+ > <span class="dhall-syntax"+ ><</span+ > <span class="dhall-label"+ >even</span+ > <span class="dhall-syntax"+ >|</span+ > <span class="dhall-label"+ >odd</span+ > <span class="dhall-syntax"+ >></span+ ><span class="dhall-syntax"+ >.</span+ ><span class="dhall-label"+ >even</span+ ><br+ /><br+ /><span class="dhall-keyword"+ >in</span+ > <span class="dhall-label"+ >my-even</span></pre></div></div></body></html>
+ tasty/data/golden/index.html view
@@ -0,0 +1,99 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"/></h2+ ><a data-path="/" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><h3+ >Exported files: </h3+ ><ul+ ><li+ ><a href="IndexesExample.dhall.html"+ >IndexesExample.dhall</a+ ><span class="of-type-token"+ >:</span+ ><span class="dhall-type source-code"+ ><pre+ ><span class="dhall-builtin"+ >Bool</span></pre></span></li+ ><li+ ><a href="InvalidMarkdown.dhall.html"+ >InvalidMarkdown.dhall</a></li+ ><li+ ><a href="MarkdownExample.dhall.html"+ >MarkdownExample.dhall</a></li+ ><li+ ><a href="Pair.dhall.html"+ >Pair.dhall</a+ ><span class="of-type-token"+ >:</span+ ><span class="dhall-type source-code"+ ><pre+ ><span class="dhall-syntax"+ >∀</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >A</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-syntax"+ >∀</span+ ><span class="dhall-syntax"+ >(</span+ ><span class="dhall-label"+ >B</span+ > <span class="dhall-syntax"+ >:</span+ > <span class="dhall-builtin"+ >Type</span+ ><span class="dhall-syntax"+ >)</span+ > <span class="dhall-syntax"+ >→</span+ > <span class="dhall-builtin"+ >Type</span></pre></span></li+ ><li+ ><a href="package.dhall.html"+ >package.dhall</a></li></ul+ ><h3+ >Exported packages: </h3+ ><ul+ ><li+ ><a href="deep/nested/folder/index.html"+ >deep/nested/folder/</a></li+ ><li+ ><a href="a/index.html"+ >a/</a></li></ul></div></body></html>
+ tasty/data/golden/package.dhall.html view
@@ -0,0 +1,64 @@+<!DOCTYPE HTML>+<html+ ><head+ ><title+ >/package.dhall</title+ ><link href="index.css" type="text/css" rel="stylesheet"+ /><link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Lato&display=swap"+ type="text/css" rel="stylesheet"+ /><script src="index.js" type="text/javascript"+ /><meta charset="UTF-8"/></head+ ><body+ ><div class="nav-bar"+ ><img src="dhall-icon.svg" class="dhall-icon"+ /><p class="package-title"+ >test-package</p+ ><div class="nav-bar-content-divider"+ /><a id="switch-light-dark-mode" class="nav-option"+ >Switch Light/Dark Mode</a></div+ ><div class="main-container"+ ><h2 class="doc-title"+ ><span class="crumb-divider"+ >/</span+ ><a href="index.html"+ >test-package</a+ ><span class="crumb-divider"+ >/</span+ ><span href="index.html" class="title-crumb"+ >package.dhall</span></h2+ ><a data-path="/package.dhall" class="copy-to-clipboard"+ ><i+ ><small+ >Copy path to clipboard</small></i></a+ ><br+ /><div class="doc-contents"+ ><p+ >This is your package entrypoint documentation</p>+</div+ ><h3+ >Source</h3+ ><div class="source-code"+ ><pre+ ><span class="dhall-syntax"+ >{</span+ > <span class="dhall-label"+ >Message</span+ > <span class="dhall-syntax"+ >=</span+ > ./Message.dhall<br+ /><span class="dhall-syntax"+ >,</span+ > <span class="dhall-label"+ >DeliveryStatus</span+ > <span class="dhall-syntax"+ >=</span+ > ./DeliveryStatus.dhall<br+ /><span class="dhall-syntax"+ >,</span+ > <span class="dhall-label"+ >Pair</span+ > <span class="dhall-syntax"+ >=</span+ > ./Pair.dhall<br+ /><span class="dhall-syntax"+ >}</span></pre></div></div></body></html>
+ tasty/data/package/IndexesExample.dhall view
@@ -0,0 +1,6 @@+{- Checking indexes -}++let x : Bool = True+let x : Natural = 1++in x@1
+ tasty/data/package/InvalidMarkdown.dhall view
@@ -0,0 +1,15 @@+-- Represents an status in our messaging system `+-- look, another line++let Pair = ./Pair.dhall++let DeliveryStatus =+ < Sent: Pair Natural Text {-| Message has been _sent_. It carries a ./Pair.dhall reference+ containing on the `first` field number of retries+ and on the `second` field the delivered text+ -}+ | InProgress -- | Message is on the way!+ | InQueue -- | Delivery for this message **hasn't** started+ >++in DeliveryStatus
+ tasty/data/package/MarkdownExample.dhall view
@@ -0,0 +1,41 @@+{-+# Heading 1++## Heading 2++### Heading 3++#### Heading 4++##### Heading 5++###### Heading 6++Message data type for our _messaging-system_ config.++ It is similar to the `kafka` message dto.+testing again another random text.++**NOTE**: This is really important to know++This allows you to:++* Send messages+* Receive messages, knowing that:+ - nothing works (?)+ - weird huh++As somebody said,++> The best way to code is to not code++Here I show you some haskell code++```haskell+main = putStrLn "dhall rulez"+```+-}+{ remitent: Text --| Remitent name+, deliveryStatus: ./DeliveryStatus.dhall --| Status+, body: Text --| Message body+}
+ tasty/data/package/Pair.dhall view
@@ -0,0 +1,11 @@++{- Just a *Pair* right here+-}++let Pair+ : forall(A: Type) -- | Type of first position+ -> forall(B: Type) -- | Type of second position+ -> Type+ = λ(A: Type) -> λ(B: Type) -> {first: A, second: B}++in Pair
+ tasty/data/package/ShouldBeIgnored.dhall view
@@ -0,0 +1,4 @@+{-+Should be ignored since it's syntactically invalid+-}+{
+ tasty/data/package/a/b.dhall view
@@ -0,0 +1,5 @@+{-+Hi there boys+-}++let b = 1 in b
+ tasty/data/package/a/b/c.dhall view
@@ -0,0 +1,5 @@+{-+Hi there boys+-}++let c = 1 in c
+ tasty/data/package/a/b/c/a.dhall view
@@ -0,0 +1,5 @@+{-+Hi there boys+-}++let a = 1 in a
+ tasty/data/package/deep/nested/folder/my-even.dhall view
@@ -0,0 +1,12 @@+{-+Check if a natural is even or not returning an union data-type+-}+let my-even+ : Natural → < even | odd >+ = λ(n : Natural) →+ if Natural/even n then < even | odd>.even else < even | odd >.odd++let example0 = assert : my-even 1 === <even | odd>.odd+let example0 = assert : my-even 2 === <even | odd>.even++in my-even
+ tasty/data/package/package.dhall view
@@ -0,0 +1,7 @@+{-+This is your package entrypoint documentation+-}+{ Message = ./Message.dhall+, DeliveryStatus = ./DeliveryStatus.dhall+, Pair = ./Pair.dhall+}