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 +11/−0
- LICENSE +29/−0
- cmark-gfm-lens.cabal +124/−0
- src/CMarkGFM/Lens.hs +195/−0
- test/Main.hs +33/−0
+ 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 ""