packages feed

gemmula 1.0.0 → 1.0.1

raw patch · 4 files changed

+36/−37 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,6 +1,10 @@  # `gemmula` Change Log +## 1.0.1 (January 08, 2024)+* Improve code readability and quality.+* Clean up some documentations.+ ## 1.0.0 (December 19, 2023) * Change the stability to `stable`. * Use strict data types and functions instead of lazy ones.
README.md view
@@ -1,11 +1,12 @@  # [gemmula](https://hackage.haskell.org/package/gemmula)-A tiny and functional Gemtext (`text/gemini`) parser from and to Text. -Check the Section 5 of the [Gemini Protocol specification](https://geminiprotocol.net/docs/specification.gmi)-for more about the `text/gemini` filetype.+A tiny and functional Gemtext (`text/gemini`) parser from and back to Text. -The documentation is available at [Hackage](https://hackage.haskell.org/package/gemmula/docs/Text-Gemini.html).+Check the Section 5 of the [Gemini Protocol specification](https://geminiprotocol.net/docs/specification.gmi)+for more about the `text/gemini` filetype.  +You can also check the [Gemini Protocol](https://geminiprotocol.net) capsule for more about the Gemini itself. +The documentation is available at [Hackage](https://hackage.haskell.org/package/gemmula/docs/Text-Gemini.html).   You can find more information and related modules at the [Codeberg repository](https://codeberg.org/sena/gemmula). 
gemmula.cabal view
@@ -1,8 +1,8 @@ name:               gemmula-version:            1.0.0+version:            1.0.1 synopsis:           A tiny Gemtext parser-description:        gemmula is a tiny and functional text/gemini (also known as Gemtext)-                    parser that aims to parse a Gemtext document from and to Text,+description:        gemmula is a tiny and functional Gemtext (unofficially text/gemini)+                    parser that aims to parse a Gemtext document from and back to Text,                     according to the Section 5 of the Gemini Protocol specification at                     <https://geminiprotocol.net/docs/specification.gmi>. license:            AGPL-3
src/Text/Gemini.hs view
@@ -9,9 +9,9 @@ -- Stability   :  stable -- Portability :  portable ----- A tiny @text/gemini@ parser.+-- A tiny Gemtext (@text/gemini@) parser. ----- Parses Gemtext documents from and to 'Text'. See the Section 5 of the+-- Parses Gemtext documents from and back to 'Text'. See the Section 5 of the -- [Gemini Protocol specification](https://geminiprotocol.net/docs/specification.gmi).  module Text.Gemini@@ -21,20 +21,19 @@     -- * Decoding from Text   , decode   , decodeLine-    -- * Encoding to Text+    -- * Encoding as Text   , encode   , encodeItem   ) where  import Data.Text (Text) import qualified Data.Text as T-import Data.Maybe (maybeToList)+import Data.Maybe (fromMaybe) import Data.Char (isSpace)-import Data.List (foldl') import Data.Bool (bool)  --- | A Gemtext document, in the form of an ordered list.+-- | A Gemtext document, in the form of an ordered list of 'GemItem's. type GemDocument = [GemItem]  -- | A Gemtext item.@@ -47,7 +46,7 @@              deriving (Show, Eq)  --- | Parse a @text/gemini@ file as 'GemDocument'.+-- | Parse a Gemtext file as 'GemDocument'. -- The text should be supplied as an LF-ending 'Text'. decode :: Text -> GemDocument decode = parse [] . T.lines@@ -62,29 +61,23 @@               | otherwise = parse (doc <> [decodeLine l]) ls           parse doc [] = doc -          -- List recursive parser with a list carried. Adds the line to-          -- the list if it starts with list prefix. If the line doesn't-          -- start with the prefix, will end the recursion and continue with-          -- @parse@, with the final list added to the carried 'GemDocument'-          -- as 'GemList'.+          -- List recursive parser. Continues with @parse@ when the line+          -- is no longer a list item, and adds the 'GemList' to the 'GemDocument'.           parseList :: GemDocument -> [Text] -> [Text] -> GemDocument           parseList doc glist (l:ls)               | l `hasValueOf` "* " = parseList doc (glist <> [value 1 l]) ls               | otherwise = parse (doc <> [GemList glist]) (l:ls)           parseList doc glist [] = doc <> [GemList glist] -          -- Preformatted recursive parser with lines carried. Adds the line to-          -- the list if the ending delimiter hasn't been reached yet. If the line-          -- is the ending with the delimiter, will end the recursion and continue-          -- with @parse@, with the final list of lines added to the carried-          -- 'GemDocument' as 'GemPre'.+          -- Preformatted recursive parser. Continues with @parse@ when the+          -- closing delimiter is reached, and adds the 'GemPre' to the 'GemDocument'.           parsePre :: GemDocument -> [Text] -> Maybe Text -> [Text] -> GemDocument           parsePre doc glines alt (l:ls)               | "```" `T.isPrefixOf` l = parse (doc <> [GemPre glines alt]) ls               | otherwise = parsePre doc (glines <> [l]) alt ls           parsePre doc glines alt [] = doc <> [GemPre glines alt] --- | Parse a /single/ @text/gemini@ line as 'GemItem'.+-- | Parse a /single/ Gemtext line as 'GemItem'. -- -- Notes: --@@ -107,15 +100,15 @@               where (pre, text) = T.span (=='#') l  --- | Encode parsed 'GemDocument' to a @text/gemini@ file.--- The output 'Text' uses LF-endings.+-- | Encode parsed 'GemDocument' as a Gemtext file.+-- The output 'Text' uses LF-endings. Uses the 'encodeItem' function below. encode :: GemDocument -> Text-encode = T.unlines . foldl' (\acc x -> acc <> [encodeItem x]) []+encode = T.unlines . map encodeItem --- | Encode a /single/ parsed 'GemItem' as @text/gemini@ text.+-- | Encode a /single/ parsed 'GemItem' as Gemtext text. -- The output 'Text' uses LF-endings and might be multiple lines. ----- /Beware/ that the final newline is always stripped, if any.+-- /Beware/ that the output text never ends with a newline. -- -- Notes: --@@ -124,12 +117,13 @@ --     * The link in the 'GemLink' should not have spaces. encodeItem :: GemItem -> Text encodeItem (GemText line) = escapePrefixes line-encodeItem (GemLink link desc) = T.unwords $ ["=>", link] <> maybeToList desc-encodeItem (GemHeading level text) = T.unwords [T.replicate (min level 3) "#", text]-encodeItem (GemList list) = T.stripEnd . T.unlines $ map (T.append "* ") list-encodeItem (GemQuote text) = T.unwords [">", text]-encodeItem (GemPre text alt) = T.stripEnd . T.unlines $ [T.concat (["```"] <> maybeToList alt)] <> text <> ["```"]+encodeItem (GemLink link desc) = "=> " <> link <> maybe "" (" " <>) desc+encodeItem (GemHeading level text) = T.replicate (min level 3) "#" <> " " <> text+encodeItem (GemList list) = T.intercalate "\n" $ map ("* " <>) list+encodeItem (GemQuote text) = "> " <> text+encodeItem (GemPre text alt) = T.intercalate "\n" $ ["```" <> fromMaybe "" alt] <> text <> ["```"] + -- Escape the line prefixes by adding a whitespace at the beginning for 'GemText'. escapePrefixes :: Text -> Text escapePrefixes line = bool line (T.cons ' ' line) escape@@ -144,11 +138,11 @@                          not (T.null $ value (T.length prefix) line)  -- Get the value of a line.--- Removes the prefix and strips.+-- Removes the prefix of given length and strips. value :: Int -> Text -> Text value prefix = T.strip . T.drop prefix  -- @Nothing@ if the text is empty. optional :: Text -> Maybe Text-optional text = if T.null text then Nothing else Just text+optional text = bool (Just text) Nothing $ T.null text