packages feed

hyakko 0.6.4 → 0.6.5

raw patch · 6 files changed

+215/−184 lines, 6 files

Files

hyakko.cabal view
@@ -1,5 +1,5 @@ name:             hyakko-version:          0.6.4+version:          0.6.5 cabal-version:    >= 1.6 build-type:       Simple license:          MIT@@ -50,7 +50,9 @@                   resources/parallel/public/fonts/novecento-bold.ttf                   resources/parallel/public/fonts/novecento-bold.woff extra-source-files:-                  src/Text/Markdown.hs+                  src/Hyakko/Text/Markdown.hs+                  src/Hyakko/Text/Templates.hs+                  src/Hyakko/Types.hs  source-repository head   type:           git
src/Hyakko.lhs view
@@ -30,14 +30,15 @@ fairly easily via a [separate languages file](https://github.com/sourrust/hyakko/blob/master/resources/languages.json). -> {-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}+> {-# LANGUAGE OverloadedStrings #-}  > module Main where -> import Text.Markdown+> import Hyakko.Text.Markdown+> import Hyakko.Text.Templates+> import Hyakko.Types -> import Data.Aeson-> import Data.HashMap.Strict (HashMap)+> import Data.Aeson (decode') > import qualified Data.HashMap.Strict as M > import Data.ByteString.Lazy.Char8 (ByteString) > import qualified Data.ByteString.Lazy.Char8 as L@@ -47,7 +48,7 @@ > import Data.List (sort) > import Data.Maybe (fromJust, isNothing) > import Data.Version (showVersion)-> import Control.Applicative ((<$>), (<*>), empty)+> import Control.Applicative ((<$>)) > import Control.Monad (filterM, (>=>), forM, forM_, unless) > import qualified Text.Blaze.Html as B > import Text.Blaze.Html.Renderer.Utf8 (renderHtml)@@ -81,25 +82,26 @@ > generateDocumentation :: Hyakko -> [FilePath] -> IO () > generateDocumentation _ [] = >   putStrLn "hyakko: no files or options given (try --help)"-> generateDocumentation opts xs = mapM_ generate xs->   where generate :: FilePath -> IO ()->         generate x = do->           code <- T.readFile x->           dataDir <- getDataDir->           let sections  = parse (getLanguage x) code->               opts'     = configHyakko opts dataDir->           unless (isNothing $ layout opts') $ do->             let layoutDir = fromJust $ layout opts'->             copyDirectory opts'$ dataDir </> "resources"->                                          </> layoutDir->                                          </> "public"->           if null sections then->             putStrLn $ "hyakko doesn't support the language extension "->                      ++ takeExtension x->             else do->               let highlighted = highlight x sections->                   y           = mapSections sections highlighted->               generateHTML opts' x y+> generateDocumentation opts xs = do+>   dataDir <- getDataDir+>   let opts'  = configHyakko opts dataDir+>       dirout = output opts'+>   style <- hyakkoStyles opts'+>   T.writeFile (dirout </> "hyakko.css") style+>   unless (isNothing $ layout opts') $ do+>     let layoutDir = fromJust $ layout opts'+>     copyDirectory opts' $ dataDir </> "resources" </> layoutDir+>                                   </> "public"+>   forM_ xs $ \x -> do+>     code <- T.readFile x+>     let sections  = parse (getLanguage x) code+>     if null sections then+>       putStrLn $ "hyakko doesn't support the language extension "+>                ++ takeExtension x+>       else do+>         let highlighted = highlight x sections+>             y           = mapSections sections highlighted+>         generateHTML opts' x y  Given a string of source code, parse out eacg block of prose and the code that follows it — by detecting which is which, line by line — then create an@@ -111,20 +113,24 @@ >   let sections = sectionOff "" "" xs >   in map M.fromList sections ->   where sectionOff :: Text -> Text -> [Text] -> [[(String, Text)]]->         sectionOff code docs [] = [ ("codeText", code)->                                   , ("docsText", docs)->                                   ] : []+>   where save :: Text -> Text -> [(String, Text)]+>         save code docs = [ ("codeText", code)+>                          , ("docsText", docs)+>                          ]++>         sectionOff :: Text -> Text -> [Text] -> [[(String, Text)]]+>         sectionOff code docs [] = save code docs : [] >         sectionOff code docs (y:ys) =->           if T.unpack y =~ r then->             handleDocs code->             else->               sectionOff (code ++. y ++. "\n") docs ys+>           let line    = T.unpack y+>               shebang = L.pack "(^#![/]|^\\s*#\\{)"+>           in if line =~ r && (not $ line =~ shebang) then+>                handleDocs code+>                else+>                  sectionOff (code ++. y ++. "\n") docs ys  >           where handleDocs "" = handleHeaders code (newdocs docs) ys->                 handleDocs _  = [ ("codeText", code)->                                 , ("docsText", docs)->                                 ] : handleHeaders "" (newdocs "") ys+>                 handleDocs _  = save code docs+>                               : handleHeaders "" (newdocs "") ys  >                 newdocs d = d ++. (replace r y "") ++. "\n" @@ -133,9 +139,7 @@  >                 handleHeaders c d zs = >                   if T.unpack d =~ L.pack "^(---|===)+" then->                     [ ("codeText", c)->                     , ("docsText", d)->                     ] : sectionOff "" "" zs+>                     save c d : sectionOff "" "" zs >                     else >                       sectionOff c d zs @@ -146,19 +150,17 @@ > parse :: Maybe Language -> Text -> Sections > parse Nothing _       = [] > parse (Just src) code =->   inSections (newlines line (literate src) True)+>   inSections (fromLiterate (T.lines code) (literate src) True) >              ("^\\s*" ++* symbol src ++* "\\s?")->   where line :: [Text]->         line = filter ((/=) "#!" . T.take 2) $ T.lines code  Transforms a literate style language file into its normal, non-literate-style language. If it is normal, `newlines` for returns the same list of+style language. If it is normal, `fromLiterate` for returns the same list of `Text` that was passed in. ->         newlines :: [Text] -> Maybe Bool -> Bool -> [Text]->         newlines [] _ _            = []->         newlines xs Nothing _      = xs->         newlines (x:xs) lit isText =+>   where fromLiterate :: [Text] -> Maybe Bool -> Bool -> [Text]+>         fromLiterate [] _ _            = []+>         fromLiterate xs Nothing _      = xs+>         fromLiterate (x:xs) lit isText = >           let s       = symbol src >               r       = "^" ++* (fromJust $ litSymbol src) ++* "\\s?" >               r1      = L.pack "^\\s*$"@@ -167,7 +169,7 @@ >                      else >                        insert (T.unpack x =~ r1) isText >                          ((T.pack $ L.unpack s)  ++. " " ++. x)->           in x': newlines xs lit y+>           in x': fromLiterate xs lit y  Inserts a comment symbol and a single space into the documentation line and check if the last line was code and documentation. If the previous line was@@ -206,80 +208,6 @@ >                       M.insert "codeHtml" (codeText x) sect >   in map intoMap [0 .. sectLength] -Determine whether or not there is a `Jump to` section.--> multiTemplate :: Int -> [(String, String)]-> multiTemplate 1 = []-> multiTemplate _ = [("multi", "1")]--Produces a list of anchor tags to different files in docs. This will only-show up if the template support it and there are more than one source file-generated.--> sourceTemplate :: Hyakko -> [FilePath] -> [(String, String)]-> sourceTemplate opts = map source->   where source x = ("source", concat->           [ "<a class=\"source\" href=\""->           , takeFileName $ destination (output opts) x->           , "\">"->           , takeFileName x->           , "</a>"->           ])--Depending on the layout type, `sectionTemplate` will produce the HTML that-will be hooked into the templates layout theme.--> sectionTemplate :: Sections->                 -> Maybe String->                 -> [Int]->                 -> [(String, String)]-> sectionTemplate section layoutType count =->   let isLayout = not $ isNothing layoutType->       sections = if isLayout then layoutFn $ fromJust layoutType->                  else undefined->   in map sections count->   where layoutFn "parallel" = parallel->         layoutFn "linear"   = linear->         layoutFn _          = undefined->         parallel x =->           let x'   = x + 1->               sect = section !! x->               docsHtml = T.unpack $ sect M.! "docsHtml"->               codeHtml = T.unpack $ sect M.! "codeHtml"->               codeText = T.unpack $ sect M.! "codeText"->               header   = docsHtml =~ L.pack "^\\s*<(h\\d)"->               isBlank  = T.null $ replace "\\s" (T.pack codeText) ""->           in ("section", concat->              [ "<li id=\"section-"->              , show x'->              , "\"><div class=\"annotation\">"->              , "<div class=\"pilwrap"->              , if null header then "" else " for-" ++ tail header->              , "\"><a class=\"pilcrow\" href=\""->              , show x'->              , "\">&#955;</a></div>"->              , docsHtml->              , "</div>"->              , if isBlank then "" else "<div class=\"content\">"->                  ++ codeHtml ++ "</div>"->              ])->         linear x =->           let sect   = section !! x->               codeText = T.unpack $ sect M.! "codeText"->               isText = not $ null codeText->           in ("section", concat->              [ T.unpack $ sect M.! "docsHtml"->              , if isText then T.unpack $ sect M.! "codeHtml" else []->              ])--> cssTemplate :: Hyakko -> [(String, String)]-> cssTemplate opts =->   let maybeLayout = layout opts->       normalize   = "public" </> "stylesheets" </> "normalize.css"->       otherFile   = if isNothing maybeLayout then id else->         ([normalize] ++)->   in zip ["css", "css"] $ otherFile ["hyakko.css"]- Once all of the code is finished highlighting, we can generate the HTML file and write out the documentation. Pass the completed sections into the template found in `resources/linear/hyakko.html` or@@ -324,33 +252,6 @@ Helpers & Setup --------------- -The `Sections` type is just an alias to keep type signatures short.--> type Sections = [HashMap String Text]--Alias `Languages`, for the multiple different languages inside the-`languages.json` file.--> type Languages = HashMap String Language--Better data type for language info — compared to the `Object` data type in-`Aeson`.--> data Language =->   Language { name_     :: ByteString->            , symbol    :: ByteString->            , literate  :: Maybe Bool->            , litSymbol :: Maybe ByteString->            }--> instance FromJSON Language where->   parseJSON (Object o) = Language->                      <$> o .:  "name"->                      <*> o .:  "symbol"->                      <*> o .:? "literate"->                      <*> o .:? "litSymbol"->   parseJSON _          = empty- Infix functions for easier concatenation with Text and ByteString.  > (++.) :: Text -> Text -> Text@@ -432,7 +333,7 @@ >   files <- forM file $ \x -> do >     isDir <- doesDirectoryExist x >     if isDir then->       unpackDirectories x >>= return . fst+>       fst <$> unpackDirectories x >       else >         return [x] >   return . sort $ concat files@@ -443,12 +344,12 @@ > unpackDirectories :: FilePath -> IO ([FilePath], [FilePath]) > unpackDirectories d = do >   let reg = L.pack "[^(^\\.{1,2}$)]"->   content <- getDirectoryContents d >>= return . filter (=~ reg)+>   content <-  filter (=~ reg) <$> getDirectoryContents d >   let content' = map (d </>) content >   files <- filterM doesFileExist content' >   subdir <- filterM doesDirectoryExist content'->   subcontent <- mapM unpackDirectories subdir >>= \x ->->     return (concatMap fst x, concatMap snd x)+>   subcontent <- fmap (\x -> (concatMap fst x, concatMap snd x))+>                      (mapM unpackDirectories subdir) >   return (files ++ fst subcontent, subdir ++ snd subcontent)  > copyDirectory :: Hyakko -> FilePath -> IO ()@@ -478,16 +379,6 @@ Configuration ------------- -Data structure for command line argument parsing.--> data Hyakko =->   Hyakko { layout     :: Maybe String->          , output     :: FilePath->          , css        :: Maybe FilePath->          , template   :: Maybe FilePath->          , dirOrFiles :: [FilePath]->          } deriving (Show, Data, Typeable)- Default configuration **options**. If no arguments for these flags are specifed, it will just use the ones in `defaultConfig`. @@ -524,9 +415,6 @@ > main :: IO () > main = do >   opts <- cmdArgs defaultConfig->   style <- hyakkoStyles opts >   source <- sources $ dirOrFiles opts->   let dirout = output opts->   createDirectoryIfMissing False dirout->   T.writeFile (dirout </> "hyakko.css") style+>   createDirectoryIfMissing False $ output opts >   generateDocumentation opts source
+ src/Hyakko/Text/Markdown.hs view
@@ -0,0 +1,16 @@+module Hyakko.Text.Markdown (toHTML) where++import Text.Pandoc ( readMarkdown+                   , writeHtmlString+                   , def+                   )++import Data.Text (Text, pack)++-- Function for translating Markdown to HTML since `Pandoc` has several+-- different generators for other markup languages.+toHTML :: String -> Text+toHTML = pack . writeHTMLStr . parse+  where parse = readMarkdown def+        writeHTMLStr = writeHtmlString def+{-# INLINE toHTML #-}
+ src/Hyakko/Text/Templates.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE OverloadedStrings #-}++module Hyakko.Text.Templates where++import Hyakko.Types++import Data.ByteString.Lazy.Char8 (ByteString)+import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.HashMap.Strict as M+import Data.Maybe (fromJust, isNothing)+import qualified Data.Text as T+import Data.Text (Text)+import System.FilePath (takeFileName, takeBaseName, (</>))+import Text.Regex.PCRE ((=~))++-- Determine whether or not there is a `Jump to` section.+multiTemplate :: Int -> [(String, String)]+multiTemplate 1 = []+multiTemplate _ = [("multi", "1")]++-- Produces a list of anchor tags to different files in docs. This will+-- only show up if the template support it and there are more than one+-- source file generated.+sourceTemplate :: Hyakko -> [FilePath] -> [(String, String)]+sourceTemplate opts = map source+  where source x = ("source", concat+          [ "<a class=\"source\" href=\""+          , takeFileName $ (output opts) </> (takeBaseName x) ++ ".html"+          , "\">"+          , takeFileName x+          , "</a>"+          ])++-- Depending on the layout type, `sectionTemplate` will produce the HTML+-- that will be hooked into the templates layout theme.+sectionTemplate :: Sections+                -> Maybe String+                -> [Int]+                -> [(String, String)]+sectionTemplate section layoutType count =+  let isLayout = not $ isNothing layoutType+      sections = if isLayout then layoutFn $ fromJust layoutType+                 else undefined+  in map sections count+  where layoutFn "parallel" = parallel+        layoutFn "linear"   = linear+        layoutFn _          = undefined++        -- Whenever the layout is sepecifed as **parallel**, this is the+        -- function that will generate the mapping for variable name and+        -- replacment value.+        parallel x =+          let x'   = x + 1+              sect = section !! x+              docsHtml = T.unpack $ sect M.! "docsHtml"+              codeHtml = T.unpack $ sect M.! "codeHtml"+              codeText = T.unpack $ sect M.! "codeText"+              header   = docsHtml =~ L.pack "^\\s*<(h\\d)"+              isBlank  = T.null $ replace "\\s" (T.pack codeText) ""+              sectnum  = "section-" ++ show x'+          in ("section", concat+             [ "<li id=\""+             , sectnum+             , "\"><div class=\"annotation\">"+             , "<div class=\"pilwrap"+             , if null header then "" else " for-" ++ tail header+             , "\"><a class=\"pilcrow\" href=\"#"+             , sectnum+             , "\">&#955;</a></div>"+             , docsHtml+             , "</div>"+             , if isBlank then "" else "<div class=\"content\">"+                 ++ codeHtml ++ "</div>"+             ])+          where replace :: ByteString -> Text -> Text -> Text+                replace reg orig replacer =+                  let str  = T.unpack orig+                      (_, _, rp) = str =~ reg :: (String, String, String)+                  in T.append replacer (T.pack rp)++        -- Far simpler layout compared to **parallel**. This function gets+        -- called when the layout is marked as **linear**.+        linear x =+          let sect   = section !! x+              codeText = T.unpack $ sect M.! "codeText"+              isText = not $ null codeText+          in ("section", concat+             [ T.unpack $ sect M.! "docsHtml"+             , if isText then T.unpack $ sect M.! "codeHtml" else []+             ])++cssTemplate :: Hyakko -> [(String, String)]+cssTemplate opts =+  let maybeLayout = layout opts+      normalize   = "public" </> "stylesheets" </> "normalize.css"+      otherFile   = if isNothing maybeLayout then id else+        ([normalize] ++)+  in zip ["css", "css"] $ otherFile ["hyakko.css"]
+ src/Hyakko/Types.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}++module Hyakko.Types where++import Control.Applicative ((<$>), (<*>), empty)+import Data.Aeson+import Data.ByteString.Lazy (ByteString)+import Data.HashMap.Strict (HashMap)+import Data.Text (Text)+import System.Console.CmdArgs++-- The `Sections` type is just an alias to keep type signatures short.+type Sections = [HashMap String Text]++-- Alias `Languages`, for the multiple different languages inside the+-- `languages.json` file.+type Languages = HashMap String Language++-- Better data type for language info — compared to the `Object` data type+-- in `Aeson`.+data Language =+  Language { name_     :: ByteString+           , symbol    :: ByteString+           , literate  :: Maybe Bool+           , litSymbol :: Maybe ByteString+           }++instance FromJSON Language where+  parseJSON (Object o) = Language+                     <$> o .:  "name"+                     <*> o .:  "symbol"+                     <*> o .:? "literate"+                     <*> o .:? "litSymbol"+  parseJSON _          = empty++-- Data structure for command line argument parsing.+data Hyakko =+  Hyakko { layout     :: Maybe String+         , output     :: FilePath+         , css        :: Maybe FilePath+         , template   :: Maybe FilePath+         , dirOrFiles :: [FilePath]+         } deriving (Show, Data, Typeable)
− src/Text/Markdown.hs
@@ -1,16 +0,0 @@-module Text.Markdown (toHTML) where--import Text.Pandoc ( readMarkdown-                   , writeHtmlString-                   , def-                   )--import Data.Text (Text, pack)---- Function for translating Markdown to HTML since `Pandoc` has several--- different generators for other markup languages.-toHTML :: String -> Text-toHTML = pack . writeHTMLStr . parse-  where parse = readMarkdown def-        writeHTMLStr = writeHtmlString def-{-# INLINE toHTML #-}