Need basic help with reformatting urls

94 views
Skip to first unread message

RJ

unread,
Jul 6, 2014, 2:33:10 PM7/6/14
to hak...@googlegroups.com
Hello,

I am still very new to both Haskall and Hakyll and need to basic help understanding how I might implement two possible route configurations. 

I understand the basics of routes and using metadata in the .markdown files.

How would I go about:

1. Remove the date from the url

so instead of this:

http://0.0.0.0:8000/projects/2014-06-20-project-name.html

I get this:


With the projects still organized by date. 


2. Make "pretty" urls

Example:

I found some hacks to get this to look like wordpress urls /YYYY/MM/DD/project-name/ but it's still hard to understand since I'm new. 

Thank you for the assistance!

RJ

Jasper Van der Jeugt

unread,
Jul 8, 2014, 4:46:18 AM7/8/14
to hak...@googlegroups.com
Hey RJ!

In order to drop the date from the URL, let's write a small utility:

-- Turns 'foo-bar' into 'bar'.
dropComponent :: String -> String
dropComponent str = case break (== '-') str of
(_, _ : str') -> str'
(str', []) -> str'

This makes writing a drop date function very easy:

-- Turns '2014-06-20-project-name.html' into 'project-name.html'.
dropDate :: String -> String
dropDate = dropComponent . dropComponent . dropComponent

Now we need a way to generate "pretty" urls. If you want to support:

http://0.0.0.0:8000/projects/project-name/

Then a good approach is to generate:

http://0.0.0.0:8000/projects/project-name/index.html

Since this works with most servers (alternatively you can customize your
server, which is probably a neater way to do this, but I'm going to
assume you might not have complete control over the server).

import System.FilePath (dropExtension, takeBaseName, takeDirectory,
(</>))

prettyRoute :: Routes
prettyRoute = customRoute $ \identifier ->
-- Suppose we have:
-- filePath = 'projects/2014-06-20-project-name.html'
--
-- We get:
-- directory = 'projects'
-- baseName = '2014-06-20-project-name.html'
-- simpleName = 'project-name'
let filePath = toFilePath identifier
directory = takeDirectory filePath
baseName = takeBaseName filePath
simpleName = dropExtension (dropDate baseName)
in directory </> simpleName </> "index.html"

This will write your file to:

_site/projects/project-name/index.html

So if you upload, it can be found by the server. However, this causes an
additional problem. Now, the links embedded in your templates will
contain this URL by default, e.g.:

<a href="./project-name/index.html">Project Name</a>

Whereas we actually want something like:

<a href="./project-name/">Project Name</a>

This means you need to rewrite the URLs in your pages. You can use a
simple compiler to do this:

cleanUrls :: String -> Compiler String
cleanUrls = return . withUrls clean
where
clean url = case takeBaseName url of
"index.html" -> takeDirectory url
_ -> url

That should be it. Hope this helps!

Peace,
Jasper
> --
> You received this message because you are subscribed to the Google Groups "hakyll" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to hakyll+un...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

RJ

unread,
Jul 16, 2014, 2:35:21 PM7/16/14
to hak...@googlegroups.com
Hi Jasper,

Thank you for the help. I have another question. 

I have been able to incorporate the pretty routes for a project as follows, but am still stuck on formatting the urls with a compiler. I guess I'm not sure how to implement cleanUrls. 

    match "projects/*" $ do
        route $ prettyRoute
        compile $ pandocCompiler
            >>= loadAndApplyTemplate "templates/project.html" projectCtx
            >>= loadAndApplyTemplate "templates/default.html" projectCtx
            >>= relativizeUrls            

    create ["projects.html"] $ do
        route prettyRoute
        compile $ do
            projects <- recentFirst =<< loadAll "projects/*"
            let projectsCtx =
                    listField "projects" projectCtx (return projects) `mappend`
                    constField "title" "Projects"            `mappend`
                    defaultContext

            makeItem ""
                >>= loadAndApplyTemplate "templates/projects.html" projectsCtx
                >>= loadAndApplyTemplate "templates/default.html" projectsCtx
                >>= relativizeUrls

With this I am able to get URL's to show up in the format project/project-name/index.html. Of course just going to project/project-name/ works but the URL's that show up as links are still including the index.html part. 
Reply all
Reply to author
Forward
0 new messages