packages feed

commonmark-extensions 0.2.4 → 0.2.5

raw patch · 7 files changed

+248/−8 lines, 7 filesdep ~commonmarkPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: commonmark

API changes (from Hackage documentation)

+ Commonmark.Extensions.Alerts: CautionAlert :: AlertType
+ Commonmark.Extensions.Alerts: ImportantAlert :: AlertType
+ Commonmark.Extensions.Alerts: NoteAlert :: AlertType
+ Commonmark.Extensions.Alerts: TipAlert :: AlertType
+ Commonmark.Extensions.Alerts: WarningAlert :: AlertType
+ Commonmark.Extensions.Alerts: alert :: HasAlerts il bl => AlertType -> bl -> bl
+ Commonmark.Extensions.Alerts: alertClass :: AlertType -> Text
+ Commonmark.Extensions.Alerts: alertName :: AlertType -> Text
+ Commonmark.Extensions.Alerts: alertSpec :: (Monad m, Typeable m, IsBlock il bl, IsInline il, Typeable il, Typeable bl, HasAlerts il bl) => SyntaxSpec m il bl
+ Commonmark.Extensions.Alerts: alertSvgText :: AlertType -> Text
+ Commonmark.Extensions.Alerts: class IsBlock il bl => HasAlerts il bl | il -> bl
+ Commonmark.Extensions.Alerts: data AlertType
+ Commonmark.Extensions.Alerts: instance (Commonmark.Extensions.Alerts.HasAlerts il bl, GHC.Base.Semigroup bl, GHC.Base.Semigroup il) => Commonmark.Extensions.Alerts.HasAlerts (Commonmark.SourceMap.WithSourceMap il) (Commonmark.SourceMap.WithSourceMap bl)
+ Commonmark.Extensions.Alerts: instance Commonmark.Types.Rangeable (Commonmark.Html.Html a) => Commonmark.Extensions.Alerts.HasAlerts (Commonmark.Html.Html a) (Commonmark.Html.Html a)
+ Commonmark.Extensions.Alerts: instance GHC.Classes.Eq Commonmark.Extensions.Alerts.AlertType
+ Commonmark.Extensions.Alerts: instance GHC.Classes.Ord Commonmark.Extensions.Alerts.AlertType
+ Commonmark.Extensions.Alerts: instance GHC.Show.Show Commonmark.Extensions.Alerts.AlertType
- Commonmark.Extensions: gfmExtensions :: (Monad m, Typeable m, Typeable il, Typeable bl, IsBlock il bl, IsInline il, HasFootnote il bl, HasEmoji il, HasStrikethrough il, HasPipeTable il bl, HasTaskList il bl, ToPlainText il) => SyntaxSpec m il bl
+ Commonmark.Extensions: gfmExtensions :: (Monad m, Typeable m, Typeable il, Typeable bl, IsBlock il bl, IsInline il, HasFootnote il bl, HasEmoji il, HasStrikethrough il, HasPipeTable il bl, HasTaskList il bl, ToPlainText il, HasAlerts il bl) => SyntaxSpec m il bl

Files

