Working prototype with few tags
Getty Ritter
9 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: |