mirror of
https://github.com/srid/rib.git
synced 2024-11-22 03:04:38 +03:00
Create project site based on Zettelkasten (#148)
* Add guide zettelkasten * Add svg logo * Try using svg logo * Move README over to guide * Revamp Concepts * Move development to README * remove TODO * Change branding
This commit is contained in:
parent
13e30d875e
commit
4c3e050217
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@ dist-newstyle
|
||||
dist
|
||||
result
|
||||
.shake
|
||||
b
|
||||
guide.output
|
||||
|
@ -1,35 +0,0 @@
|
||||
# Developing rib
|
||||
|
||||
Use ghcid for quicker compilation cycles:
|
||||
|
||||
```
|
||||
nix-shell --run ghcid
|
||||
```
|
||||
|
||||
To test your changes, clone [rib-sample](https://github.com/srid/rib-sample) and run it using your local rib checkout:
|
||||
|
||||
```
|
||||
cd ..
|
||||
git clone https://github.com/srid/rib-sample.git
|
||||
cd rib-sample
|
||||
nix-shell --arg rib ../rib --run 'ghcid -T main'
|
||||
```
|
||||
|
||||
## Release steps
|
||||
|
||||
1. Create a `release-x.y` branch
|
||||
1. Finalize ChangeLog.md
|
||||
1. Run `nix-shell --run 'cabal haddock'` and sanity check the haddocks
|
||||
1. Commit all changes, and push a release PR.
|
||||
1. Generated sdist using `cabal sdist`
|
||||
1. [Upload a package candidate](https://hackage.haskell.org/packages/candidates/upload)
|
||||
1. Sanity check the upload, and then "publish" it publicly.
|
||||
1. Run `cabal haddock --haddock-for-hackage` to generated haddocks for hackage.
|
||||
1. Run `cabal upload -d --publish $PATH_TO_TARBALL` to update haddocks on the release.
|
||||
1. Squash merge the PR.
|
||||
1. [Draft a new release](https://github.com/srid/rib/releases) on Github. Copy paste the change log. This will automatically create and push the new git tag.
|
||||
|
||||
### Post-release
|
||||
|
||||
1. Increment cabal version in .cabal file
|
||||
1. Plan, as first task, updating of nixpkgs and package dependencies.
|
237
README.md
237
README.md
@ -1,4 +1,4 @@
|
||||
![Logo](https://raw.githubusercontent.com/srid/rib/master/assets/rib.png)
|
||||
<img width="64px" src="./assets/rib.svg">
|
||||
|
||||
# rib
|
||||
|
||||
@ -9,236 +9,21 @@
|
||||
|
||||
Rib is a Haskell **static site generator** that aims to reuse existing libraries instead of reinventing the wheel.
|
||||
|
||||
How does it compare to the popular static site generator Hakyll?
|
||||
See <https://rib.srid.ca> for full documentation.
|
||||
|
||||
- Uses the [Shake](https://shakebuild.com/) build system at its core.
|
||||
- Write HTML ([Lucid](https://chrisdone.com/posts/lucid2/)) & CSS ([Clay](http://fvisser.nl/clay/)) in Haskell.
|
||||
- Built-in support for [Pandoc](https://pandoc.org/) and [MMark](https://github.com/mmark-md/mmark).
|
||||
- Remain as simple as possible to use (see example below)
|
||||
- Nix-based environment for reproducibility
|
||||
- `ghcid` and fsnotify for "hot reload"
|
||||
## Developing rib
|
||||
|
||||
Rib prioritizes the use of *existing* tools over reinventing them, and enables
|
||||
the user to compose them as they wish instead of having to write code to fit a
|
||||
custom framework.
|
||||
Use ghcid for quicker compilation cycles:
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
- [Quick Preview](#quick-preview)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Concepts](#concepts)
|
||||
- [Directory structure](#directory-structure)
|
||||
- [Run the site](#run-the-site)
|
||||
- [How Rib works](#how-rib-works)
|
||||
- [Editing workflow](#editing-workflow)
|
||||
- [What's next?](#whats-next)
|
||||
- [Examples](#examples)
|
||||
|
||||
## Quick Preview
|
||||
|
||||
Here is how your code may look like if you were to generate your static site
|
||||
using Rib:
|
||||
|
||||
```haskell
|
||||
-- | Route corresponding to each generated static page.
|
||||
--
|
||||
-- The `a` parameter specifies the data (typically Markdown document) used to
|
||||
-- generate the final page text.
|
||||
data Route a where
|
||||
Route_Index :: Route [(Route Pandoc, Pandoc)]
|
||||
Route_Article :: Path Rel File -> Route Pandoc
|
||||
|
||||
-- | The `IsRoute` instance allows us to determine the target .html path for
|
||||
-- each route. This affects what `routeUrl` will return.
|
||||
instance IsRoute Route where
|
||||
routeFile = \case
|
||||
Route_Index ->
|
||||
pure [relfile|index.html|]
|
||||
Route_Article srcPath ->
|
||||
fmap ([reldir|article|] </>) $
|
||||
replaceExtension ".html" srcPath
|
||||
|
||||
-- | Main entry point to our generator.
|
||||
--
|
||||
-- `Rib.run` handles CLI arguments, and takes three parameters here.
|
||||
--
|
||||
-- 1. Directory `content`, from which static files will be read.
|
||||
-- 2. Directory `dest`, under which target files will be generated.
|
||||
-- 3. Shake action to run.
|
||||
--
|
||||
-- In the shake action you would expect to use the utility functions
|
||||
-- provided by Rib to do the actual generation of your static site.
|
||||
main :: IO ()
|
||||
main = withUtf8 $ do
|
||||
Rib.run [reldir|content|] [reldir|dest|] generateSite
|
||||
|
||||
-- | Shake action for generating the static site
|
||||
generateSite :: Action ()
|
||||
generateSite = do
|
||||
-- Copy over the static files
|
||||
Rib.buildStaticFiles [[relfile|static/**|]]
|
||||
let writeHtmlRoute :: Route a -> a -> Action ()
|
||||
writeHtmlRoute r = Rib.writeRoute r . Lucid.renderText . renderPage r
|
||||
-- Build individual sources, generating .html for each.
|
||||
articles <-
|
||||
Rib.forEvery [[relfile|*.md|]] $ \srcPath -> do
|
||||
let r = Route_Article srcPath
|
||||
doc <- Pandoc.parse Pandoc.readMarkdown srcPath
|
||||
writeHtmlRoute r doc
|
||||
pure (r, doc)
|
||||
writeHtmlRoute Route_Index articles
|
||||
|
||||
-- | Define your site HTML here
|
||||
renderPage :: Route a -> a -> Html ()
|
||||
renderPage route val = html_ [lang_ "en"] $ do
|
||||
head_ $ do
|
||||
meta_ [httpEquiv_ "Content-Type", content_ "text/html; charset=utf-8"]
|
||||
title_ routeTitle
|
||||
style_ [type_ "text/css"] $ C.render pageStyle
|
||||
body_ $ do
|
||||
div_ [class_ "header"] $
|
||||
a_ [href_ "/"] "Back to Home"
|
||||
h1_ routeTitle
|
||||
case route of
|
||||
Route_Index ->
|
||||
div_ $ forM_ val $ \(r, src) ->
|
||||
li_ [class_ "pages"] $ do
|
||||
let meta = getMeta src
|
||||
b_ $ a_ [href_ (Rib.routeUrl r)] $ toHtml $ title meta
|
||||
renderMarkdown `mapM_` description meta
|
||||
Route_Article _ ->
|
||||
article_ $
|
||||
Pandoc.render val
|
||||
where
|
||||
routeTitle :: Html ()
|
||||
routeTitle = case route of
|
||||
Route_Index -> "Rib sample site"
|
||||
Route_Article _ -> toHtml $ title $ getMeta val
|
||||
renderMarkdown :: Text -> Html ()
|
||||
renderMarkdown =
|
||||
Pandoc.render . Pandoc.parsePure Pandoc.readMarkdown
|
||||
|
||||
-- | Define your site CSS here
|
||||
pageStyle :: Css
|
||||
pageStyle = C.body ? do
|
||||
C.margin (em 4) (pc 20) (em 1) (pc 20)
|
||||
".header" ? do
|
||||
C.marginBottom $ em 2
|
||||
"li.pages" ? do
|
||||
C.listStyleType C.none
|
||||
C.marginTop $ em 1
|
||||
"b" ? C.fontSize (em 1.2)
|
||||
"p" ? sym C.margin (px 0)
|
||||
|
||||
-- | Metadata in our markdown sources
|
||||
data SrcMeta
|
||||
= SrcMeta
|
||||
{ title :: Text,
|
||||
-- | Description is optional, hence `Maybe`
|
||||
description :: Maybe Text
|
||||
}
|
||||
deriving (Show, Eq, Generic, FromJSON)
|
||||
```
|
||||
nix-shell --run ghcid
|
||||
```
|
||||
|
||||
(View full [`Main.hs`](https://github.com/srid/rib-sample/blob/master/src/Main.hs) at rib-sample)
|
||||
To test your changes, clone [rib-sample](https://github.com/srid/rib-sample) and run it using your local rib checkout:
|
||||
|
||||
## Getting Started
|
||||
|
||||
The easiest way to get started with [Rib](/) is to [use the
|
||||
template](https://help.github.com/en/articles/creating-a-repository-from-a-template)
|
||||
repository, [**rib-sample**](https://github.com/srid/rib-sample), from Github.
|
||||
|
||||
## Concepts
|
||||
|
||||
### Directory structure
|
||||
|
||||
Let's look at what's in the template repository:
|
||||
|
||||
```shell
|
||||
$ git clone https://github.com/srid/rib-sample.git mysite
|
||||
...
|
||||
$ cd mysite
|
||||
$ ls -F
|
||||
content/ default.nix Main.hs README.md rib-sample.cabal
|
||||
```
|
||||
|
||||
The three key items here are:
|
||||
|
||||
1. `Main.hs`: Haskell source containing the DSL of the HTML/CSS of your site.
|
||||
1. `content/`: The source content (eg: Markdown sources and static files)
|
||||
1. `dest/`: The target directory, excluded from the git repository, will contain
|
||||
_generated_ content (i.e., the HTML files, and copied over static content)
|
||||
|
||||
The template repository comes with a few sample posts under `content/`, and a basic
|
||||
HTML layout and CSS style defined in `Main.hs`.
|
||||
|
||||
### Run the site
|
||||
|
||||
Now let's run them all.
|
||||
|
||||
Clone the sample repository locally, install [Nix](https://nixos.org/nix/) (as
|
||||
described in its README) and run your site as follows:
|
||||
|
||||
```shell
|
||||
nix-shell --run 'ghcid -T ":main serve"'
|
||||
cd ..
|
||||
git clone https://github.com/srid/rib-sample.git
|
||||
cd rib-sample
|
||||
nix-shell --arg rib ../rib --run 'ghcid -T main'
|
||||
```
|
||||
|
||||
(Note that even though the author recommends it Nix is strictly not required; you may
|
||||
simply run `ghcid -T ":main serve"` instead of the above command if you do not wish to
|
||||
use Nix.)
|
||||
|
||||
Running this command gives you a local HTTP server at http://127.0.0.1:8080
|
||||
(serving the generated files) that automatically reloads when either the content
|
||||
(`content/`) or the HTML/CSS/build-actions (`Main.hs`) changes. Hot reload, in other
|
||||
words.
|
||||
|
||||
### How Rib works
|
||||
|
||||
How does the aforementioned nix-shell command work?
|
||||
|
||||
1. `nix-shell` will run the given command in a shell environment with all of our
|
||||
dependencies (notably the Haskell ones including the `rib` library itself)
|
||||
installed.
|
||||
|
||||
1. [`ghcid`](https://github.com/ndmitchell/ghcid) will compile your `Main.hs`
|
||||
and run its `main` function.
|
||||
|
||||
1. `Main.hs:main` in turn calls `Rib.App.run` which takes as argument your custom
|
||||
Shake action that will build the static site.
|
||||
|
||||
1. `Rib.App.run`: this parses the CLI arguments and runs the rib CLI "app" which
|
||||
can be run in one of a few modes --- generating static files, watching the
|
||||
`content/` directory for changes, starting HTTP server for the `dest/` directory.
|
||||
The "serve" subcommand will run the Shake build action passed as argument on
|
||||
every file change and spin up a HTTP server.
|
||||
|
||||
Run that command, and visit http://127.0.0.1:8080 to view your site.
|
||||
|
||||
### Editing workflow
|
||||
|
||||
Now try making some changes to the content, say `content/first-post.md`. You should
|
||||
see it reflected when you refresh the page. Or change the HTML or CSS of your
|
||||
site in `Main.hs`; this will trigger `ghcid` to rebuild the Haskell source and
|
||||
restart the server.
|
||||
|
||||
### What's next?
|
||||
|
||||
Great, by now you should have your static site generator ready and running!
|
||||
|
||||
Rib recommends writing your Shake actions in the style of being
|
||||
[forward-defined](http://hackage.haskell.org/package/shake-0.18.3/docs/Development-Shake-Forward.html)
|
||||
which adds to the simplicity of the entire thing.
|
||||
|
||||
## Examples
|
||||
|
||||
* [rib-sample](https://github.com/srid/rib-sample): Use this to get started with
|
||||
your own site.
|
||||
|
||||
* [zulip-archive](https://github.com/srid/zulip-archive): Zulip chat archive viewer ([running here](https://funprog.srid.ca/)).
|
||||
|
||||
* [open-editions.org](https://github.com/open-editions/open-editions.org) ([running here](https://open-editions.org/)).
|
||||
|
||||
* Rib powers the Zettelkasten system [neuron](https://github.com/srid/neuron#neuron)
|
||||
* Example: [www.srid.ca](https://www.srid.ca/)
|
||||
* Example: [neuron.srid.ca](https://neuron.srid.ca/)
|
||||
* Example: [haskell.srid.ca](https://haskell.srid.ca/)
|
||||
|
@ -1,3 +1,3 @@
|
||||
## Credits
|
||||
|
||||
* `rib.png`: https://www.svgrepo.com/svg/24439/ribs
|
||||
* `rib.svg`: https://www.svgrepo.com/svg/24439/ribs
|
||||
|
78
assets/rib.svg
Normal file
78
assets/rib.svg
Normal file
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<g>
|
||||
<path style="fill:#BDCED4;" d="M160.019,501.801h-27.781c-5.172,0-9.364-4.192-9.364-9.364V19.563c0-5.171,4.192-9.364,9.364-9.364
|
||||
h27.781c5.172,0,9.364,4.192,9.364,9.364v472.874C169.383,497.609,165.191,501.801,160.019,501.801z"/>
|
||||
<path style="fill:#BDCED4;" d="M269.304,501.801h-27.781c-5.171,0-9.364-4.192-9.364-9.364V19.563c0-5.171,4.192-9.364,9.364-9.364
|
||||
h27.781c5.171,0,9.364,4.192,9.364,9.364v472.874C278.668,497.609,274.476,501.801,269.304,501.801z"/>
|
||||
<path style="fill:#BDCED4;" d="M379.759,501.801h-27.781c-5.171,0-9.364-4.192-9.364-9.364V19.563c0-5.171,4.192-9.364,9.364-9.364
|
||||
h27.781c5.171,0,9.364,4.192,9.364,9.364v472.874C389.123,497.609,384.93,501.801,379.759,501.801z"/>
|
||||
</g>
|
||||
<path style="fill:#8C4F39;" d="M365.869,65.797L365.869,65.797c-30.059,0-55.745,24.368-55.745,54.427
|
||||
c0-30.059-24.65-54.427-54.711-54.427l0,0c-30.059,0-54.642,24.368-54.642,54.427c0-30.059-24.583-54.427-54.642-54.427l0,0
|
||||
c-30.059,0-54.427,24.368-54.427,54.427v271.552c0,30.059,24.368,54.427,54.427,54.427l0,0c30.059,0,54.652-24.368,54.652-54.427
|
||||
c0,30.059,24.572,54.427,54.631,54.427l0,0c30.059,0,55.12-24.368,55.12-54.427c0,30.059,25.276,54.427,55.335,54.427l0,0
|
||||
c30.059,0,54.427-24.368,54.427-54.427V120.224C420.296,90.165,395.928,65.797,365.869,65.797z"/>
|
||||
<path d="M399.321,64.949V19.563C399.321,8.775,390.546,0,379.759,0h-27.781c-10.788,0-19.563,8.775-19.563,19.563V64.68
|
||||
c-4.578,2.687-8.87,5.942-12.784,9.73c-3.587,3.47-6.717,7.256-9.366,11.292c-5.409-8.489-12.748-15.641-21.399-20.842V19.563
|
||||
C288.867,8.775,280.092,0,269.304,0h-27.781c-10.787,0-19.563,8.775-19.563,19.563v45.32c-8.545,5.151-15.809,12.208-21.189,20.58
|
||||
c-5.38-8.372-12.644-15.43-21.189-20.58v-45.32C179.582,8.775,170.807,0,160.02,0H132.24c-10.787,0-19.563,8.775-19.563,19.563
|
||||
v45.385c-18.673,11.344-31.173,31.877-31.173,55.276v271.552c0,23.399,12.5,43.933,31.173,55.276v45.385
|
||||
c0,10.787,8.775,19.563,19.563,19.563h27.781c10.787,0,19.563-8.775,19.563-19.563v-45.316c8.549-5.151,15.816-12.21,21.198-20.584
|
||||
c5.378,8.369,12.639,15.426,21.18,20.577v45.323c0,10.787,8.775,19.563,19.563,19.563h27.781c10.788,0,19.563-8.775,19.563-19.563
|
||||
v-45.174c8.763-5.191,16.203-12.354,21.684-20.869c5.521,8.549,13.024,15.735,21.865,20.932v45.111
|
||||
c0,10.787,8.775,19.563,19.563,19.563h27.781c10.787,0,19.563-8.775,19.563-19.563v-45.385
|
||||
c18.673-11.344,31.173-31.877,31.173-55.276V120.224C430.495,96.825,417.995,76.291,399.321,64.949z M352.814,20.398h26.11v36.525
|
||||
c-4.217-0.869-8.584-1.326-13.055-1.326c-4.425,0-8.793,0.445-13.055,1.3L352.814,20.398L352.814,20.398z M242.359,20.398h26.11
|
||||
v36.518c-4.218-0.861-8.584-1.319-13.055-1.319c-4.471,0-8.836,0.459-13.055,1.322V20.398z M133.075,20.398h26.11V56.92
|
||||
c-4.218-0.863-8.584-1.322-13.055-1.322s-8.837,0.457-13.055,1.326V20.398z M159.184,491.602h-26.11v-36.525
|
||||
c4.217,0.869,8.584,1.326,13.055,1.326c4.471,0,8.836-0.459,13.055-1.322V491.602z M268.469,491.602h-26.11v-36.522
|
||||
c4.218,0.863,8.584,1.323,13.055,1.323c4.47,0,8.835-0.451,13.055-1.301V491.602z M378.923,491.602h-26.11V455.11
|
||||
c4.22,0.844,8.586,1.292,13.055,1.292c4.471,0,8.837-0.457,13.055-1.326L378.923,491.602L378.923,491.602z M410.097,391.776
|
||||
c0,24.387-19.841,44.228-44.228,44.228c-24.466,0-45.136-20.254-45.136-44.228c0-5.632-4.566-10.199-10.199-10.199
|
||||
s-10.199,4.567-10.199,10.199c0,24.387-20.152,44.228-44.92,44.228c-24.499,0-44.432-19.841-44.432-44.228
|
||||
c0-0.194-0.018-0.382-0.029-0.573c0.01-0.191,0.029-0.379,0.029-0.573V246.821c0-5.632-4.566-10.199-10.199-10.199
|
||||
c-5.633,0-10.199,4.567-10.199,10.199v143.809c0,0.194,0.018,0.382,0.029,0.573c-0.01,0.191-0.029,0.379-0.029,0.573
|
||||
c0,24.387-19.941,44.228-44.453,44.228c-24.387,0-44.228-19.841-44.228-44.228V120.224c0-24.387,19.841-44.228,44.228-44.228
|
||||
c24.506,0,44.443,19.841,44.443,44.228c0,5.632,4.566,10.199,10.199,10.199c5.633,0,10.199-4.567,10.199-10.199
|
||||
c0-24.387,19.936-44.228,44.443-44.228c24.543,0,44.511,19.841,44.511,44.228c0,0.366,0.021,0.727,0.059,1.083
|
||||
c-0.038,0.356-0.059,0.717-0.059,1.083v50.996c0,5.632,4.566,10.199,10.199,10.199c5.633,0,10.199-4.567,10.199-10.199V122.39
|
||||
c0-0.366-0.021-0.727-0.059-1.083c0.038-0.356,0.059-0.717,0.059-1.083c0-23.974,20.857-44.228,45.546-44.228
|
||||
c24.387,0,44.228,19.841,44.228,44.228v271.552H410.097z"/>
|
||||
<path d="M126.075,159.185c-5.633,0-10.199,4.567-10.199,10.199v223.561c0,5.632,4.566,10.199,10.199,10.199
|
||||
c5.633,0,10.199-4.567,10.199-10.199V169.384C136.275,163.752,131.708,159.185,126.075,159.185z"/>
|
||||
<path d="M126.075,112.367c-5.633,0-10.199,4.567-10.199,10.199v8.193c0,5.632,4.566,10.199,10.199,10.199
|
||||
c5.633,0,10.199-4.567,10.199-10.199v-8.193C136.275,116.933,131.708,112.367,126.075,112.367z"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.0 KiB |
81
guide/2014301.md
Normal file
81
guide/2014301.md
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: How Rib works
|
||||
---
|
||||
|
||||
Although Rib is at its core a Haskell library (and meant to be used as one, rather than as a framework), it provides toolset (based on nix, ghcid, fsnotify, etc.) to make working with static sites pleasant.
|
||||
|
||||
## Directory structure
|
||||
|
||||
Let us clone the template repository, [**rib-sample**](https://github.com/srid/rib-sample), and inspect what's in it:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/srid/rib-sample.git mysite
|
||||
...
|
||||
$ cd mysite
|
||||
$ ls -F
|
||||
content/ default.nix Main.hs README.md rib-sample.cabal
|
||||
```
|
||||
|
||||
The three key items here are:
|
||||
|
||||
1. `Main.hs`: Haskell source containing the DSL of the HTML/CSS of your site.
|
||||
2. `content/`: The source content (eg: Markdown sources and static files)
|
||||
3. `dest/`: The target directory, excluded from the git repository, will contain
|
||||
_generated_ content (i.e., the HTML files, and copied over static content)
|
||||
|
||||
The template repository comes with a few sample posts under `content/`, and a basic
|
||||
HTML layout and CSS style defined in `Main.hs`.
|
||||
|
||||
## Run the site
|
||||
|
||||
Now let's run them all.
|
||||
|
||||
Clone the sample repository locally, install [Nix](https://nixos.org/nix/) (as
|
||||
described in its README) and run your site as follows:
|
||||
|
||||
```bash
|
||||
nix-shell --run 'ghcid -T ":main serve"'
|
||||
```
|
||||
|
||||
Running this command gives you a local HTTP server at <http://127.0.0.1:8080>
|
||||
(serving the generated files) that automatically reloads when either the content
|
||||
(`content/`) or the HTML/CSS/build-actions (`Main.hs`) changes. Hot reload, in other
|
||||
words.
|
||||
|
||||
## How Rib works
|
||||
|
||||
How does the aforementioned nix-shell command work?
|
||||
|
||||
1. `nix-shell` will run the given command in a shell environment with all of our
|
||||
dependencies (notably the Haskell ones including the `rib` library itself)
|
||||
installed.
|
||||
|
||||
2. [`ghcid`](https://github.com/ndmitchell/ghcid) will compile your `Main.hs`
|
||||
and run its `main` function.
|
||||
|
||||
3. `Main.hs:main` in turn calls `Rib.App.run` which takes as argument your custom
|
||||
Shake action that will build the static site.
|
||||
|
||||
4. `Rib.App.run`: this parses the CLI arguments and runs the rib CLI "app" which
|
||||
can be run in one of a few modes --- generating static files, watching the
|
||||
`content/` directory for changes, starting HTTP server for the `dest/` directory.
|
||||
The "serve" subcommand will run the Shake build action passed as argument on
|
||||
every file change and spin up a HTTP server.
|
||||
|
||||
Run that command, and visit <http://127.0.0.1:8080> to view your site.
|
||||
|
||||
## Editing workflow
|
||||
|
||||
Now try making some changes to the content, say `content/first-post.md`. You should
|
||||
see it reflected when you refresh the page. Or change the HTML or CSS of your
|
||||
site in `Main.hs`; this will trigger `ghcid` to rebuild the Haskell source and
|
||||
restart the server.
|
||||
|
||||
## What's next?
|
||||
|
||||
Great, by now you should have your static site generator ready and running!
|
||||
|
||||
Rib recommends writing your Shake actions in the style of being
|
||||
[forward-defined](http://hackage.haskell.org/package/shake-0.18.3/docs/Development-Shake-Forward.html)
|
||||
which adds to the simplicity of the entire thing.
|
||||
|
16
guide/2014302.md
Normal file
16
guide/2014302.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Examples
|
||||
---
|
||||
|
||||
* [rib-sample](https://github.com/srid/rib-sample): Use this to get started with
|
||||
your own site.
|
||||
|
||||
* [zulip-archive](https://github.com/srid/zulip-archive): Zulip chat archive viewer ([running here](https://funprog.srid.ca/)).
|
||||
|
||||
* [open-editions.org](https://github.com/open-editions/open-editions.org) ([running here](https://open-editions.org/)).
|
||||
|
||||
* Rib powers the Zettelkasten system [neuron](https://github.com/srid/neuron#neuron)
|
||||
* Example: [rib.srid.ca](https://rib.srid.ca) - Rib's guide site
|
||||
* Example: [www.srid.ca](https://www.srid.ca/)
|
||||
* Example: [neuron.srid.ca](https://neuron.srid.ca/)
|
||||
* Example: [haskell.srid.ca](https://haskell.srid.ca/)
|
136
guide/index.md
Normal file
136
guide/index.md
Normal file
@ -0,0 +1,136 @@
|
||||
---
|
||||
title: Rib
|
||||
---
|
||||
|
||||
[Rib](https://github.com/srid/rib) is an easily composable Haskell static site generator library based on Shake.
|
||||
|
||||
## Compared to Hakyll
|
||||
|
||||
How does it compare to the popular static site generator Hakyll?
|
||||
|
||||
- Uses the [Shake](https://shakebuild.com/) build system at its core.
|
||||
- Write HTML ([Lucid](https://chrisdone.com/posts/lucid2/)) & CSS ([Clay](http://fvisser.nl/clay/)) in Haskell.
|
||||
- Built-in support for [Pandoc](https://pandoc.org/) and [MMark](https://github.com/mmark-md/mmark).
|
||||
- Remain as simple as possible to use (see example below)
|
||||
- Nix-based environment for reproducibility
|
||||
- `ghcid` and fsnotify for "hot reload"
|
||||
|
||||
## Quick Preview
|
||||
|
||||
Here is how your code may look like if you were to generate your static site
|
||||
using Rib:
|
||||
|
||||
```haskell
|
||||
-- | Route corresponding to each generated static page.
|
||||
--
|
||||
-- The `a` parameter specifies the data (typically Markdown document) used to
|
||||
-- generate the final page text.
|
||||
data Route a where
|
||||
Route_Index :: Route [(Route Pandoc, Pandoc)]
|
||||
Route_Article :: Path Rel File -> Route Pandoc
|
||||
|
||||
-- | The `IsRoute` instance allows us to determine the target .html path for
|
||||
-- each route. This affects what `routeUrl` will return.
|
||||
instance IsRoute Route where
|
||||
routeFile = \case
|
||||
Route_Index ->
|
||||
pure [relfile|index.html|]
|
||||
Route_Article srcPath ->
|
||||
fmap ([reldir|article|] </>) $
|
||||
replaceExtension ".html" srcPath
|
||||
|
||||
-- | Main entry point to our generator.
|
||||
--
|
||||
-- `Rib.run` handles CLI arguments, and takes three parameters here.
|
||||
--
|
||||
-- 1. Directory `content`, from which static files will be read.
|
||||
-- 2. Directory `dest`, under which target files will be generated.
|
||||
-- 3. Shake action to run.
|
||||
--
|
||||
-- In the shake action you would expect to use the utility functions
|
||||
-- provided by Rib to do the actual generation of your static site.
|
||||
main :: IO ()
|
||||
main = withUtf8 $ do
|
||||
Rib.run [reldir|content|] [reldir|dest|] generateSite
|
||||
|
||||
-- | Shake action for generating the static site
|
||||
generateSite :: Action ()
|
||||
generateSite = do
|
||||
-- Copy over the static files
|
||||
Rib.buildStaticFiles [[relfile|static/**|]]
|
||||
let writeHtmlRoute :: Route a -> a -> Action ()
|
||||
writeHtmlRoute r = Rib.writeRoute r . Lucid.renderText . renderPage r
|
||||
-- Build individual sources, generating .html for each.
|
||||
articles <-
|
||||
Rib.forEvery [[relfile|*.md|]] $ \srcPath -> do
|
||||
let r = Route_Article srcPath
|
||||
doc <- Pandoc.parse Pandoc.readMarkdown srcPath
|
||||
writeHtmlRoute r doc
|
||||
pure (r, doc)
|
||||
writeHtmlRoute Route_Index articles
|
||||
|
||||
-- | Define your site HTML here
|
||||
renderPage :: Route a -> a -> Html ()
|
||||
renderPage route val = html_ [lang_ "en"] $ do
|
||||
head_ $ do
|
||||
meta_ [httpEquiv_ "Content-Type", content_ "text/html; charset=utf-8"]
|
||||
title_ routeTitle
|
||||
style_ [type_ "text/css"] $ C.render pageStyle
|
||||
body_ $ do
|
||||
div_ [class_ "header"] $
|
||||
a_ [href_ "/"] "Back to Home"
|
||||
h1_ routeTitle
|
||||
case route of
|
||||
Route_Index ->
|
||||
div_ $ forM_ val $ \(r, src) ->
|
||||
li_ [class_ "pages"] $ do
|
||||
let meta = getMeta src
|
||||
b_ $ a_ [href_ (Rib.routeUrl r)] $ toHtml $ title meta
|
||||
renderMarkdown `mapM_` description meta
|
||||
Route_Article _ ->
|
||||
article_ $
|
||||
Pandoc.render val
|
||||
where
|
||||
routeTitle :: Html ()
|
||||
routeTitle = case route of
|
||||
Route_Index -> "Rib sample site"
|
||||
Route_Article _ -> toHtml $ title $ getMeta val
|
||||
renderMarkdown :: Text -> Html ()
|
||||
renderMarkdown =
|
||||
Pandoc.render . Pandoc.parsePure Pandoc.readMarkdown
|
||||
|
||||
-- | Define your site CSS here
|
||||
pageStyle :: Css
|
||||
pageStyle = C.body ? do
|
||||
C.margin (em 4) (pc 20) (em 1) (pc 20)
|
||||
".header" ? do
|
||||
C.marginBottom $ em 2
|
||||
"li.pages" ? do
|
||||
C.listStyleType C.none
|
||||
C.marginTop $ em 1
|
||||
"b" ? C.fontSize (em 1.2)
|
||||
"p" ? sym C.margin (px 0)
|
||||
|
||||
-- | Metadata in our markdown sources
|
||||
data SrcMeta
|
||||
= SrcMeta
|
||||
{ title :: Text,
|
||||
-- | Description is optional, hence `Maybe`
|
||||
description :: Maybe Text
|
||||
}
|
||||
deriving (Show, Eq, Generic, FromJSON)
|
||||
```
|
||||
|
||||
(View full [`Main.hs`](https://github.com/srid/rib-sample/blob/master/src/Main.hs) at rib-sample)
|
||||
|
||||
## Getting Started
|
||||
|
||||
The easiest way to get started with [Rib](/) is to [use the
|
||||
template](https://help.github.com/en/articles/creating-a-repository-from-a-template)
|
||||
repository, [**rib-sample**](https://github.com/srid/rib-sample), from Github.
|
||||
|
||||
## Next
|
||||
|
||||
* [2014301](z://concepts)
|
||||
* [2014302](z://examples)
|
||||
|
9
guide/neuron.dhall
Normal file
9
guide/neuron.dhall
Normal file
@ -0,0 +1,9 @@
|
||||
{ siteTitle =
|
||||
"Rib"
|
||||
, siteBaseUrl =
|
||||
Some "https://rib.srid.ca"
|
||||
, editUrl =
|
||||
Some "https://github.com/srid/rib/edit/master/guide/"
|
||||
, minVersion =
|
||||
"0.2"
|
||||
}
|
@ -10,7 +10,7 @@ bug-reports: https://github.com/srid/rib/issues
|
||||
synopsis:
|
||||
Static site generator using Shake
|
||||
description:
|
||||
Haskell static site generator that aims to reuse existing libraries instead of reinventing the wheel
|
||||
Easily composable Haskell static site generator library based on Shake.
|
||||
category: Web
|
||||
build-type: Simple
|
||||
extra-source-files:
|
||||
|
Loading…
Reference in New Issue
Block a user