changelog.md view
@@ -1,5 +1,16 @@ # Changelog for commonmark-extensions +## 0.2.5++  * Add support for alerts extension, supporting GitHub-style alerts (#132).+    <https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts>+    New module Commonmark.Extensions.Alerts [API change].++  * Do not accept footnote labels with line breaks (Michael Howell).++  * Parse `[^ ]` and `[^]` as links (Michael Howell). This is consistent with+    most other CommonMark parsers, even when they have support for footnotes turned on.+ ## 0.2.4    * Make `pipe_tables` extension treat backslash escapes like GH does (#112,
commonmark-extensions.cabal view
@@ -1,5 +1,5 @@ name:           commonmark-extensions-version:        0.2.4+version:        0.2.5 synopsis:       Pure Haskell commonmark parser. description:    This library provides some useful extensions to core commonmark@@ -59,7 +59,7 @@     , transformers     , filepath     , network-uri-    , commonmark >= 0.2.2 && < 0.3+    , commonmark >= 0.2.4.1 && < 0.3     -- for extensions:     , emojis >= 0.1 && < 0.2   exposed-modules:@@ -82,6 +82,7 @@       Commonmark.Extensions.ImplicitHeadingReferences       Commonmark.Extensions.RebaseRelativePaths       Commonmark.Extensions.Wikilinks+      Commonmark.Extensions.Alerts   ghc-options: -Wall -fno-warn-unused-do-bind -funbox-small-strict-fields   if impl(ghc >= 8.10)     ghc-options:      -Wunused-packages@@ -99,7 +100,7 @@   ghc-options: -threaded -rtsopts -with-rtsopts=-K40K   build-depends:       base >= 4.9 && <5-    , commonmark >= 0.2 && < 0.3+    , commonmark >= 0.2.4.1 && < 0.3     , commonmark-extensions     , text     , tasty@@ -112,7 +113,7 @@   main-is:         benchmark.hs   hs-source-dirs:  benchmark   build-depends:-       commonmark >= 0.2 && < 0.3+       commonmark >= 0.2.4.1 && < 0.3      , commonmark-extensions      , base >= 4.9 && < 5      , text
src/Commonmark/Extensions.hs view
@@ -39,6 +39,7 @@     , module Commonmark.Extensions.TaskList     , module Commonmark.Extensions.ImplicitHeadingReferences     , module Commonmark.Extensions.Wikilinks+    , module Commonmark.Extensions.Alerts     , module Commonmark.Extensions.RebaseRelativePaths     , gfmExtensions     ) where@@ -60,6 +61,7 @@ import           Commonmark.Extensions.TaskList import           Commonmark.Extensions.ImplicitHeadingReferences import           Commonmark.Extensions.Wikilinks+import           Commonmark.Extensions.Alerts import           Commonmark.Extensions.RebaseRelativePaths import           Commonmark import           Data.Typeable@@ -68,9 +70,9 @@ gfmExtensions :: (Monad m, Typeable m, Typeable il, Typeable bl,                   IsBlock il bl, IsInline il, HasFootnote il bl,                   HasEmoji il, HasStrikethrough il, HasPipeTable il bl,-                  HasTaskList il bl, ToPlainText il)+                  HasTaskList il bl, ToPlainText il, HasAlerts il bl)               => SyntaxSpec m il bl gfmExtensions =   emojiSpec <> strikethroughSpec <> pipeTableSpec <> autolinkSpec <>-    autoIdentifiersSpec <> taskListSpec <> footnoteSpec+    autoIdentifiersSpec <> taskListSpec <> footnoteSpec <> alertSpec 
+ src/Commonmark/Extensions/Alerts.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+module Commonmark.Extensions.Alerts+  ( alertSpec+  , alertSvgText+  , alertClass+  , alertName+  , AlertType(..)+  , HasAlerts(..)+  )+where+import Commonmark.Types+import Commonmark.Syntax+import Commonmark.Blocks+import Commonmark.SourceMap+import Commonmark.TokParsers+import Commonmark.Tokens+import Commonmark.Html+import Control.Monad (void)+import Data.Dynamic+import Data.Tree+import Text.Parsec+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL++alertSpec :: (Monad m, Typeable m, IsBlock il bl, IsInline il,+                 Typeable il, Typeable bl, HasAlerts il bl)+             => SyntaxSpec m il bl+alertSpec = mempty+  { syntaxBlockSpecs = [alertBlockSpec]+  }+++alertBlockSpec :: (Monad m, IsBlock il bl, HasAlerts il bl)+               => BlockSpec m il bl+alertBlockSpec = BlockSpec+     { blockType           = "Alert"+     , blockStart          = do+             nonindentSpaces+             pos <- getPosition+             _ <- symbol '>'+             _ <- option 0 (gobbleSpaces 1)+             _ <- symbol '['+             _ <- symbol '!'+             let eqCI x y = x == T.toUpper y+             alertType <- (NoteAlert <$ satisfyWord (eqCI "NOTE"))+                      <|> (TipAlert <$ satisfyWord (eqCI "TIP"))+                      <|> (ImportantAlert <$ satisfyWord (eqCI "IMPORTANT"))+                      <|> (WarningAlert <$ satisfyWord (eqCI "WARNING"))+                      <|> (CautionAlert <$ satisfyWord (eqCI "CAUTION"))+             _ <-  symbol ']'+             skipWhile (hasType Spaces)+             lookAhead $ void lineEnd <|> eof+             addNodeToStack $+                Node (defBlockData alertBlockSpec){+                          blockData = toDyn alertType,+                          blockStartPos = [pos] } []+             return BlockStartMatch+     , blockCanContain     = const True+     , blockContainsLines  = False+     , blockParagraph      = False+     , blockContinue       = \n -> try $ do+             nonindentSpaces+             pos <- getPosition+             _ <- symbol '>'+             _ <- gobbleUpToSpaces 1+             return (pos, n)+     , blockConstructor    = \node -> do+         let alertType = fromDyn (blockData (rootLabel node)) NoteAlert+         alert alertType . mconcat <$> renderChildren node+     , blockFinalize       = defaultFinalizer+     }++data AlertType =+     NoteAlert+   | TipAlert+   | ImportantAlert+   | WarningAlert+   | CautionAlert+  deriving (Show, Typeable, Eq, Ord)++alertClass :: AlertType -> Text+alertClass NoteAlert = "alert-note"+alertClass TipAlert = "alert-tip"+alertClass ImportantAlert = "alert-important"+alertClass WarningAlert = "alert-warning"+alertClass CautionAlert = "alert-caution"++alertName :: AlertType -> Text+alertName NoteAlert = "Note"+alertName TipAlert = "Tip"+alertName ImportantAlert = "Important"+alertName WarningAlert = "Warning"+alertName CautionAlert = "Caution"++alertSvg :: AlertType -> Html a+alertSvg alertType =+  addAttribute ("viewBox", "0 0 16 16") $+  addAttribute ("width", "16") $+  addAttribute ("height", "16") $+  addAttribute ("aria-hidden", "true") $+  htmlBlock "svg" $+    Just $ htmlRaw "\n" <>+      addAttribute ("d", svgPath alertType)+        (htmlBlock "path" (Just mempty))++alertSvgText :: AlertType -> Text+alertSvgText = TL.toStrict . renderHtml . alertSvg++svgPath :: AlertType -> Text+svgPath NoteAlert = "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"+svgPath TipAlert = "M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"+svgPath ImportantAlert = "M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"+svgPath WarningAlert = "M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"+svgPath CautionAlert = "M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"++class IsBlock il bl => HasAlerts il bl | il -> bl where+  alert :: AlertType -> bl -> bl++instance Rangeable (Html a) =>+         HasAlerts (Html a) (Html a) where+  alert alertType bs =+    addAttribute ("class", "alert " <> alertClass alertType) $+    htmlBlock "div" (Just $ htmlRaw "\n" <>+      addAttribute ("class", "alert-title")+        (htmlBlock "p" (Just $ htmlRaw "\n" <>+           alertSvg alertType <>+           htmlText (alertName alertType))) <> bs)++instance (HasAlerts il bl, Semigroup bl, Semigroup il)+        => HasAlerts (WithSourceMap il) (WithSourceMap bl) where+  alert alertType bs = alert alertType <$> bs <* addName "alert"
src/Commonmark/Extensions/Footnote.hs view
@@ -101,9 +101,13 @@  pFootnoteLabel :: Monad m => ParsecT [Tok] u m Text pFootnoteLabel = try $ do-  lab <- pLinkLabel+  lab <- untokenize+      <$> try (between (symbol '[') (symbol ']')+            (snd <$> withRaw (many+              (pEscaped <|> noneOfToks [Symbol ']', Symbol '[', LineEnd]))))   case T.uncons lab of-        Just ('^', t') -> return $! t'+        Just ('^', t') | T.any (\x -> x /= ' ' && x /= '\t') t' && T.all (\x -> x /= '\n' && x /= '\r') t'+            -> return $! t'         _ -> mzero  pFootnoteRef :: (Monad m, Typeable m, Typeable a,
test/footnotes.md view
@@ -134,3 +134,87 @@ </div> </section> ````````````````````````````````++Footnote labels cannot be empty, or composed only of whitespace.++```````````````````````````````` example+Test [^] link [^ ]++[^]: https://haskell.org+.+<p>Test <a href="https://haskell.org">^</a> link <a href="https://haskell.org">^ </a></p>+````````````````````````````````++```````````````````````````````` example+[^]: not a footnote++[^ ]: not a footnote++[^+]: not a footnote+.+<p>[^]: not a footnote</p>+<p>[^ ]: not a footnote</p>+<p>[^+]: not a footnote</p>+````````````````````````````````++Footnote labels cannot contain line breaks, even where link labels can.++```````````````````````````````` example+[^foo\+bar]: not a footnote definition++[baz\+quux]: https://haskell.org++[first+second]: https://haskell.org++[^third+fourth]: not a footnote definition++[baz\+quux]+[^foo\+bar]+[first+second]+[^third+fourth]+.+<p>[^foo<br />+bar]: not a footnote definition</p>+<p>[^third+fourth]: not a footnote definition</p>+<p><a href="https://haskell.org">baz<br />+quux</a>+[^foo<br />+bar]+<a href="https://haskell.org">first+second</a>+[^third+fourth]</p>+````````````````````````````````++Paragraphs in footnotes can be lazily wrapped (#126).++```````````````````````````````` example+[^foo]:bar+baz++[^foo]+.+<p><sup class="footnote-ref"><a href="#fn-foo" id="fnref-foo">1</a></sup></p>+<section class="footnotes">+<div class="footnote" id="fn-foo">+<div class="footnote-number">+<a href="#fnref-foo">1</a>+</div>+<div class="footnote-contents">+<p>bar+baz</p>+</div>+</div>+</section>+````````````````````````````````
test/test-commonmark-extensions.hs view
@@ -49,6 +49,7 @@                  autoIdentifiersSpec <> attributesSpec <> implicitHeadingReferencesSpec)              , ("test/wikilinks_title_before_pipe.md", wikilinksSpec TitleBeforePipe)              , ("test/wikilinks_title_after_pipe.md", wikilinksSpec TitleAfterPipe)+             , ("test/alerts.md", alertSpec)              ]   defaultMain $ testGroup "Tests" (tests ++ [rebaseRelativePathTests])