Lab #9: Rendering HTML output

Assigned: Wed 13 Apr 2005
Due: Wed 27 Apr 2005

In this lab you will write two programs which generate web pages in HTML format using the Text.Html library supplied with Hugs. I've given two weeks for this lab since there is no lab on the 20th of April (SSRD Day).

When you're done, you might have a set of html files which look something like this (you would have more interesting pictures, of course, and likely a larger and more complex directory structure).

Some references

The Text.Html library comes with a Hugs installation, and although it is not very thoroughly documented, see the following places for some tips:

Most people who would use this library would be already familiar with HTML, and most of the standard HTML tags are represented by little tagging functions, but there are also some higher-level "combinators" (functions) which can simplify the rendering of Haskell values such as lists (see below). If you want to read up on HTML, here are some other nice on-line references:

A warm-up exercise

HTML uses a couple of tag structures to represent lists of items, namely the ordered (<ol> and </ol>) and unordered list (<ul> and </ul>) tags and the list item (<li>) which occurs embedded between them (see this reference for how they are used).

In the Haskell Html library, you can either use low-level tag functions to get these same list types, or you can use the higher-level combinators ordList and unordList of these types:

	ordList   :: (HTML a) => [a] -> Html
	ordList items = olist << map (li <<) items
	
	unordList :: (HTML a) => [a] -> Html
	unordList items = ulist << map (li <<) items	
Nested lists (whether ordered or unordered) display with successive indents, rather like the display format we used for printing Spread trees.

Write a function which will take a Spread tree as argument and return an Html object as a result, where each item is separated by a paragraph from its children, which are themselves rendered as an unordered list. For example, this file shows the ubiquitous dog tree as rendered in HTML using this format.

I used a function of type renderTree :: HTML a => Tree a -> Html which allows a tree of any renderable item type to be output as HTML. I also used a tree fold in my definition, which made it especially simple (one line, in fact), but you may use explicit recursion if you are more comfortable with that.

Once you have your function working, you can test it by using the following code, which serves as a kind of generic "wrapper" to output simple HTML pages (you will need to change the path variable to point to your own webspace). Your output should look something like this.

	dump f p = writeFile (path ++ f ++ ".html") (renderHtml p)
	
	path = "/Volumes/fruehr/public_html/454/html/"
	
	simpPage b = header << thetitle << "" +++ body << b
	
	main' = dump "rawtree" (simpPage (renderTree dogs))
You might also want to use this wrapper code for the bigger exercise below.

An on-line picture browser

Many people these days have folders of digital pictures on their computer, and they sometimes wish to share these with friends and relatives over the web. A lot of tools exist which can take a hierarchy of folders of pictures and render them into weg pages with thumbnails and navigation controls: we will write a simple one using Haskell and the Text.Html libraries.

The idea is to read in information about a folder (or directory) with nested sub-folders and (ultimately) picture files, and output a series of HTML files which display the pictures and allow for easy navigation. You can get information about folders (or directories) using the Directory standard library which ships with Hugs (just remember to import it in your code). You can read about the directory functions here (note that many of them work in the IO monad, so you will need to wrap them up in "do" notation to use them).

Once you have information about a folder's contents, you can distinguish sub-directories from graphic files by their extension (assume either GIF or jpeg files, and use whichever extensions you have on your own data; you may also assume that only sub-directories and pictures will occur in any given folder). A natural approach would be to build a tree (like a Spread tree) to represent the contents of a given file hierarchy, perhaps with special nodes to distinguish pictures from other directories; for example, you might use a definition like this:

	data PicTree = Picture FilePath | Directory FilePath [PicTree] 
Once you have an internal Haskell tree representing the file structure, it should be pretty easy to use the idea of the previous exercise to generate an HTML file for each tree node (you might want to use a "do" block and generate one file with each action). These files could then contain references to the pictures (using ) or, if the node is a directory, perhaps a hot-linked listing of the contents of the directory. (These references point you to HTML documentation; you may want to also look at the Haskell Html library docs to see how to access them in Haskell.)

Rather than give a detailed description of requirements for this project (and especially because of the upcoming end-of-term projects), I think I will just give some broad guidelines and then allow people to implement as much as they want (I'm assuming that the enthusiasm for applications, especially in HTML, will carry people through to a relatively complete solution).

So, here are some guidleines on what to produce:

  • try to produce at least an image file for each picture and a listing file for each directory;

  • if you can, try to add links from one picture to the next one and the previous ones in the same directory (this is a little harder, but you could using something like a tree zip to get the right data connected);

  • similarly, links to next and previous sub-directories would be nice, along with links up to the containing directory;

  • if you can, you might try to generate thumbnails: you can do this by specifying dimensions on your images, but unless the specified dimensions preserve the aspect ratio of the picture, they may look a bit distorted (you may be able to get suitable dimensions globally if all your pictures come from a digital camera, though).

Remember, the main idea of this exercise is to give you something both fun and useful to do which works with IO, libraries, HTML and data structures. So try to do as much as you can, within the confines of your own motivations.

Please have answers to the above exercises ready for the next lab session on Wednesday 27 April. We will likely use a "demo style" for this program, rather than a static grading.