module Pencil
(
-- * Getting started
--
-- $gettingstarted
-- * Templates
--
-- $templates
PencilApp
, run
-- * Pages, Structures and Resources
--
-- $pagesStructuresResources
, Page
, getPageEnv, setPageEnv
, load
, withEnv
, renderCss
, Structure
, (<||)
, (<|)
, structure
, Resource
, loadResource
, loadResources
, passthrough
, listDir
, Render(..)
, asHtml
, asDir
, asCss
, asIntended
-- * Environment Manipulation
, merge
, insertEnv
, insertText
, insertPages
, updateEnvVal
, sortByVar
, filterByVar
, groupByElements
-- * Configuration
, Config
, defaultConfig
, getSourceDir, setSourceDir
, getOutputDir, setOutputDir
, getEnv, setEnv, updateEnv
, getDisplayValue, setDisplayValue
, getSassOptions, setSassOptions
, getPandocReaderOptions, setPandocReaderOptions
, getPandocWriterOptions, setPandocWriterOptions
-- * Utils and re-exports
, FileType
, fileType
, toExtension
-- Re-exports
, Reader.asks
-- * Error handling
, PencilException
) where
import Pencil.Internal
import Control.Monad.Reader as Reader
----------------------------------------------------------------------
-- $gettingstarted
--
-- We'll start by building a very simple website, with only a couple of pages,
-- to give you a feel for using Pencil. Go to http://elbenshira.com/pencil for
-- in-depth tutorials, including how you can set up a blog.
--
-- To build our simple website, we'll first create some folders and files:
--
-- > cd ~/code/mywebsite
-- > mkdir site/
-- > echo '
-- >
-- >
-- >
-- > ${title}
-- >
-- >
-- > ${body}
-- > ' > site/layout.html
-- > echo 'Welcome to my *awesome* [website](http://example.com)!' > site/index.markdown
-- > echo '$mycolor: #ff0000; body { color: $mycolor; }' > site/style.scss
--
-- Notice that @layout.html@ contains two variable directives, @${title}@ and
-- @${body}@, which we will have to fill values for before rendering the pages that
-- use @layout.html@.
--
-- Then inside your @Main.hs@:
--
-- @
-- import Pencil
--
-- config :: Config
-- config = insertText "title" "My Website" defaultConfig
--
-- website :: PencilApp ()
-- website = do
-- layout <- load asHtml "layout.html"
-- index <- load asHtml "index.markdown"
--
-- render (layout <|| index)
-- renderCss "style.scss"
--
-- main = run website config
-- @
----------------------------------------------------------------------
-- $templates
--
-- Pencil comes with a simple templating engine. Templates allow us to build web
-- pages dynamically using Haskell code. This allows us to build modular
-- components. Templates can be used for things like shared page layouts,
-- navigation and blog post templates.
--
-- Pencil templates are regular text files that can contain a /preamble/ and
-- /directives/.
--
-- == Preamble
--
-- Preambles are YAML-formatted environment variable declarations inside your
-- source files. They should be declared at the top of the file, and you may
-- only have one preamble per source file. Example preamble, in the first part
-- of @my-blog-post.markdown@:
--
-- >
--
-- In the above example, Pencil will intelligently parse the @date@ value as a
-- `VDateTime`.
--
-- == Directives
--
-- Directives are rendering /commands/. They are surrounded by @${...}@.
--
-- === Variables
--
-- The simplest directive is the variable directive.
--
-- @
-- Hello ${name}!
-- @
--
-- The above template will render the value of the variable @name@, which is
-- expected to be in the environment at 'render'. If the variable is not found,
-- Pencil will throw an exception with some debugging information.
--
-- === If block
--
-- The @if@ directive allows us to render content based off the existence of a
-- variable in the current environment.
--
-- > ${if(name)}
-- > Hello ${name}!
-- > ${end}
--
-- In this case, we now make sure that @name@ is available before rendering.
--
-- === For loop
--
-- The @for@ directive allows us to loop over array type variable. This is
-- useful for things like rendering a list of blog post titles, and URLs to the
-- individual blog posts.
--
-- >
--
-- Assuming that @posts@ exists in our environment as an array of @Value@,
-- this will render each post's title, publish date, and will link it to
-- @this.url@. Note that inside the @for@ block, you have access to the current
-- environment's variables. This is why we're able to simply request
-- @${postTitle}@—it is the current post's @postTitle@ that will be rendered.
--
-- @this.url@ is a special variable that is automatically inserted for you
-- inside a loaded @Page@. It points to the final file path destination of that
-- current @Page@.
--
-- === Partials
--
-- The @partial@ directive injects another template file into the current file.
-- The directives inside the partial are rendered in the same environmental
-- context as the @partial@ directive.
--
-- Think of partials as just copy-and-pasting snippet from one file to another.
-- Unlike 'Structure's, partials cannot define environment variables.
--
-- In the example below, the first @partial@ is rendered with the current
-- environment. The @partial@ inside the @for@ loop receives the same
-- environemnt as any other snippet inside the loop, and thus has access to
-- the environment inside each post.
--
-- > ${partial("partials/nav-bar.html")}
-- >
-- > ${for(posts)}
-- > ${partial("partials/nav-bar.html")}
-- > ${end}
----------------------------------------------------------------------
-- $pagesStructuresResources
--
-- 'Page', 'Structure' and 'Resource' are the "big three" data types you need to
-- know to effectively use Pencil.
----------------------------------------------------------------------