Added a new post, added syntax highlighting CSS for code blocks
parent
6cf7774288
commit
259b67b4a0
|
@ -227,7 +227,41 @@ setFontSize x = do
|
|||
-}
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-- Syntax Highlighting via highlighting-kate
|
||||
scKeyword, scDataType, scDecimal, scBaseN, scFloat, scChar, scString :: Selector
|
||||
scComment, scOther, scAlert, scFunction, scRegion, scError :: Selector
|
||||
|
||||
scKeyword = ".kw"
|
||||
scDataType = ".dt"
|
||||
scDecimal = ".dv"
|
||||
scBaseN = ".bn"
|
||||
scFloat = ".fl"
|
||||
scChar = ".ch"
|
||||
scString = ".st"
|
||||
scComment = ".co"
|
||||
scOther = ".ot"
|
||||
scAlert = ".al"
|
||||
scFunction = ".fu"
|
||||
scRegion = ".re"
|
||||
scError = ".er"
|
||||
|
||||
syntaxHighlight = pre # ".sourceCode" ? do
|
||||
backgroundColor "#F9F9F9"
|
||||
borderLeft solid (px 3) accent2
|
||||
scKeyword <> scDataType ? color "#268BD2"
|
||||
scDecimal <> scBaseN <> scFloat ? color "#D33682"
|
||||
scChar ? color "#DC322F"
|
||||
scString ? color "#2AA198"
|
||||
scComment ? color "#93A1A1"
|
||||
scOther ? color "#A57800"
|
||||
scFunction ? color "#268BD2"
|
||||
scError ? do color "#D30102"
|
||||
fontWeight bold
|
||||
scAlert ? do color "#CB4B16"
|
||||
fontWeight bold
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
def =
|
||||
Layout { totalColumns = 12
|
||||
, columnWidth = Em 3
|
||||
|
@ -247,7 +281,8 @@ headingColor = primary
|
|||
|
||||
main = putCss $ do
|
||||
typography
|
||||
|
||||
syntaxHighlight
|
||||
|
||||
"#container" ? do
|
||||
container
|
||||
|
||||
|
@ -308,10 +343,8 @@ typography = do
|
|||
"#footer" ** p ? do
|
||||
color accent2
|
||||
|
||||
selectors [ p, ".info", "#logo" ] ? do
|
||||
selectors [ p, ".info", "#logo", pre ] ? do
|
||||
setFontSize baseFontPx
|
||||
|
||||
selectors [ p, ".info", "#logo" ] ? do
|
||||
marginBottom $ px baselinePx
|
||||
|
||||
selectors [ h1, h2, h3] ? do
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
---
|
||||
title: More on Hakyll
|
||||
---
|
||||
|
||||
On Personal Websites
|
||||
--------------------
|
||||
|
||||
I have had a website running, off and on, since the mid-90s. At first,
|
||||
it was a simple collection of HTML files with a few images. Web
|
||||
technologies developed rapidly, though, and it became time-consuming
|
||||
to do anything interesting with my sites.
|
||||
|
||||
I've used a number of "simplifying" tools over the years, but most of
|
||||
them relied on dynamically generating pages from a SQL database of
|
||||
some sort, and I just don't want to deal with that right now. I want
|
||||
simple markup again, and I want it to be served directly and
|
||||
efficiently by any old plain web server.
|
||||
|
||||
My Basic Requirements
|
||||
---------------------
|
||||
|
||||
HTML is no longer really a markup language, it's more of a structured
|
||||
document modeling language. I don't want to compose text documents in
|
||||
*code*, I want to write them naturally in my native language. A few
|
||||
stylistic clues in my text formatting should suffice for specifying
|
||||
the structure of these simple text documents.
|
||||
|
||||
So, [Markdown][Md] provides exactly the sort of markup language I
|
||||
want, but a web site requires more structure. Exactly the structure
|
||||
provided by HTML, in fact. So, [Pandoc][Pan] converts Markdown to HTML
|
||||
(among *many* other formats), which provides the core functionality I
|
||||
need.
|
||||
|
||||
But there's more-- a bunch of HTML files don't quite make a cohesive
|
||||
site. They need some common additional structure, such as headers and
|
||||
footers. They need a navigation structure to link them together. And
|
||||
it would be nice to be able to generate content syndication feeds as
|
||||
well.
|
||||
|
||||
What I need is a system that allows me to compose simple text files
|
||||
written in a text-based markup language together with some HTML
|
||||
templates into a *static* set of interlinked pure-HTML pages, along
|
||||
with some other resources, whenever I write a new document.
|
||||
|
||||
Enter Hakyll
|
||||
------------
|
||||
|
||||
The [Hakyll][Hak] system provides a flexible language for describing
|
||||
just that sort of system. It is essentially a static site *compiler*
|
||||
built from a set of *rules* for transforming source documents to
|
||||
output documents.
|
||||
|
||||
This code snippet shows the rule for compiling top-level pages of my
|
||||
site from Markdown to HTML:
|
||||
|
||||
~~~~ { .haskell }
|
||||
match "*.markdown" $ do
|
||||
route $ setExtension "html"
|
||||
compile $ pandocCompiler
|
||||
>>= loadAndApplyTemplate "templates/default.html" defaultContext
|
||||
>>= relativizeUrls
|
||||
~~~~
|
||||
|
||||
The code is a form of Embedded Domain Specific Language (EDSL) that is
|
||||
both a legal [Haskell][Has] expression as well as a succinct
|
||||
description of what I want Hakyll to do for this particular case.
|
||||
|
||||
The first line describes what files this rule should apply to. It's
|
||||
expressed in a format similar to UNIX filename glob format. This one
|
||||
says that it applies to all files at the top level of the site source
|
||||
directory that have names ending in `".markdown"`.
|
||||
|
||||
Digressions on Haskell
|
||||
----------------------
|
||||
|
||||
For those not familiar with Haskell, the `$` character is a
|
||||
right-associative operator that denotes function application-- the
|
||||
left-operand is the function, the right-operand is the argument. This
|
||||
is in addition to the normal way of expressing function application,
|
||||
which is a left-associative operation denoted by juxtaposing the
|
||||
operands.
|
||||
|
||||
Normal function application has a very high precedence in the Haskell
|
||||
grammar, so the `$` form is often used in place of parentheses to
|
||||
allow a secondary function application to provide the argument to a
|
||||
primary function application.
|
||||
|
||||
With that digression out of the way, the second line can be seen as a
|
||||
nested function application-- the `route` function is passed the
|
||||
`setExtension "html"` function. As another digression, there are two
|
||||
interesting things to say about this nested application:
|
||||
|
||||
1. The function application `setExtension "html"` evaluates to a value
|
||||
that is itself a function-- the function that takes a filename,
|
||||
possibly with some extension already, and produces a new filename
|
||||
with the extension `"html"` instead. So `setExtensions` is a
|
||||
*higher-order* function in two ways, because it is used as an
|
||||
argument to another function and also because it returns a function
|
||||
as its result.
|
||||
|
||||
2. The arguments to Haskell functions are not necessarily evaluated
|
||||
before the functions themselves. So if the rule on line 1 never
|
||||
matched any files, the `setExtension "html"` expression would never
|
||||
need to be evaluated. If the rule found multiple matches, however,
|
||||
the expression would evaluate *only once* to the function that sets
|
||||
filename extensions to `"html"`.
|
||||
|
||||
Regardless of the language mechanics behind the scene, the effect of
|
||||
the second line is to ensure that when the rule completes, the
|
||||
resulting file will have the `"html"` extension rather than the
|
||||
`"markdown"` extension it started with.
|
||||
|
||||
Back to the Example
|
||||
-------------------
|
||||
|
||||
The third line starts the expression that does the bulk of the
|
||||
work. It calls the `compile` function, and specifies the compiler as
|
||||
the `pandocCompiler` function with its output piped through a couple
|
||||
of post-processors, `loadAndApplyTemplates` and `relativizeUrls`.
|
||||
|
||||
The `pandocCompiler` is built in to Hakyll, and it links to the Pandoc
|
||||
markup processor mentioned earlier. In default form, as it's used
|
||||
here, it translates Markdown documents to HTML documents.
|
||||
|
||||
As the name implies, `loadAndApplyTemplates` applies the template we
|
||||
give it along with a `Context`, which is a data structure that
|
||||
describes the mappings between template variables and the values they
|
||||
should expand to. We use the default one, which provides template
|
||||
variables such as `"title"`, `"url"`, and `"body"` to the template
|
||||
based on the values from the item that's being processed.
|
||||
|
||||
Finally, `relativizeUrls` will find all the links in the document and
|
||||
change them from absolute URL form, e.g. `"/foo.html"`; to relative
|
||||
URL form, e.g. `"foo.html"`. This allows us to have absolute URLs for
|
||||
syndication feeds, but relative URLs for the site itself.
|
||||
|
||||
This example covered only one of eight rules I'm currently using, but
|
||||
hopefully it gives an idea of how simple and flexible the rule-based
|
||||
system is.
|
||||
|
||||
Hakyll's Rule Processing
|
||||
------------------------
|
||||
|
||||
Like the `make` language, Hakyll's rule processor keeps track of the
|
||||
relationships between source files and build products, and it only
|
||||
runs rules for which the input files are newer than the existing build
|
||||
products. If you just add a new bit of content, such as a blog entry,
|
||||
only a few rules may need to run again. On the other hand, changing a
|
||||
core template may require rebuilding most of the site!
|
||||
|
||||
Full rebuilds are one of the areas in which Hakyll really shines,
|
||||
though. Since its rules are a language embedded within Haskell, a
|
||||
Hakyll site builder is a compiled and optimized binary program whose
|
||||
single purpose is to rebuild your site as quickly as possible.
|
||||
|
||||
By default, it stores all its intermediate work on disk, but if you
|
||||
have the memory to work with, it can also keep all its intermediate
|
||||
work in memory, which makes it even faster. For my own site, which
|
||||
only has a few files so far, rebuilding the entire thing is nearly
|
||||
instant even on an old 32-bit PC, so I haven't bothered with any
|
||||
optimization.
|
||||
|
||||
[Md]: http://daringfireball.net/projects/markdown/ "Markdown's Original Home"
|
||||
[Pan]: http://johnmacfarlane.net/pandoc/ "Pandoc's Home"
|
||||
[Hak]: http://jaspervdj.be/hakyll/ "Hakyll's Home"
|
||||
[Has]: http://www.haskell.org/ "Haskell's Home"
|
Loading…
Reference in New Issue