summaryrefslogtreecommitdiff
path: root/src/Hakyll/Web
diff options
context:
space:
mode:
authorJasper Van der Jeugt <m@jaspervdj.be>2012-11-18 21:56:52 +0100
committerJasper Van der Jeugt <m@jaspervdj.be>2012-11-18 21:56:52 +0100
commit877cb21d1630d32c6e40eb7c6f0ecc7e1da2bd52 (patch)
tree57ce11325adbbb7502086450dd1d1a9f1e81b8f2 /src/Hakyll/Web
parent1347b0fa6cdd98986f927368e76e849068f69e1a (diff)
downloadhakyll-877cb21d1630d32c6e40eb7c6f0ecc7e1da2bd52.tar.gz
Add Item abstraction
Diffstat (limited to 'src/Hakyll/Web')
-rw-r--r--src/Hakyll/Web/CompressCss.hs5
-rw-r--r--src/Hakyll/Web/Page.hs25
-rw-r--r--src/Hakyll/Web/Page/Internal.hs8
-rw-r--r--src/Hakyll/Web/Pandoc.hs87
-rw-r--r--src/Hakyll/Web/Pandoc/Biblio.hs57
-rw-r--r--src/Hakyll/Web/Pandoc/FileType.hs9
-rw-r--r--src/Hakyll/Web/Template.hs56
-rw-r--r--src/Hakyll/Web/Template/Context.hs39
-rw-r--r--src/Hakyll/Web/Urls/Relativize.hs24
9 files changed, 142 insertions, 168 deletions
diff --git a/src/Hakyll/Web/CompressCss.hs b/src/Hakyll/Web/CompressCss.hs
index 133c7f0..f3290f3 100644
--- a/src/Hakyll/Web/CompressCss.hs
+++ b/src/Hakyll/Web/CompressCss.hs
@@ -15,13 +15,14 @@ import Data.List (isPrefixOf)
--------------------------------------------------------------------------------
import Hakyll.Core.Compiler
+import Hakyll.Core.Item
import Hakyll.Core.Util.String
--------------------------------------------------------------------------------
-- | Compiler form of 'compressCss'
-compressCssCompiler :: Compiler String
-compressCssCompiler = compressCss <$> getResourceString
+compressCssCompiler :: Compiler (Item String)
+compressCssCompiler = fmap compressCss <$> getResourceString
--------------------------------------------------------------------------------
diff --git a/src/Hakyll/Web/Page.hs b/src/Hakyll/Web/Page.hs
index ca98042..f58f948 100644
--- a/src/Hakyll/Web/Page.hs
+++ b/src/Hakyll/Web/Page.hs
@@ -49,34 +49,26 @@
-- contains three metadata fields and a body. The body is given in markdown
-- format, which can be easily rendered to HTML by Hakyll, using pandoc.
module Hakyll.Web.Page
- ( Page
- , readPageCompiler
- , pageCompiler
+ ( pageCompiler
, pageCompilerWith
, pageCompilerWithPandoc
) where
--------------------------------------------------------------------------------
-import Text.Pandoc (Pandoc, ParserState, WriterOptions)
+import Control.Applicative ((<$>))
+import Text.Pandoc (Pandoc, ParserState, WriterOptions)
--------------------------------------------------------------------------------
import Hakyll.Core.Compiler
-import Hakyll.Web.Page.Internal
+import Hakyll.Core.Item
import Hakyll.Web.Pandoc
--------------------------------------------------------------------------------
--- | Read a page (do not render it)
-readPageCompiler :: Compiler Page
-readPageCompiler = getResourceBody
-{-# DEPRECATED readPageCompiler "Use getResourceBody" #-}
-
-
---------------------------------------------------------------------------------
-- | Read a page render using pandoc
-pageCompiler :: Compiler Page
+pageCompiler :: Compiler (Item String)
pageCompiler =
pageCompilerWith defaultHakyllParserState defaultHakyllWriterOptions
@@ -84,7 +76,7 @@ pageCompiler =
--------------------------------------------------------------------------------
-- | A version of 'pageCompiler' which allows you to specify your own pandoc
-- options
-pageCompilerWith :: ParserState -> WriterOptions -> Compiler Page
+pageCompilerWith :: ParserState -> WriterOptions -> Compiler (Item String)
pageCompilerWith state options = pageCompilerWithPandoc state options id
@@ -93,9 +85,8 @@ pageCompilerWith state options = pageCompilerWithPandoc state options id
-- pandoc transformation for the content
pageCompilerWithPandoc :: ParserState -> WriterOptions
-> (Pandoc -> Pandoc)
- -> Compiler Page
+ -> Compiler (Item String)
pageCompilerWithPandoc state options f = cached cacheName $
- readPageCompiler >>= pageReadPandocWith state >>=
- return . writePandocWith options . f
+ writePandocWith options . fmap f . readPandocWith state <$> getResourceBody
where
cacheName = "Hakyll.Web.Page.pageCompilerWithPandoc"
diff --git a/src/Hakyll/Web/Page/Internal.hs b/src/Hakyll/Web/Page/Internal.hs
deleted file mode 100644
index 04cf08a..0000000
--- a/src/Hakyll/Web/Page/Internal.hs
+++ /dev/null
@@ -1,8 +0,0 @@
---------------------------------------------------------------------------------
-module Hakyll.Web.Page.Internal
- ( Page
- ) where
-
-
---------------------------------------------------------------------------------
-type Page = String
diff --git a/src/Hakyll/Web/Pandoc.hs b/src/Hakyll/Web/Pandoc.hs
index caada26..c2319dc 100644
--- a/src/Hakyll/Web/Pandoc.hs
+++ b/src/Hakyll/Web/Pandoc.hs
@@ -6,12 +6,8 @@ module Hakyll.Web.Pandoc
, readPandocWith
, writePandoc
, writePandocWith
-
- -- * Functions working on pages/compilers
- , pageReadPandoc
- , pageReadPandocWith
- , pageRenderPandoc
- , pageRenderPandocWith
+ , renderPandoc
+ , renderPandocWith
-- * Default options
, defaultHakyllParserState
@@ -20,89 +16,66 @@ module Hakyll.Web.Pandoc
--------------------------------------------------------------------------------
-import Control.Applicative ((<$>))
-import Data.Maybe (fromMaybe)
import Text.Pandoc
--------------------------------------------------------------------------------
-import Hakyll.Core.Compiler
-import Hakyll.Core.Identifier
-import Hakyll.Web.Page.Internal
+import Hakyll.Core.Item
import Hakyll.Web.Pandoc.FileType
--------------------------------------------------------------------------------
-- | Read a string using pandoc, with the default options
-readPandoc :: FileType -- ^ Determines how parsing happens
- -> Maybe Identifier -- ^ Optional, for better error messages
- -> Page -- ^ String to read
- -> Pandoc -- ^ Resulting document
+readPandoc :: Item String -- ^ String to read
+ -> Item Pandoc -- ^ Resulting document
readPandoc = readPandocWith defaultHakyllParserState
--------------------------------------------------------------------------------
-- | Read a string using pandoc, with the supplied options
-readPandocWith :: ParserState -- ^ Parser options
- -> FileType -- ^ Determines parsing method
- -> Maybe Identifier -- ^ Optional, for better error messages
- -> Page -- ^ String to read
- -> Pandoc -- ^ Resulting document
-readPandocWith state fileType' id' = case fileType' of
- Html -> readHtml state
- LaTeX -> readLaTeX state
- LiterateHaskell t ->
- readPandocWith state {stateLiterateHaskell = True} t id'
- Markdown -> readMarkdown state
- Rst -> readRST state
- Textile -> readTextile state
- t -> error $
- "Hakyll.Web.readPandocWith: I don't know how to read a file of the " ++
- "type " ++ show t ++ fromMaybe "" (fmap ((" for: " ++) . show) id')
+readPandocWith :: ParserState -- ^ Parser options
+ -> Item String -- ^ String to read
+ -> Item Pandoc -- ^ Resulting document
+readPandocWith state item = fmap (reader state (itemFileType item)) item
+ where
+ reader s t = case t of
+ Html -> readHtml s
+ LaTeX -> readLaTeX s
+ LiterateHaskell t' -> reader s {stateLiterateHaskell = True} t'
+ Markdown -> readMarkdown s
+ Rst -> readRST s
+ Textile -> readTextile s
+ _ -> error $
+ "Hakyll.Web.readPandocWith: I don't know how to read a file of the " ++
+ "type " ++ show t ++ " for: " ++ show (itemIdentifier item)
--------------------------------------------------------------------------------
-- | Write a document (as HTML) using pandoc, with the default options
-writePandoc :: Pandoc -- ^ Document to write
- -> Page -- ^ Resulting HTML
+writePandoc :: Item Pandoc -- ^ Document to write
+ -> Item String -- ^ Resulting HTML
writePandoc = writePandocWith defaultHakyllWriterOptions
--------------------------------------------------------------------------------
-- | Write a document (as HTML) using pandoc, with the supplied options
writePandocWith :: WriterOptions -- ^ Writer options for pandoc
- -> Pandoc -- ^ Document to write
- -> Page -- ^ Resulting HTML
-writePandocWith = writeHtmlString
-
-
---------------------------------------------------------------------------------
--- | Read the resource using pandoc
-pageReadPandoc :: Page -> Compiler Pandoc
-pageReadPandoc = pageReadPandocWith defaultHakyllParserState
-
-
---------------------------------------------------------------------------------
--- | Read the resource using pandoc
-pageReadPandocWith :: ParserState -> Page -> Compiler Pandoc
-pageReadPandocWith state page = do
- identifier <- getIdentifier
- fileType' <- getFileType
- return $ readPandocWith state fileType' (Just identifier) page
+ -> Item Pandoc -- ^ Document to write
+ -> Item String -- ^ Resulting HTML
+writePandocWith options = fmap $ writeHtmlString options
--------------------------------------------------------------------------------
-- | Render the resource using pandoc
-pageRenderPandoc :: Page -> Compiler Page
-pageRenderPandoc =
- pageRenderPandocWith defaultHakyllParserState defaultHakyllWriterOptions
+renderPandoc :: Item String -> Item String
+renderPandoc =
+ renderPandocWith defaultHakyllParserState defaultHakyllWriterOptions
--------------------------------------------------------------------------------
-- | Render the resource using pandoc
-pageRenderPandocWith :: ParserState -> WriterOptions -> Page -> Compiler Page
-pageRenderPandocWith state options page =
- writePandocWith options <$> pageReadPandocWith state page
+renderPandocWith :: ParserState -> WriterOptions -> Item String -> Item String
+renderPandocWith state options = writePandocWith options . readPandocWith state
--------------------------------------------------------------------------------
diff --git a/src/Hakyll/Web/Pandoc/Biblio.hs b/src/Hakyll/Web/Pandoc/Biblio.hs
index ca8d10e..8c284a0 100644
--- a/src/Hakyll/Web/Pandoc/Biblio.hs
+++ b/src/Hakyll/Web/Pandoc/Biblio.hs
@@ -15,7 +15,7 @@ module Hakyll.Web.Pandoc.Biblio
, cslCompiler
, Biblio (..)
, biblioCompiler
- , pageReadPandocBiblio
+ , readPandocBiblio
) where
@@ -31,19 +31,31 @@ import Text.Pandoc.Biblio (processBiblio)
--------------------------------------------------------------------------------
import Hakyll.Core.Compiler
import Hakyll.Core.Identifier
+import Hakyll.Core.Item
import Hakyll.Core.Writable
-import Hakyll.Web.Page
import Hakyll.Web.Pandoc
--------------------------------------------------------------------------------
-newtype CSL = CSL FilePath
- deriving (Binary, Show, Typeable, Writable)
+data CSL = CSL
+ deriving (Show, Typeable)
+
+
+--------------------------------------------------------------------------------
+instance Binary CSL where
+ put CSL = return ()
+ get = return CSL
+
+
+--------------------------------------------------------------------------------
+instance Writable CSL where
+ -- Shouldn't be written.
+ write _ _ = return ()
--------------------------------------------------------------------------------
-cslCompiler :: Compiler CSL
-cslCompiler = CSL . toFilePath <$> getIdentifier
+cslCompiler :: Compiler (Item CSL)
+cslCompiler = makeItem CSL
--------------------------------------------------------------------------------
@@ -57,29 +69,34 @@ instance Binary Biblio where
get = Biblio . read <$> get
put (Biblio rs) = put $ show rs
+
+--------------------------------------------------------------------------------
instance Writable Biblio where
+ -- Shouldn't be written.
write _ _ = return ()
--------------------------------------------------------------------------------
-biblioCompiler :: Compiler Biblio
+biblioCompiler :: Compiler (Item Biblio)
biblioCompiler = do
- filePath <- toFilePath <$> getIdentifier
- unsafeCompiler $ Biblio <$> CSL.readBiblioFile filePath
+ filePath <- toFilePath <$> getUnderlying
+ makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile filePath)
--------------------------------------------------------------------------------
-pageReadPandocBiblio :: ParserState
- -> CSL
- -> Biblio
- -> Page
- -> Compiler Pandoc
-pageReadPandocBiblio state (CSL csl) (Biblio refs) page = do
+readPandocBiblio :: ParserState
+ -> Item CSL
+ -> Item Biblio
+ -> (Item String)
+ -> Compiler (Item Pandoc)
+readPandocBiblio state csl biblio item = do
-- We need to know the citation keys, add then *before* actually parsing the
-- actual page. If we don't do this, pandoc won't even consider them
-- citations!
- let cits = map CSL.refId refs
- state' = state {stateCitations = stateCitations state ++ cits}
- pandoc <- pageReadPandocWith state' page
- pandoc' <- unsafeCompiler $ processBiblio csl Nothing refs pandoc
- return pandoc'
+ let Biblio refs = itemBody biblio
+ cits = map CSL.refId refs
+ state' = state {stateCitations = stateCitations state ++ cits}
+ pandoc = itemBody $ readPandocWith state' item
+ cslPath = toFilePath $ itemIdentifier csl
+ pandoc' <- unsafeCompiler $ processBiblio cslPath Nothing refs pandoc
+ return $ fmap (const pandoc') item
diff --git a/src/Hakyll/Web/Pandoc/FileType.hs b/src/Hakyll/Web/Pandoc/FileType.hs
index 2d28edd..1ae4c10 100644
--- a/src/Hakyll/Web/Pandoc/FileType.hs
+++ b/src/Hakyll/Web/Pandoc/FileType.hs
@@ -3,18 +3,17 @@
module Hakyll.Web.Pandoc.FileType
( FileType (..)
, fileType
- , getFileType
+ , itemFileType
) where
--------------------------------------------------------------------------------
-import Control.Applicative ((<$>))
import System.FilePath (takeExtension)
--------------------------------------------------------------------------------
-import Hakyll.Core.Compiler
import Hakyll.Core.Identifier
+import Hakyll.Core.Item
--------------------------------------------------------------------------------
@@ -62,5 +61,5 @@ fileType = fileType' . takeExtension
--------------------------------------------------------------------------------
-- | Get the file type for the current file
-getFileType :: Compiler FileType
-getFileType = fileType . toFilePath <$> getIdentifier
+itemFileType :: Item a -> FileType
+itemFileType = fileType . toFilePath . itemIdentifier
diff --git a/src/Hakyll/Web/Template.hs b/src/Hakyll/Web/Template.hs
index 6d9060f..adaf1aa 100644
--- a/src/Hakyll/Web/Template.hs
+++ b/src/Hakyll/Web/Template.hs
@@ -60,10 +60,10 @@
-- > #{body}
module Hakyll.Web.Template
( Template
- , applyTemplate
, templateCompiler
, templateCompilerWith
- , applyTemplateCompiler
+ , applyTemplate
+ , applyTemplateWith
) where
@@ -78,51 +78,51 @@ import Text.Hamlet (HamletSettings,
--------------------------------------------------------------------------------
import Hakyll.Core.Compiler
import Hakyll.Core.Identifier
-import Hakyll.Web.Page.Internal
+import Hakyll.Core.Item
import Hakyll.Web.Template.Context
import Hakyll.Web.Template.Internal
import Hakyll.Web.Template.Read
--------------------------------------------------------------------------------
-applyTemplate :: Monad m
- => (String -> a -> m String)
- -> Template -> a -> m String
-applyTemplate context tpl x = liftM concat $
- forM (unTemplate tpl) $ \e -> case e of
- Chunk c -> return c
- Escaped -> return "$"
- Key k -> context k x
-
-
---------------------------------------------------------------------------------
-- | Read a template. If the extension of the file we're compiling is
-- @.hml@ or @.hamlet@, it will be considered as a Hamlet template, and parsed
-- as such.
-templateCompiler :: Compiler Template
+templateCompiler :: Compiler (Item Template)
templateCompiler = templateCompilerWith defaultHamletSettings
--------------------------------------------------------------------------------
-- | Version of 'templateCompiler' that enables custom settings.
-templateCompilerWith :: HamletSettings -> Compiler Template
+templateCompilerWith :: HamletSettings -> Compiler (Item Template)
templateCompilerWith settings =
cached "Hakyll.Web.Template.templateCompilerWith" $ do
- identifier <- getIdentifier
- string <- getResourceString
+ identifier <- getUnderlying
+ item <- getResourceString
if takeExtension (toFilePath identifier) `elem` [".hml", ".hamlet"]
-- Hamlet template
- then return $ readHamletTemplateWith settings string
+ then return $ fmap (readHamletTemplateWith settings) item
-- Hakyll template
- else return $ readTemplate string
+ else return $ fmap readTemplate item
+
+
+--------------------------------------------------------------------------------
+applyTemplate :: Template -- ^ Template
+ -> Context a -- ^ Context
+ -> Item a -- ^ Page
+ -> Compiler (Item String) -- ^ Resulting item
+applyTemplate tpl context item = do
+ let context' k x = unContext context k x
+ body <- applyTemplateWith context' tpl item
+ return $ itemSetBody body item
--------------------------------------------------------------------------------
-applyTemplateCompiler :: Template -- ^ Template
- -> Context Page -- ^ Context
- -> Page -- ^ Page
- -> Compiler Page -- ^ Compiler
-applyTemplateCompiler tpl context page = do
- identifier <- getIdentifier
- let context' k x = unContext context k identifier x
- applyTemplate context' tpl page
+applyTemplateWith :: Monad m
+ => (String -> a -> m String)
+ -> Template -> a -> m String
+applyTemplateWith context tpl x = liftM concat $
+ forM (unTemplate tpl) $ \e -> case e of
+ Chunk c -> return c
+ Escaped -> return "$"
+ Key k -> context k x
diff --git a/src/Hakyll/Web/Template/Context.hs b/src/Hakyll/Web/Template/Context.hs
index 2ef82e9..b3c2a6d 100644
--- a/src/Hakyll/Web/Template/Context.hs
+++ b/src/Hakyll/Web/Template/Context.hs
@@ -34,36 +34,36 @@ import System.Locale (TimeLocale, defaultTimeLocale)
import Hakyll.Core.Compiler
import Hakyll.Core.Compiler.Internal
import Hakyll.Core.Identifier
-import Hakyll.Core.ResourceProvider
+import Hakyll.Core.Item
+import Hakyll.Core.Provider
import Hakyll.Core.Util.String (splitAll)
-import Hakyll.Web.Page.Internal
import Hakyll.Web.Urls
--------------------------------------------------------------------------------
newtype Context a = Context
- { unContext :: String -> Identifier -> a -> Compiler String
+ { unContext :: String -> Item a -> Compiler String
}
--------------------------------------------------------------------------------
instance Monoid (Context a) where
- mempty = Context $ \_ _ _ -> empty
- mappend (Context f) (Context g) = Context $ \k i x -> f k i x <|> g k i x
+ mempty = Context $ \_ _ -> empty
+ mappend (Context f) (Context g) = Context $ \k i -> f k i <|> g k i
--------------------------------------------------------------------------------
mapContext :: (String -> String) -> Context a -> Context a
-mapContext f (Context g) = Context $ \k i x -> f <$> g k i x
+mapContext f (Context g) = Context $ \k i -> f <$> g k i
--------------------------------------------------------------------------------
-field :: String -> (Identifier -> a -> Compiler String) -> Context a
-field key value = Context $ \k i x -> if k == key then value i x else empty
+field :: String -> (Item a -> Compiler String) -> Context a
+field key value = Context $ \k i -> if k == key then value i else empty
--------------------------------------------------------------------------------
-defaultContext :: Context Page
+defaultContext :: Context String
defaultContext =
bodyField "body" `mappend`
urlField "url" `mappend`
@@ -74,18 +74,19 @@ defaultContext =
--------------------------------------------------------------------------------
-bodyField :: String -> Context Page
-bodyField key = field key $ \_ x -> return x
+bodyField :: String -> Context String
+bodyField key = field key $ return . itemBody
--------------------------------------------------------------------------------
urlField :: String -> Context a
-urlField key = field key $ \i _ -> maybe empty toUrl <$> getRouteFor i
+urlField key = field key $
+ fmap (maybe empty toUrl) . getRoute . itemIdentifier
--------------------------------------------------------------------------------
pathField :: String -> Context a
-pathField key = field key $ \i _ -> return $ toFilePath i
+pathField key = field key $ return . toFilePath . itemIdentifier
--------------------------------------------------------------------------------
@@ -133,8 +134,8 @@ dateFieldWith :: TimeLocale -- ^ Output time locale
-> String -- ^ Destination key
-> String -- ^ Format to use on the date
-> Context a -- ^ Resulting context
-dateFieldWith locale key format = field key $ \id' _ -> do
- time <- getUTC locale id'
+dateFieldWith locale key format = field key $ \i -> do
+ time <- getUTC locale $ itemIdentifier i
return $ formatTime locale format time
@@ -145,7 +146,7 @@ getUTC :: TimeLocale -- ^ Output time locale
-> Identifier -- ^ Input page
-> Compiler UTCTime -- ^ Parsed UTCTime
getUTC locale id' = do
- metadata <- getMetadataFor id'
+ metadata <- getMetadata id'
let tryField k fmt = M.lookup k metadata >>= parseTime' fmt
fn = takeFileName $ toFilePath id'
@@ -177,11 +178,11 @@ modificationTimeFieldWith :: TimeLocale -- ^ Time output locale
-> String -- ^ Key
-> String -- ^ Format
-> Context a -- ^ Resulting context
-modificationTimeFieldWith locale key fmt = field key $ \id' _ -> do
- mtime <- compilerUnsafeIO $ resourceModificationTime id'
+modificationTimeFieldWith locale key fmt = field key $ \i -> do
+ mtime <- compilerUnsafeIO $ resourceModificationTime $ itemIdentifier i
return $ formatTime locale fmt mtime
--------------------------------------------------------------------------------
missingField :: Context a
-missingField = Context $ \k _ _ -> return $ "$" ++ k ++ "$"
+missingField = Context $ \k _ -> return $ "$" ++ k ++ "$"
diff --git a/src/Hakyll/Web/Urls/Relativize.hs b/src/Hakyll/Web/Urls/Relativize.hs
index 068ae09..321bbe3 100644
--- a/src/Hakyll/Web/Urls/Relativize.hs
+++ b/src/Hakyll/Web/Urls/Relativize.hs
@@ -15,8 +15,8 @@
--
-- > <img src="../images/lolcat.png" alt="Funny zomgroflcopter" />
module Hakyll.Web.Urls.Relativize
- ( relativizeUrlsCompiler
- , relativizeUrls
+ ( relativizeUrls
+ , relativizeUrlsWith
) where
@@ -26,27 +26,27 @@ import Data.List (isPrefixOf)
--------------------------------------------------------------------------------
import Hakyll.Core.Compiler
-import Hakyll.Web.Page
+import Hakyll.Core.Item
import Hakyll.Web.Urls
--------------------------------------------------------------------------------
-- | Compiler form of 'relativizeUrls' which automatically picks the right root
-- path
-relativizeUrlsCompiler :: Page -> Compiler Page
-relativizeUrlsCompiler page = do
- route <- getRoute
+relativizeUrls :: Item String -> Compiler (Item String)
+relativizeUrls item = do
+ route <- getRoute $ itemIdentifier item
return $ case route of
- Nothing -> page
- Just r -> relativizeUrls (toSiteRoot r) page
+ Nothing -> item
+ Just r -> fmap (relativizeUrlsWith $ toSiteRoot r) item
--------------------------------------------------------------------------------
-- | Relativize URL's in HTML
-relativizeUrls :: String -- ^ Path to the site root
- -> Page -- ^ HTML to relativize
- -> Page -- ^ Resulting HTML
-relativizeUrls root = withUrls rel
+relativizeUrlsWith :: String -- ^ Path to the site root
+ -> String -- ^ HTML to relativize
+ -> String -- ^ Resulting HTML
+relativizeUrlsWith root = withUrls rel
where
isRel x = "/" `isPrefixOf` x && not ("//" `isPrefixOf` x)
rel x = if isRel x then root ++ x else x