packages feed

reflex-dom-pandoc 0.2.0.0 → 0.4.0.0

raw patch · 9 files changed

+112/−73 lines, 9 filesdep ~skylightingPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: skylighting

API changes (from Hackage documentation)

- Reflex.Dom.Pandoc.Document: [_uriLink_linkText] :: URILink -> Text
- Reflex.Dom.Pandoc.URILink: [_uriLink_linkText] :: URILink -> Text
+ Reflex.Dom.Pandoc.Document: [_uriLink_inner] :: URILink -> Maybe [Inline]
+ Reflex.Dom.Pandoc.URILink: [_uriLink_inner] :: URILink -> Maybe [Inline]
- Reflex.Dom.Pandoc.Document: URILink :: Text -> URI -> URILink
+ Reflex.Dom.Pandoc.Document: URILink :: Maybe [Inline] -> URI -> URILink
- Reflex.Dom.Pandoc.URILink: URILink :: Text -> URI -> URILink
+ Reflex.Dom.Pandoc.URILink: URILink :: Maybe [Inline] -> URI -> URILink

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # Change Log for reflex-dom-pandoc +## 0.4.0.0++- Fix task list checkbox styling margins by using Semantic UI checkbox.+- Add a wrapping div with class "pandoc" for user styling of elements+- Make unicode quote characters less heavy+- Require pure Haskell skylighting+- Remove empty HTML attributes (#6)+- Fancy lists (#7)+- Make `LineBreak` generate `<br>`+- Footnote misalignment on Firefox (#9)+ ## 0.2.0.0  Initial public release
README.md view
@@ -11,4 +11,4 @@  ## Hacking -To develop in reflex-dom-pandoc, follow neuron's README: https://github.com/srid/neuron#developing-on-reflex-dom-pandoc+To develop in reflex-dom-pandoc, follow neuron's README: <https://github.com/srid/neuron/blob/master/CONTRIBUTING.md#hacking-on-pandocs-html-layout>
reflex-dom-pandoc.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2  name:           reflex-dom-pandoc-version:        0.2.0.0+version:        0.4.0.0 synopsis:       Render Pandoc documents to HTML using reflex-dom description:    Please see the README on GitHub at <https://github.com/srid/reflex-dom-pandoc> homepage:       https://github.com/srid/reflex-dom-pandoc#readme@@ -46,7 +46,7 @@     , pandoc-types >= 0.21     , reflex-dom-core     , safe-    , skylighting+    , skylighting >= 0.9     , text     , time     , ref-tf
src/Reflex/Dom/Pandoc/Document.hs view
@@ -28,14 +28,13 @@ import Control.Monad.Reader import Data.Bool import qualified Data.Map as Map-import Data.Maybe-import Data.Traversable (for)+import qualified Data.Text as T import Reflex.Dom.Core hiding (Link, Space, mapAccum) import Reflex.Dom.Pandoc.Footnotes import Reflex.Dom.Pandoc.PandocRaw import Reflex.Dom.Pandoc.SyntaxHighlighting (elCodeHighlighted) import Reflex.Dom.Pandoc.URILink-import Reflex.Dom.Pandoc.Util (elPandocAttr, headerElement, renderAttr)+import Reflex.Dom.Pandoc.Util (elPandocAttr, headerElement, renderAttr, sansEmptyAttrs) import Text.Pandoc.Definition  -- | Like `DomBuilder` but with a capability to render pandoc raw content.@@ -57,9 +56,10 @@ -- | Convert Markdown to HTML elPandoc :: forall t m a. (PandocBuilder t m, Monoid a) => Config t m a -> Pandoc -> m a elPandoc cfg doc@(Pandoc _meta blocks) = do-  let fs = getFootnotes doc-  x <- flip runReaderT fs $ renderBlocks cfg blocks-  fmap (x <>) $ renderFootnotes (sansFootnotes . renderBlocks cfg) fs+  divClass "pandoc" $ do+    let fs = queryFootnotes doc+    x <- flip runReaderT fs $ renderBlocks cfg blocks+    fmap (x <>) $ renderFootnotes (sansFootnotes . renderBlocks cfg) fs  -- | Render list of Pandoc inlines elPandocInlines :: PandocBuilder t m => [Inline] -> m ()@@ -70,8 +70,8 @@ elPandocBlocks = void . sansFootnotes . renderBlocks defaultConfig  mapAccum :: (Monoid b, Applicative f) => (a -> f b) -> [a] -> f b-mapAccum f xs =-  fmap mconcat $ for xs f+mapAccum f =+  fmap mconcat . traverse f  renderBlocks :: (PandocBuilder t m, Monoid a) => Config t m a -> [Block] -> ReaderT Footnotes m a renderBlocks cfg =@@ -97,18 +97,20 @@     elPandocRaw fmt x >> pure mempty   BlockQuote xs ->     el "blockquote" $ renderBlocks cfg xs-  OrderedList _lattr xss ->-    -- TODO: Implement list attributes.-    el "ol" $ do+  OrderedList (idx, style, _delim) xss ->+    -- delimStyle is not supported in HTML or in Semantic UI+    elAttr "ol" (listStyle style <> startFrom idx) $ do       flip mapAccum xss $ \xs -> do         el "li" $ renderBlocks cfg xs   BulletList xss ->     el "ul" $ flip mapAccum xss $ \xs -> el "li" $ renderBlocks cfg xs   DefinitionList defs ->-    el "dl" $ flip mapAccum defs $ \(term, descList) -> do-      x <- el "dt" $ renderInlines cfg term-      fmap (x <>) $ flip mapAccum descList $ \desc ->-        el "dd" $ renderBlocks cfg desc+    el "dl" $+      flip mapAccum defs $ \(term, descList) -> do+        x <- el "dt" $ renderInlines cfg term+        fmap (x <>) $+          flip mapAccum descList $ \desc ->+            el "dd" $ renderBlocks cfg desc   Header level attr xs ->     elPandocAttr (headerElement level) attr $ do       renderInlines cfg xs@@ -122,29 +124,39 @@           el "tr" $ do             flip mapAccum cells $ \(Cell _ _ _ _ blks) ->               el "th" $ renderBlocks cfg blks-      fmap (x <>) $ flip mapAccum tbodys $ \(TableBody _ _ _ rows) ->-        el "tbody" $ do-          flip mapAccum rows $ \(Row _ cells) ->-            el "tr" $ do-              flip mapAccum cells $ \(Cell _ _ _ _ blks) ->-                el "td" $ renderBlocks cfg blks+      fmap (x <>) $+        flip mapAccum tbodys $ \(TableBody _ _ _ rows) ->+          el "tbody" $ do+            flip mapAccum rows $ \(Row _ cells) ->+              el "tr" $ do+                flip mapAccum cells $ \(Cell _ _ _ _ blks) ->+                  el "td" $ renderBlocks cfg blks   Div attr xs ->     elPandocAttr "div" attr $       renderBlocks cfg xs   Null ->     blank >> pure mempty   where-    checkboxEl checked =-      void $-        elAttr-          "input"-          ( mconcat $ catMaybes $-              [ Just $ "type" =: "checkbox",-                Just $ "disabled" =: "True",-                bool Nothing (Just $ "checked" =: "True") checked-              ]-          )-          blank+    checkboxEl checked = do+      let attrs =+            ( mconcat $+                [ "type" =: "checkbox",+                  "disabled" =: "True",+                  bool mempty ("checked" =: "True") checked+                ]+            )+          invisibleChar = "\8206"+      divClass "ui disabled fitted checkbox" $ do+        void $ elAttr "input" attrs blank+        -- Semantic UI requires a non-empty label element+        el "label" $ text invisibleChar+    startFrom idx = bool mempty ("start" =: (T.pack $ show idx)) (idx /= 1)+    listStyle = \case+      LowerRoman -> "type" =: "i"+      UpperRoman -> "type" =: "I"+      LowerAlpha -> "type" =: "a"+      UpperAlpha -> "type" =: "A"+      _ -> mempty  renderInlines :: (PandocBuilder t m, Monoid a) => Config t m a -> [Inline] -> ReaderT Footnotes m a renderInlines cfg =@@ -182,7 +194,7 @@   SoftBreak ->     text " " >> pure mempty   LineBreak ->-    text "\n" >> pure mempty+    el "br" blank >> pure mempty   RawInline fmt x ->     elPandocRaw fmt x >> pure mempty   Math mathType s -> do@@ -195,7 +207,7 @@     pure mempty   inline@(Link attr xs (lUrl, lTitle)) -> do     let defaultRender = do-          let attr' = renderAttr attr <> ("href" =: lUrl <> "title" =: lTitle)+          let attr' = sansEmptyAttrs $ renderAttr attr <> ("href" =: lUrl <> "title" =: lTitle)           elAttr "a" attr' $ renderInlines cfg xs     case uriLinkFromInline inline of       Just uriLink -> do@@ -204,11 +216,11 @@       Nothing ->         defaultRender   Image attr xs (iUrl, iTitle) -> do-    let attr' = renderAttr attr <> ("src" =: iUrl <> "title" =: iTitle)+    let attr' = sansEmptyAttrs $ renderAttr attr <> ("src" =: iUrl <> "title" =: iTitle)     elAttr "img" attr' $ renderInlines cfg xs   Note xs -> do     fs :: Footnotes <- ask-    case Map.lookup (Footnote xs) fs of+    case Map.lookup (mkFootnote xs) fs of       Nothing ->         -- No footnote in the global map (this means that the user has         -- defined a footnote inside a footnote); just put the whole thing in@@ -216,11 +228,10 @@         elClass "aside" "footnote-inline" $ renderBlocks cfg xs       Just idx ->         renderFootnoteRef idx >> pure mempty-  -- el "aside" $ renderBlocks xs   Span attr xs ->     elPandocAttr "span" attr $       renderInlines cfg xs   where     inQuotes w = \case-      SingleQuote -> text "❛" >> w <* text "❜"-      DoubleQuote -> text "❝" >> w <* text "❞"+      SingleQuote -> text "‘" >> w <* text "’"+      DoubleQuote -> text "“" >> w <* text "”"
src/Reflex/Dom/Pandoc/Footnotes.hs view
@@ -7,8 +7,8 @@  import Control.Monad.Reader import Data.List (nub, sortOn)-import qualified Data.Map as Map import Data.Map (Map)+import qualified Data.Map as Map import qualified Data.Text as T import Reflex.Dom.Core hiding (Link, Space) import Text.Pandoc.Definition@@ -19,19 +19,26 @@  type Footnotes = Map Footnote Int -getFootnotes :: Pandoc -> Footnotes-getFootnotes =+-- | Make a footnote from the Pandoc `Note` node's block elements+mkFootnote :: [Block] -> Footnote+mkFootnote blocks =+  Footnote blocks++-- | Traverse the Pandoc document accumulating any footnotes+queryFootnotes :: Pandoc -> Footnotes+queryFootnotes =   buildFootnotes     . query       ( \case-          Note s -> [Footnote s]+          Note xs -> [mkFootnote xs]           _ -> []       )   where     buildFootnotes :: [Footnote] -> Footnotes     buildFootnotes fs =-      Map.fromList $ flip fmap (zip (nub fs) [1 ..]) $ \(fn, idx) ->-        (fn, idx)+      Map.fromList $+        flip fmap (zip (nub fs) [1 ..]) $ \(fn, idx) ->+          (fn, idx)  renderFootnotes :: (DomBuilder t m, Monoid a) => ([Block] -> m a) -> Footnotes -> m a renderFootnotes render footnotes = do@@ -39,19 +46,19 @@     then pure mempty     else do       elAttr "div" ("id" =: "footnotes") $ do-        el "ol" $ fmap mconcat $ forM (sortOn snd $ Map.toList footnotes) $ \(Footnote blks, idx) -> do-          el "li" $ do-            -- We discard any footnotes inside footnotes-            elAttr "a" ("name" =: ("fn" <> T.pack (show idx))) blank-            x <- render blks-            -- FIXME: This should appear inline if the footnote is a single paragraph.-            elAttr "a" ("href" =: ("#fnref" <> T.pack (show idx))) $ text "↩︎"-            pure x+        el "ol" $+          fmap mconcat $+            forM (sortOn snd $ Map.toList footnotes) $ \(Footnote blks, idx) -> do+              elAttr "li" ("id" =: ("fn" <> T.pack (show idx))) $ do+                x <- render blks+                -- FIXME: This should appear inline if the footnote is a single paragraph.+                elAttr "a" ("href" =: ("#fnref" <> T.pack (show idx))) $ text "↩︎"+                pure x  renderFootnoteRef :: DomBuilder t m => Int -> m () renderFootnoteRef idx = do   elClass "sup" "footnote-ref" $ do-    elAttr "a" ("name" =: ("fnref" <> T.pack (show idx)) <> "href" =: ("#fn" <> T.pack (show idx))) $ do+    elAttr "a" ("id" =: ("fnref" <> T.pack (show idx)) <> "href" =: ("#fn" <> T.pack (show idx))) $ do       text $ T.pack $ show idx  sansFootnotes :: DomBuilder t m => ReaderT Footnotes m a -> m a
src/Reflex/Dom/Pandoc/PandocRaw.hs view
@@ -67,5 +67,6 @@  instance PandocRaw m => PandocRaw (PostBuildT t m) where   type PandocRawConstraints (PostBuildT t m) = PandocRawConstraints m-  elPandocRaw f s = PostBuildT $ ReaderT $ \_ ->-    elPandocRaw f s+  elPandocRaw f s = PostBuildT $+    ReaderT $ \_ ->+      elPandocRaw f s
src/Reflex/Dom/Pandoc/SyntaxHighlighting.hs view
@@ -24,15 +24,17 @@   case tokenizeForOneOfLang langClasses x of     Nothing -> do       divClass "pandoc-code nosyntax" $ do-        el "pre" $ elPandocAttr "code" attr $-          text x+        el "pre" $+          elPandocAttr "code" attr $+            text x     Just lines ->       divClass "pandoc-code highlighted" $ do-        el "pre" $ elPandocAttr "code" attr $ do-          forM_ lines $ \line -> do-            forM_ line $ \(tokType, tok) ->-              elClass "span" (tokenClass tokType) $ text tok-            text "\n"+        el "pre" $+          elPandocAttr "code" attr $ do+            forM_ lines $ \line -> do+              forM_ line $ \(tokType, tok) ->+                elClass "span" (tokenClass tokType) $ text tok+              text "\n"   where     tokenizeForOneOfLang langs s = do       syntax <- msum (fmap (`S.lookupSyntax` S.defaultSyntaxMap) langs)
src/Reflex/Dom/Pandoc/URILink.hs view
@@ -3,24 +3,28 @@  module Reflex.Dom.Pandoc.URILink where +import Control.Monad (guard) import Data.Maybe-import Data.Text (Text) import Text.Pandoc.Definition import qualified Text.Pandoc.Walk as W import Text.URI (URI, mkURI) --- | A Pandoc Link node with a valid URI and a simple (unformatted) link text.+-- | A Pandoc Link node with a valid URI data URILink = URILink-  { _uriLink_linkText :: Text,+  { -- | This is set to Nothing for autolinks+    _uriLink_inner :: Maybe [Inline],     _uriLink_uri :: URI   }   deriving (Eq, Show, Ord)  uriLinkFromInline :: Inline -> Maybe URILink uriLinkFromInline = \case-  Link _attr [Str linkText] (url, _title) -> do+  Link _attr inlines (url, _title) -> do     uri <- mkURI url-    pure $ URILink linkText uri+    let inner = do+          guard $ inlines /= [Str url]+          pure inlines+    pure $ URILink inner uri   _ ->     Nothing 
src/Reflex/Dom/Pandoc/Util.hs view
@@ -18,15 +18,18 @@   -- | Child widget   m a ->   m a-elPandocAttr name = elAttr name . renderAttr+elPandocAttr name = elAttr name . sansEmptyAttrs . renderAttr +sansEmptyAttrs :: Map k Text -> Map k Text+sansEmptyAttrs = Map.filter (not . T.null)+ renderAttr ::   -- | Pandoc attribute object. TODO: Use a sensible type.   Attr ->   Map Text Text renderAttr (identifier, classes, attrs) =   "id" =: identifier-    <> "class" =: (T.unwords classes)+    <> "class" =: T.unwords classes     <> Map.fromList attrs  addClass ::