Working prototype with few tags
    
    
      
        Getty Ritter
        10 years ago
      
    
    
  
  
  | 1 | {-# LANGUAGE LambdaCase #-} | |
| 2 | ||
| 3 | module Data.TeLML.Markup where | |
| 4 | ||
| 5 | import Control.Monad (void) | |
| 6 | import Data.TeLML | |
| 7 | import Text.Blaze.Html | |
| 8 | import Text.Blaze.Internal (MarkupM) | |
| 9 | import Text.Blaze.Html5 hiding (map, head, html) | |
| 10 | import Text.Blaze.Html5.Attributes hiding (name) | |
| 11 | ||
| 12 | renderWith :: [(String, Renderer)] -> Document -> Either String Html | |
| 13 | renderWith rs = | |
| 14 | fmap (void . sequence) . mapM (renderPara (basicTags ++ rs)) . gatherPara | |
| 15 | ||
| 16 | render :: Document -> Either String Html | |
| 17 | render = renderWith [] | |
| 18 | ||
| 19 | gatherPara :: Document -> [Document] | |
| 20 | gatherPara = reverse . map reverse . go [[]] | |
| 21 | where go rs [] = rs | |
| 22 | go (r:rs) (t@Tag {}:ts) = go ((t:r):rs) ts | |
| 23 | go (r:rs) (Text s:ts) = case splitString s of | |
| 24 | [] -> go (r:rs) ts | |
| 25 | [x] -> go ((Text x:r):rs) ts | |
| 26 | xs -> go (map ((:[]) . Text) (tail xs) ++ | |
| 27 | ((Text (head xs):r) : rs)) ts | |
| 28 | go _ _ = error "[unreachable]" | |
| 29 | ||
| 30 | splitString :: String -> [String] | |
| 31 | splitString = filter (/= "") . go | |
| 32 | where go ('\n':'\n':xs) = "\n":go xs | |
| 33 | go (x:xs) = let r:rs = go xs in ((x:r):rs) | |
| 34 | go [] = [""] | |
| 35 | ||
| 36 | type HtmlE = Either String Html | |
| 37 | ||
| 38 | type Renderer = (Fragment -> HtmlE, [Document]) -> HtmlE | |
| 39 | ||
| 40 | basicTags :: [(String, Renderer)] | |
| 41 | basicTags = | |
| 42 | [ ("em" | |
| 43 | , \case (f,[rs]) -> fmap (em . sequence_) (mapM f rs) | |
| 44 | _ -> Left "wrong arity for em/1" | |
| 45 | ) | |
| 46 | , ("strong" | |
| 47 | , \case (f,[rs]) -> fmap (strong . sequence_) (mapM f rs) | |
| 48 | _ -> Left "wrong arity for strong/1" | |
| 49 | ) | |
| 50 | , ("link" | |
| 51 | , \case (f,[[Text l],r]) -> let go h = a ! href (stringValue l) $ h | |
| 52 | in fmap (go . sequence_) (mapM f r) | |
| 53 | (_,[_,_]) -> Left "link target should be string" | |
| 54 | _ -> Left "wrong arity for link/1" | |
| 55 | ) | |
| 56 | ] | |
| 57 | ||
| 58 | renderPara :: [(String, Renderer)] -> Document -> Either String Html | |
| 59 | renderPara taglist ds = fmap (p . sequence_) (mapM go ds) | |
| 60 | where go (Text ts) = Right (toMarkup ts) | |
| 61 | go (Tag tx rs) = exec tx rs taglist | |
| 62 | exec name args ((tag, func):tags) | |
| 63 | | name == tag = case func (go, args) of | |
| 64 | Right html -> Right html | |
| 65 | Left {} -> exec name args tags | |
| 66 | exec name args (_:tags) = exec name args tags | |
| 67 | exec name args [] = Left $ | |
| 68 | "Error: no match for tag " ++ name ++ "/" ++ show (length args) | 
| 1 | Copyright (c) 2015, Getty Ritter | |
| 2 | ||
| 3 | All rights reserved. | |
| 4 | ||
| 5 | Redistribution and use in source and binary forms, with or without | |
| 6 | modification, are permitted provided that the following conditions are met: | |
| 7 | ||
| 8 | * Redistributions of source code must retain the above copyright | |
| 9 | notice, this list of conditions and the following disclaimer. | |
| 10 | ||
| 11 | * Redistributions in binary form must reproduce the above | |
| 12 | copyright notice, this list of conditions and the following | |
| 13 | disclaimer in the documentation and/or other materials provided | |
| 14 | with the distribution. | |
| 15 | ||
| 16 | * Neither the name of Getty Ritter nor the names of other | |
| 17 | contributors may be used to endorse or promote products derived | |
| 18 | from this software without specific prior written permission. | |
| 19 | ||
| 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 1 | # telml-markup | |
| 2 | ||
| 3 | TODO: Write description here | |
| 4 | ||
| 5 | ## Installation | |
| 6 | ||
| 7 | TODO: Write installation instructions here | |
| 8 | ||
| 9 | ## Usage | |
| 10 | ||
| 11 | TODO: Write usage instructions here | |
| 12 | ||
| 13 | ## How to run tests | |
| 14 | ||
| 15 | ``` | |
| 16 | cabal configure --enable-tests && cabal build && cabal test | |
| 17 | ``` | |
| 18 | ||
| 19 | ## Contributing | |
| 20 | ||
| 21 | TODO: Write contribution instructions here | 
| 1 | Name: telml-markup | |
| 2 | Version: 0.0.0 | |
| 3 | Author: Getty Ritter <gettylefou@gmail.com> | |
| 4 | Maintainer: Getty Ritter <gettylefou@gmail.com> | |
| 5 | License: BSD3 | |
| 6 | License-File: LICENSE | |
| 7 | -- Synopsis: | |
| 8 | -- Description: | |
| 9 | Cabal-Version: >= 1.10 | |
| 10 | Build-Type: Simple | |
| 11 | Extra-Source-Files: README.md, ChangeLog.md | |
| 12 | ||
| 13 | Library | |
| 14 | Default-Language: Haskell2010 | |
| 15 | GHC-Options: -Wall | |
| 16 | Exposed-Modules: Data.TeLML.Markup | |
| 17 | Build-Depends: base >= 4 && < 5, telml, blaze-markup, blaze-html, mtl | |
| 18 | ||
| 19 | -- Test-Suite spec | |
| 20 | -- Type: exitcode-stdio-1.0 | |
| 21 | -- Default-Language: Haskell2010 | |
| 22 | -- Hs-Source-Dirs: test | |
| 23 | -- Ghc-Options: -Wall | |
| 24 | -- Main-Is: Spec.hs | |
| 25 | -- Build-Depends: base | |
| 26 | -- , hspec | |
| 27 | ||
| 28 | Source-Repository head | |
| 29 | Type: git | |
| 30 | -- Location: |