packages feed

cmark-gfm-lens (empty) → 0.2.0.0

raw patch · 5 files changed

+392/−0 lines, 5 filesdep +basedep +cmark-gfmdep +cmark-gfm-lens

Dependencies added: base, cmark-gfm, cmark-gfm-lens, hspec, lens, profunctors, text

Files

+ CHANGELOG.md view
@@ -0,0 +1,11 @@+# Revision history for cmark-gfm-lens++## 0.1.0.0 -- 2025-09-22++* First version. Released on an unsuspecting world.++## 0.2.0.0 -- 2025-10-10++* Rename `nodeTraversal` to `nodes`+* Add some inline documentations+* Export more lenses
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2025, ingun+++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * 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.++    * Neither the name of the copyright holder 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.
+ cmark-gfm-lens.cabal view
@@ -0,0 +1,124 @@+cabal-version:      3.12+-- The cabal-version field refers to the version of the .cabal specification,+-- and can be different from the cabal-install (the tool) version and the+-- Cabal (the library) version you are using. As such, the Cabal (the library)+-- version used must be equal or greater than the version stated in this field.+-- Starting from the specification version 2.2, the cabal-version field must be+-- the first thing in the cabal file.++-- Initial package description 'cmark-gfm-lens' generated by+-- 'cabal init'. For further documentation, see:+--   http://haskell.org/cabal/users-guide/+--+-- The name of the package.+name:               cmark-gfm-lens++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary:     +-+------- breaking API changes+--                  | | +----- non-breaking API additions+--                  | | | +--- code changes with no API change+version:            0.2.0.0++-- A short (one-line) description of the package.+synopsis:           Collection of Lens for cmark-gfm with minimal dependencies++-- A longer description of the package.+description:        Unofficial collection of Lens for cmark-gfm with minimal dependencies++-- URL for the project homepage or repository.+homepage:           https://github.com/ingun37/cmark-gfm-lens++-- The license under which the package is released.+license:            BSD-3-Clause++-- The file containing the license text.+license-file:       LICENSE++-- The package author(s).+author:             Ingun Jon++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer:         ingun37@gmail.com++-- A copyright notice.+-- copyright:+category:           Control+build-type:         Simple++-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README.+extra-doc-files:    CHANGELOG.md++-- Extra source files to be distributed with the package, such as examples, or a tutorial module.+-- extra-source-files:++source-repository this+    type:     git+    location: https://github.com/ingun37/cmark-gfm-lens.git+    tag:      7fdb8db41b3a6fce79734f305e59bfb51d26df88++source-repository head+    type:     git+    location: https://github.com/ingun37/cmark-gfm-lens.git++common warnings+    ghc-options: -Wall++library+    -- Import common warning flags.+    import:           warnings++    -- Modules exported by the library.+    exposed-modules:  CMarkGFM.Lens++    -- Modules included in this library but not exported.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- Other library packages from which modules are imported.+    build-depends:+        base ^>=4.21.0.0,+        cmark-gfm >= 0.2.6 && < 0.3,+        text ^>=2.1.2,+        profunctors ^>=5.6.3++    -- Directories containing source files.+    hs-source-dirs:   src++    -- Base language which the package is written in.+    default-language: GHC2024++test-suite cmark-gfm-lens-test+    -- Import common warning flags.+    import:           warnings++    -- Base language which the package is written in.+    default-language: GHC2024++    -- Modules included in this executable, other than Main.+    -- other-modules:++    -- LANGUAGE extensions used by modules in this package.+    -- other-extensions:++    -- The interface type and version of the test suite.+    type:             exitcode-stdio-1.0++    -- Directories containing source files.+    hs-source-dirs:   test++    -- The entrypoint to the test suite.+    main-is:          Main.hs++    -- Test dependencies.+    build-depends:+        base ^>=4.21.0.0,+        cmark-gfm-lens,+        lens,+        cmark-gfm,+        text,+        hspec
+ src/CMarkGFM/Lens.hs view
@@ -0,0 +1,195 @@+module CMarkGFM.Lens+  ( _posInfo,+    _nodeType,+    _nodes,+    _nodesLens,+    _HEADING,+    _PARAGRAPH,+    _TEXT,+    _DOCUMENT,+    _THEMATIC_BREAK,+    _BLOCK_QUOTE,+    _ITEM,+    _SOFTBREAK,+    _LINEBREAK,+    _EMPH,+    _STRONG,+    _HTML_BLOCK,+    _HTML_INLINE,+    _CODE,+    _LIST,+    _CUSTOM_BLOCK,+    _CUSTOM_INLINE,+    _CODE_BLOCK,+    _LINK,+    _IMAGE,+  )+where++import CMarkGFM+import Data.Profunctor+import Data.Text qualified as T++_posInfo :: (Functor f) => (Maybe PosInfo -> f (Maybe PosInfo)) -> Node -> f Node+_posInfo inj (Node pi a b) =+  let set x = Node x a b+   in set <$> inj pi+{-# INLINE _posInfo #-}++_nodeType :: (Functor f) => (NodeType -> f NodeType) -> Node -> f Node+_nodeType inj (Node a nt b) =+  let set x = Node a x b+   in set <$> inj nt+{-# INLINE _nodeType #-}++-- | Traversal' for the child Nodes of a Node. For the Lens' use `_nodesLens`+_nodes :: (Applicative f) => (Node -> f Node) -> Node -> f Node+_nodes inj (Node a b nodes) = Node a b <$> traverse inj nodes+{-# INLINE _nodes #-}++-- | Lens' for the child Nodes of a Node. For the Traversal' use `_nodes`+_nodesLens :: (Functor f) => ([Node] -> f [Node]) -> Node -> f Node+_nodesLens inj (Node a b nodes) = Node a b <$> inj nodes+{-# INLINE _nodesLens #-}++prism0 :: (Choice p, Applicative f) => NodeType -> p () (f ()) -> p NodeType (f NodeType)+prism0 c = dimap to fro . right'+  where+    to x = if x == c then Right () else Left x+    fro (Left it) = pure it+    fro (Right fa) = c <$ fa++_DOCUMENT :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_DOCUMENT = prism0 DOCUMENT+{-# INLINE _DOCUMENT #-}++_THEMATIC_BREAK :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_THEMATIC_BREAK = prism0 THEMATIC_BREAK+{-# INLINE _THEMATIC_BREAK #-}++_PARAGRAPH :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_PARAGRAPH = prism0 PARAGRAPH+{-# INLINE _PARAGRAPH #-}++_BLOCK_QUOTE :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_BLOCK_QUOTE = prism0 BLOCK_QUOTE+{-# INLINE _BLOCK_QUOTE #-}++_ITEM :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_ITEM = prism0 ITEM+{-# INLINE _ITEM #-}++_SOFTBREAK :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_SOFTBREAK = prism0 SOFTBREAK+{-# INLINE _SOFTBREAK #-}++_LINEBREAK :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_LINEBREAK = prism0 LINEBREAK+{-# INLINE _LINEBREAK #-}++_EMPH :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_EMPH = prism0 EMPH+{-# INLINE _EMPH #-}++_STRONG :: (Choice p, Applicative f) => p () (f ()) -> p NodeType (f NodeType)+_STRONG = prism0 STRONG+{-# INLINE _STRONG #-}++_HTML_BLOCK :: (Choice p, Applicative f) => p T.Text (f T.Text) -> p NodeType (f NodeType)+_HTML_BLOCK = dimap to fro . right'+  where+    to (HTML_BLOCK a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = HTML_BLOCK <$> fa+{-# INLINE _HTML_BLOCK #-}++_TEXT :: (Choice p, Applicative f) => p T.Text (f T.Text) -> p NodeType (f NodeType)+_TEXT = dimap to fro . right'+  where+    to (TEXT a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = TEXT <$> fa+{-# INLINE _TEXT #-}++_HTML_INLINE :: (Choice p, Applicative f) => p T.Text (f T.Text) -> p NodeType (f NodeType)+_HTML_INLINE = dimap to fro . right'+  where+    to (HTML_INLINE a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = HTML_INLINE <$> fa+{-# INLINE _HTML_INLINE #-}++_CODE :: (Choice p, Applicative f) => p T.Text (f T.Text) -> p NodeType (f NodeType)+_CODE = dimap to fro . right'+  where+    to (CODE a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = CODE <$> fa+{-# INLINE _CODE #-}++_HEADING :: (Choice p, Applicative f) => p Level (f Level) -> p NodeType (f NodeType)+_HEADING = dimap to fro . right'+  where+    to (HEADING a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = HEADING <$> fa+{-# INLINE _HEADING #-}++_LIST :: (Choice p, Applicative f) => p ListAttributes (f ListAttributes) -> p NodeType (f NodeType)+_LIST = dimap to fro . right'+  where+    to (LIST a) = Right a+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = LIST <$> fa+{-# INLINE _LIST #-}++_CUSTOM_BLOCK :: (Choice p, Applicative f) => p (T.Text, T.Text) (f (T.Text, T.Text)) -> p NodeType (f NodeType)+_CUSTOM_BLOCK = dimap to fro . right'+  where+    to (CUSTOM_BLOCK a b) = Right (a, b)+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = uncurry CUSTOM_BLOCK <$> fa+{-# INLINE _CUSTOM_BLOCK #-}++_CUSTOM_INLINE :: (Choice p, Applicative f) => p (T.Text, T.Text) (f (T.Text, T.Text)) -> p NodeType (f NodeType)+_CUSTOM_INLINE = dimap to fro . right'+  where+    to (CUSTOM_INLINE a b) = Right (a, b)+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = uncurry CUSTOM_INLINE <$> fa+{-# INLINE _CUSTOM_INLINE #-}++_CODE_BLOCK :: (Choice p, Applicative f) => p (Info, T.Text) (f (Info, T.Text)) -> p NodeType (f NodeType)+_CODE_BLOCK = dimap to fro . right'+  where+    to (CODE_BLOCK a b) = Right (a, b)+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = uncurry CODE_BLOCK <$> fa+{-# INLINE _CODE_BLOCK #-}++_LINK :: (Choice p, Applicative f) => p (Url, Title) (f (Url, Title)) -> p NodeType (f NodeType)+_LINK = dimap to fro . right'+  where+    to (LINK a b) = Right (a, b)+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = uncurry LINK <$> fa+{-# INLINE _LINK #-}++_IMAGE :: (Choice p, Applicative f) => p (Url, Title) (f (Url, Title)) -> p NodeType (f NodeType)+_IMAGE = dimap to fro . right'+  where+    to (IMAGE a b) = Right (a, b)+    to x = Left x+    fro (Left it) = pure it+    fro (Right fa) = uncurry IMAGE <$> fa+{-# INLINE _IMAGE #-}
+ test/Main.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE OverloadedStrings #-}++module Main (main) where++import CMarkGFM+import CMarkGFM.Lens+import Control.Lens+import Data.Text.IO qualified as TIO+import Test.Hspec++main :: IO ()+main = do+  content <- TIO.readFile "test/test.md"+  let node = commonmarkToNode [] [] content+  hspec $ do+    describe "Prelude.head" $ do+      it "returns the first element of a list" $ do+        node ^. _nodeType `shouldBe` DOCUMENT+        let nodes1 = node ^.. _nodes+        let nodes2 = node ^. _nodesLens+        let invalidText = node ^. _nodeType . _TEXT+        invalidText `shouldBe` ""+        nodes1 `shouldBe` nodes2+        let headingLevel = (node ^.. _nodes) ^? ix 0 . _nodeType . _HEADING+        headingLevel `shouldBe` Just 1+        let paragraph = node ^? _nodesLens . ix 1 . _nodesLens . ix 0 . _nodeType . _TEXT+        paragraph `shouldBe` Just "paragraph 1"+        let node' = over (_nodes . _nodes . _nodeType . _TEXT) (<> "?") node+        let paragraph' = node' ^? _nodesLens . ix 1 . _nodesLens . ix 0 . _nodeType . _TEXT+        paragraph' `shouldBe` Just "paragraph 1?"+        let node'' = set (_nodes . _nodes . _nodeType . _TEXT) "" node+        let paragraph'' = node'' ^? _nodesLens . ix 1 . _nodesLens . ix 0 . _nodeType . _TEXT+        paragraph'' `shouldBe` Just ""