on 91e89d2 help sign in
.circleci/config.ymldeleted−19
since splitsnapshots
unifiedsplit
@@ -1,19 +0,0 @@
1−version: 2
2−jobs:
3− build:
4− docker:
5− - image: 'fpco/stack-build:latest'
6− steps:
7− - checkout
8− - restore_cache:
9− key: 'v3-hakyll-{{ arch }}-{{ .Branch }}'
10− - run:
11− # We set jobs to 1 here because that prevents Out-Of-Memory exceptions
12− # while compiling dependencies.
13− name: 'Install dependencies'
14− command: '.circleci/tickle.sh stack build --test --copy-bins --jobs=1'
15− - save_cache:
16− key: 'v3-hakyll-{{ arch }}-{{ .Branch }}-{{ .Revision }}'
17− paths:
18− - '~/.stack-work'
19− - '~/.stack'
.circleci/tickle.shdeleted−24
@@ -1,24 +0,0 @@
1−#!/bin/bash
2−set -o nounset -o errexit -o pipefail
3−
4−function tickle() {
5− while [ true ]; do
6− echo "[$(date +%H:%M:%S)] Tickling..."
7− sleep 60
8− done
9−}
10−
11−echo "Forking tickle process..."
12−tickle &
13−TICKLE_PID=$!
14−
15−echo "Forking build process..."
16−eval $@ &
17−BUILD_PID=$!
18−
19−echo "Waiting for build thread ($BUILD_PID)..."
20−wait $BUILD_PID
21−
22−echo "Killing tickle thread ($TICKLE_PID)..."
23−kill $TICKLE_PID
24−echo "All done!"
.travis.ymlnew file+20
@@ -0,0 +1,20 @@
1+language: haskell
2+ghc: '7.10'
3+branches:
4+ only:
5+ - master
6+cache:
7+ directories:
8+ - $HOME/.stack
9+before_install:
10+ - echo "override before_install"
11+install:
12+ - wget https://github.com/commercialhaskell/stack/releases/download/v1.0.0/stack-1.0.0-linux-x86_64.tar.gz -O stack.gz
13+ - tar xvf stack.gz
14+ - chmod +x stack-1.0.0-linux-x86_64/stack
15+ - stack-1.0.0-linux-x86_64/stack setup
16+ - stack-1.0.0-linux-x86_64/stack build
17+before_script:
18+ - echo "override before_script"
19+script:
20+ - stack-1.0.0-linux-x86_64/stack test
CHANGELOG.md−142
@@ -4,148 +4,6 @@ title: Releases
4
4
5# Releases
5# Releases
6
6
7−## Hakyll 4.13.0.0 (2019-08-30)
8−
9−- Improved documentation in many places (contribution by Bergi)
10−- Significantly improve error messages when reading and applying templates
11− (contribution by Bergi)
12− * `empty` and `fail` for `Compiler` now fail without or with a message,
13− allowing for much better debug output
14− * `renderFeed`, `renderRssWithTemplates` and `renderAtomWithTemplates` now
15− take `Template` rather than `String` arguments
16−- Add option to specify date in directory structure,e.g.
17− `posts/2019/05/10/tomorrow.md` (contribution by Taeer Bar-Ya)
18−- Bump QuickCheck to 2.13
19−
20−## Hakyll 4.12.5.2 (2019-05-09)
21−
22−- Bump pandoc to 2.7
23−- Add `srcset` to the list of URL attributes (contribution by c50a326)
24−- Expose `getCategory` in `Hakyll.Web.Tags` (contribution by Ng Wei En)
25−- Fix issue where `published` overwrites the user's context (contribution by
26− ncaq)
27−
28−## Hakyll 4.12.5.1 (2019-02-03)
29−
30−- Bump pandoc to 2.6
31−- Bump pandoc-citeproc to 0.16
32−
33−## Hakyll 4.12.5.0 (2019-01-12)
34−
35−- Update dependencies (contribution by Hexirp):
36− * Bump containers to 0.6
37− * Bump yaml to 0.11
38− * Bump pandoc to 2.5
39− * Bump pandoc-citeproc to 0.15
40− * Bump tasty to 1.2
41−- Correct assertion in unixFilterError test
42− (contribution by Jim McStanton)
43−- Add renderRssWithTemplates, renderAtomWithTemplates
44− (contribution by Abhinav Sarkar)
45−- Speed up hashing in cache (contribution by 0xd34df00d)
46−- Update type of fromFilePath to use FilePath instead of String
47− (contribution by Jim McStanton)
48−- Drop extension when parsing dates in filepaths (contribution by
49− Gabriel Aumala)
50−
51−## Hakyll 4.12.4.0 (2018-08-13)
52−
53−- Bump yaml to 0.10
54−- Bump file-embed to 0.0.11
55−- Bump QuickCheck to 2.12
56−- Use makeRelativeToProject with embedFile for stack ghci (contribution by
57− Michael Sloan)
58−
59−## Hakyll 4.12.3.0 (2018-05-29)
60−
61−- Bump tasty to 1.1
62−- Bump fsnotify to 0.3
63−
64−## Hakyll 4.12.2.0
65−
66−- Bump pandoc to 2.2
67−- Fix path resolution in Pandoc.Biblio (contribution by knih)
68−
69−## Hakyll 4.12.1.0
70−
71−- Fix hakyll-init on older GHC versions
72−- Make the Pandoc dependency optional
73−
74−## Hakyll 4.12.0.1
75−
76−- Bump resourcet to 1.2 in test section
77−
78−## Hakyll 4.12.0.0
79−
80−- Add Semigroup instances for existing Monoids (contribution by
81− Christian Barcenas)
82−- Fix issue with CPP and comment containing `/*`
83−- Add `withTagList` (contribution by Oleg Grenrus)
84−- Improve CSS compression (contribution by Bergi)
85−- Bump pandoc-citeproc to 0.14
86−- Bump resourcet to 1.2
87−- Bump time to 1.9
88−- Bump http-types to 0.12
89−- Bump http-conduit to 2.3
90−- Bump tasty-quickcheck to 0.10
91−
92−## Hakyll 4.11.0.0
93−
94−- Bump binary to 0.9
95−- Bump pandoc to 2.1
96−- Bump pandoc-citeproc to 0.13
97−- Bump http-types to 0.11
98−- Bump QuickCheck to 2.11
99−- Bump tasty to 1.0
100−- Bump tasty-hunit to 0.10
101−- Remove system-filepath dependency
102−- Embed feed templates rather than using data-files (contribution by Roman
103− Kuznetsov)
104−- Fix pthread link error on GHC-8.2.2 (contribution by Shinya Yamaguchi)
105−- Extend capture with Regex handling (contribution by frederik-h)
106−
107−## Hakyll 4.10.0.0
108−
109−- Bump Pandoc to 2.0 (contribution by Vaibhav Sagar)
110−- Fix compression of calc() in CSS (contribution by Krzysztof Jurewicz)
111−- Make unixFilter output stderr when failing (contribution by Nick Boultbee)
112−- Export Check type from `Hakyll.Commands` (contribution by Futtetennista)
113−- Add overwritten files check to `hakyll-init` (contribution by Ilya Murzinov)
114−- Expose & document `hakyllWithExitCodeAndArgs`, `Options`, and `Command`
115− (contribution by Michael Walker)
116−- Add check for non-overlapping redirects (contribution by gwern)
117−- Fix early exit when calling check as a library
118−
119−## Hakyll 4.9.8.0
120−
121−- Bump pandoc-citeproc to 0.10.5
122−- Bump optparse-applicative to 0.14
123−- Bump QuickCheck to 2.10
124−- Bump tasty-quickcheck to 0.9
125−- Restructure .cabal to avoid redundant compilation (contribution by
126− Christopher League)
127−
128−## Hakyll 4.9.7.0
129−
130−- Fix compilation trouble with `Options.Applicative`
131−- Some small CSS compression improvements (contribution by Nicole Rauch)
132−
133−## Hakyll 4.9.6.0
134−
135−- Tighten dependency on `pandoc-citeproc` (contribution by Mikhail Glushenkov)
136−- Enable using a custom parser for command line arguments (contribution by
137− Alberto)
138−- Update examples to semantic HTML (contribution by Elie Génard)
139−- Better error for `cached` on non-existing file
140−- Provide an `$allPages$` key when doing pagination
141−- Preserve file metadata in `copyFileCompiler` (contribution by frederik-h)
142−
143−## Hakyll 4.9.5.1
144−
145−- Bump blaze-html dependency to 0.9
146−- Bump blaze-markup dependency to 0.8
147−- Bump process dependency to 1.5
148−
149## Hakyll 4.9.5.0
7## Hakyll 4.9.5.0
150
8
151- Fix compilation issue with `Hakyll.Check` if `checkExternal` is disabled
9- Fix compilation issue with `Hakyll.Check` if `checkExternal` is disabled
CODE_OF_CONDUCT.mddeleted−45
@@ -1,45 +0,0 @@
1−# Contributor Covenant Code of Conduct
2−
3−## Our Pledge
4−
5−In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6−
7−## Our Standards
8−
9−Examples of behavior that contributes to creating a positive environment include:
10−* Using welcoming and inclusive language
11−* Being respectful of differing viewpoints and experiences
12−* Gracefully accepting constructive criticism
13−* Focusing on what is best for the community
14−* Showing empathy towards other community members
15−
16−Examples of unacceptable behavior by participants include:
17−
18−* The use of sexualized language or imagery and unwelcome sexual attention or advances
19−* Trolling, insulting/derogatory comments, and personal or political attacks
20−* Public or private harassment
21−* Publishing others' private information, such as a physical or electronic address, without explicit permission
22−* Other conduct which could reasonably be considered inappropriate in a professional setting
23−
24−## Our Responsibilities
25−
26−Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
27−
28−Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
29−
30−## Scope
31−
32−This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
33−
34−## Enforcement
35−
36−Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by [contacting the project team at m@jaspervdj.be](mailto:m@jaspervdj.be). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
37−
38−Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
39−
40−## Attribution
41−
42−This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
43−
44−[homepage]: http://contributor-covenant.org
45−[version]: http://contributor-covenant.org/version/1/4/
LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright (c) 2009 - 2017, Jasper Van der Jeugt
1+Copyright (c) 2009, Jasper Van der Jeugt
2 
2 
3All rights reserved.
3All rights reserved.
4 
4 
Makefile+6−6
@@ -1,9 +1,9 @@
1−PACKAGE="$(shell stack list-dependencies --separator='-' | grep hakyll)"
2−LOCAL_DOC_ROOT="$(shell stack path --local-doc-root)"
3−
4# Generate the docs and copy them to the website dir
1# Generate the docs and copy them to the website dir
5haddock:
2haddock:
6− stack build --haddock --no-haddock-deps
3+ cabal haddock --hyperlink-source
7− rsync -r "$(LOCAL_DOC_ROOT)/$(PACKAGE)/" web/reference/
4+ rm -rf web/reference/
5+ cp -r dist/doc/html/hakyll/ web/reference/
8
6
9−.PHONY: haddock
7+# Run the tests
8+test:
9+ runghc -isrc -itests tests/TestSuite.hs
README.markdown+1−1
@@ -1,6 +1,6 @@
1# hakyll
1# hakyll
2
2
3−[![Build Status](https://img.shields.io/circleci/project/github/jaspervdj/hakyll.svg)](https://circleci.com/gh/jaspervdj/hakyll)
3+[![Build Status](https://img.shields.io/travis/jaspervdj/hakyll.svg)](http://travis-ci.org/jaspervdj/hakyll)
4
4
5Hakyll is a static site generator library in Haskell. More information
5Hakyll is a static site generator library in Haskell. More information
6(including a tutorial) can be found on
6(including a tutorial) can be found on
data/example/css/default.css+37−122
@@ -1,141 +1,56 @@
1−html {
1+body {
2+ color: black;
2− font-size: 62.5%;
3+ font-size: 16px;
4+ margin: 0px auto 0px auto;
5+ width: 600px;
3}
6}
4
7
5−body {
8+div#header {
6− font-size: 1.6rem;
9+ border-bottom: 2px solid black;
7− color: #000;
10+ margin-bottom: 30px;
11+ padding: 12px 0px 12px 0px;
8}
12}
9
13
10−header {
14+div#logo a {
11− border-bottom: 0.2rem solid #000;
15+ color: black;
16+ float: left;
17+ font-size: 18px;
18+ font-weight: bold;
19+ text-decoration: none;
12}
20}
13
21
14−nav {
22+div#header #navigation {
15− text-align: right;
23+ text-align: right;
16}
24}
17
25
18−nav a {
26+div#header #navigation a {
27+ color: black;
19− font-size: 1.8rem;
28+ font-size: 18px;
20− font-weight: bold;
29+ font-weight: bold;
21− color: black;
30+ margin-left: 12px;
22− text-decoration: none;
31+ text-decoration: none;
23− text-transform: uppercase;
32+ text-transform: uppercase;
24}
33}
25
34
26−footer {
35+div#footer {
27− margin-top: 3rem;
28− padding: 1.2rem 0;
29− border-top: 0.2rem solid #000;
36+ border-top: solid 2px black;
30− font-size: 1.2rem;
31− color: #555;
37+ color: #555;
38+ font-size: 12px;
39+ margin-top: 30px;
40+ padding: 12px 0px 12px 0px;
41+ text-align: right;
32}
42}
33
43
34h1 {
44h1 {
35− font-size: 2.4rem;
45+ font-size: 24px;
36}
46}
37
47
38h2 {
48h2 {
39− font-size: 2rem;
40−}
41−
42−article .header {
43− font-size: 1.4rem;
44− font-style: italic;
45− color: #555;
46−}
47−
48−.logo a {
49− font-weight: bold;
50− color: #000;
51− text-decoration: none;
52−}
53−
54−@media (max-width: 319px) {
55− body {
56− width: 90%;
57− margin: 0;
58− padding: 0 5%;
59− }
60− header {
61− margin: 4.2rem 0;
62− }
63− nav {
64− margin: 0 auto 3rem;
65− text-align: center;
66− }
67− footer {
68− text-align: center;
69− }
70− .logo {
71− text-align: center;
72− margin: 1rem auto 3rem;
73− }
74− .logo a {
75− font-size: 2.4rem;
49+ font-size: 20px;
76− }
77− nav a {
78− display: block;
79− line-height: 1.6;
80− }
81−}
82−
83−@media (min-width: 320px) {
84− body {
85− width: 90%;
86− margin: 0;
87− padding: 0 5%;
88− }
89− header {
90− margin: 4.2rem 0;
91− }
92− nav {
93− margin: 0 auto 3rem;
94− text-align: center;
95− }
96− footer {
97− text-align: center;
98− }
99− .logo {
100− text-align: center;
101− margin: 1rem auto 3rem;
102− }
103− .logo a {
104− font-size: 2.4rem;
105− }
106− nav a {
107− display: inline;
108− margin: 0 0.6rem;
109− }
110}
50}
111
51
112−@media (min-width: 640px) {
52+div.info {
113− body {
53+ color: #555;
114− width: 60rem;
115− margin: 0 auto;
116− padding: 0;
117− }
118− header {
119− margin: 0 0 3rem;
120− padding: 1.2rem 0;
121− }
122− nav {
123− margin: 0;
124− text-align: right;
125− }
126− nav a {
127− margin: 0 0 0 1.2rem;
128− display: inline;
129− }
130− footer {
131− text-align: right;
132− }
133− .logo {
134− margin: 0;
135− text-align: left;
136− }
137− .logo a {
138− float: left;
139− font-size: 1.8rem;
54+ font-size: 14px;
140− }
55+ font-style: italic;
141}
56}
data/example/templates/default.html+9−9
@@ -8,26 +8,26 @@
8 <link rel="stylesheet" href="/css/default.css" />
8 <link rel="stylesheet" href="/css/default.css" />
9 </head>
9 </head>
10 <body>
10 <body>
11− <header>
11+ <div id="header">
12− <div class="logo">
12+ <div id="logo">
13 <a href="/">My Hakyll Blog</a>
13 <a href="/">My Hakyll Blog</a>
14 </div>
14 </div>
15− <nav>
15+ <div id="navigation">
16 <a href="/">Home</a>
16 <a href="/">Home</a>
17 <a href="/about.html">About</a>
17 <a href="/about.html">About</a>
18 <a href="/contact.html">Contact</a>
18 <a href="/contact.html">Contact</a>
19 <a href="/archive.html">Archive</a>
19 <a href="/archive.html">Archive</a>
20− </nav>
20+ </div>
21− </header>
21+ </div>
22
22
23− <main role="main">
23+ <div id="content">
24 <h1>$title$</h1>
24 <h1>$title$</h1>
25 $body$
25 $body$
26− </main>
26+ </div>
27
27
28− <footer>
28+ <div id="footer">
29 Site proudly generated by
29 Site proudly generated by
30 <a href="http://jaspervdj.be/hakyll">Hakyll</a>
30 <a href="http://jaspervdj.be/hakyll">Hakyll</a>
31− </footer>
31+ </div>
32 </body>
32 </body>
33</html>
33</html>
data/example/templates/post.html+8−11
@@ -1,11 +1,8 @@
1−<article>
1+<div class="info">
2− <section class="header">
3− Posted on $date$
2+ Posted on $date$
4− $if(author)$
3+ $if(author)$
5− by $author$
4+ by $author$
6− $endif$
5+ $endif$
7− </section>
6+</div>
8− <section>
7+
9− $body$
8+$body$
10− </section>
11−</article>
hakyll.cabal+125−128
@@ -1,5 +1,5 @@
1Name: hakyll
1Name: hakyll
2−Version: 4.13.0.0
2+Version: 4.9.5.0
3
3
4Synopsis: A static website compiler library
4Synopsis: A static website compiler library
5Description:
5Description:
@@ -37,7 +37,7 @@ License: BSD3
37License-File: LICENSE
37License-File: LICENSE
38Category: Web
38Category: Web
39
39
40−Cabal-Version: >= 1.10
40+Cabal-Version: >= 1.8
41Build-Type: Simple
41Build-Type: Simple
42Data-Dir: data
42Data-Dir: data
43
43
@@ -56,6 +56,10 @@ Data-files:
56 example/index.html
56 example/index.html
57 example/about.rst
57 example/about.rst
58 example/contact.markdown
58 example/contact.markdown
59+ templates/atom-item.xml
60+ templates/atom.xml
61+ templates/rss-item.xml
62+ templates/rss.xml
59
63
60Extra-source-files:
64Extra-source-files:
61 CHANGELOG.md
65 CHANGELOG.md
@@ -68,16 +72,11 @@ Extra-source-files:
68 tests/data/partial.html
72 tests/data/partial.html
69 tests/data/partial.html.out
73 tests/data/partial.html.out
70 tests/data/posts/2010-08-26-birthday.md
74 tests/data/posts/2010-08-26-birthday.md
71− tests/data/posts/2018-09-26.md
72 tests/data/russian.md
75 tests/data/russian.md
73 tests/data/strip.html
76 tests/data/strip.html
74 tests/data/strip.html.out
77 tests/data/strip.html.out
75 tests/data/template.html
78 tests/data/template.html
76 tests/data/template.html.out
79 tests/data/template.html.out
77− data/templates/atom-item.xml
78− data/templates/atom.xml
79− data/templates/rss-item.xml
80− data/templates/rss.xml
81
80
82Source-Repository head
81Source-Repository head
83 Type: git
82 Type: git
@@ -95,43 +94,24 @@ Flag checkExternal
95 Description: Include external link checking
94 Description: Include external link checking
96 Default: True
95 Default: True
97
96
98−Flag buildWebsite
99− Description: Build the hakyll website
100− Default: False
101− Manual: True
102−
103−Flag usePandoc
104− Description: Include Pandoc support
105− Default: True
106− Manual: True
107−
108Library
97Library
109− Ghc-Options: -Wall
98+ Ghc-Options: -Wall
110− Hs-Source-Dirs: lib
99+ Hs-Source-Dirs: src
111− Default-language: Haskell2010
112
100
113 Exposed-Modules:
101 Exposed-Modules:
114 Hakyll
102 Hakyll
115 Hakyll.Commands
103 Hakyll.Commands
116 Hakyll.Core.Compiler
104 Hakyll.Core.Compiler
117− Hakyll.Core.Compiler.Internal
118 Hakyll.Core.Configuration
105 Hakyll.Core.Configuration
119 Hakyll.Core.Dependencies
106 Hakyll.Core.Dependencies
120 Hakyll.Core.File
107 Hakyll.Core.File
121 Hakyll.Core.Identifier
108 Hakyll.Core.Identifier
122 Hakyll.Core.Identifier.Pattern
109 Hakyll.Core.Identifier.Pattern
123 Hakyll.Core.Item
110 Hakyll.Core.Item
124− Hakyll.Core.Logger
125 Hakyll.Core.Metadata
111 Hakyll.Core.Metadata
126− Hakyll.Core.Provider
127− Hakyll.Core.Provider.Metadata
128 Hakyll.Core.Routes
112 Hakyll.Core.Routes
129 Hakyll.Core.Rules
113 Hakyll.Core.Rules
130− Hakyll.Core.Rules.Internal
131− Hakyll.Core.Runtime
132− Hakyll.Core.Store
133 Hakyll.Core.UnixFilter
114 Hakyll.Core.UnixFilter
134− Hakyll.Core.Util.File
135 Hakyll.Core.Util.String
115 Hakyll.Core.Util.String
136 Hakyll.Core.Writable
116 Hakyll.Core.Writable
137 Hakyll.Main
117 Hakyll.Main
@@ -139,9 +119,12 @@ Library
139 Hakyll.Web.Feed
119 Hakyll.Web.Feed
140 Hakyll.Web.Html
120 Hakyll.Web.Html
141 Hakyll.Web.Html.RelativizeUrls
121 Hakyll.Web.Html.RelativizeUrls
142− Hakyll.Web.Paginate
122+ Hakyll.Web.Pandoc
123+ Hakyll.Web.Pandoc.Biblio
124+ Hakyll.Web.Pandoc.FileType
143 Hakyll.Web.Redirect
125 Hakyll.Web.Redirect
144 Hakyll.Web.Tags
126 Hakyll.Web.Tags
127+ Hakyll.Web.Paginate
145 Hakyll.Web.Template
128 Hakyll.Web.Template
146 Hakyll.Web.Template.Context
129 Hakyll.Web.Template.Context
147 Hakyll.Web.Template.Internal
130 Hakyll.Web.Template.Internal
@@ -153,53 +136,64 @@ Library
153 Data.List.Extended
136 Data.List.Extended
154 Data.Yaml.Extended
137 Data.Yaml.Extended
155 Hakyll.Check
138 Hakyll.Check
139+ Hakyll.Core.Compiler.Internal
156 Hakyll.Core.Compiler.Require
140 Hakyll.Core.Compiler.Require
157− Hakyll.Core.Identifier.Pattern.Internal
158 Hakyll.Core.Item.SomeItem
141 Hakyll.Core.Item.SomeItem
142+ Hakyll.Core.Logger
143+ Hakyll.Core.Provider
159 Hakyll.Core.Provider.Internal
144 Hakyll.Core.Provider.Internal
145+ Hakyll.Core.Provider.Metadata
160 Hakyll.Core.Provider.MetadataCache
146 Hakyll.Core.Provider.MetadataCache
147+ Hakyll.Core.Rules.Internal
148+ Hakyll.Core.Runtime
149+ Hakyll.Core.Store
150+ Hakyll.Core.Util.File
161 Hakyll.Core.Util.Parser
151 Hakyll.Core.Util.Parser
152+ Hakyll.Web.Pandoc.Binary
162 Paths_hakyll
153 Paths_hakyll
163
154
164 Build-Depends:
155 Build-Depends:
165− base >= 4.8 && < 5,
156+ base >= 4.8 && < 5,
166− binary >= 0.5 && < 0.10,
157+ binary >= 0.5 && < 0.9,
167− blaze-html >= 0.5 && < 0.10,
158+ blaze-html >= 0.5 && < 0.9,
168− blaze-markup >= 0.5.1 && < 0.9,
159+ blaze-markup >= 0.5.1 && < 0.8,
169− bytestring >= 0.9 && < 0.11,
160+ bytestring >= 0.9 && < 0.11,
170− containers >= 0.3 && < 0.7,
161+ containers >= 0.3 && < 0.6,
171− cryptohash >= 0.7 && < 0.12,
162+ cryptohash >= 0.7 && < 0.12,
172− data-default >= 0.4 && < 0.8,
163+ data-default >= 0.4 && < 0.8,
173− deepseq >= 1.3 && < 1.5,
164+ deepseq >= 1.3 && < 1.5,
174− directory >= 1.0 && < 1.4,
165+ directory >= 1.0 && < 1.4,
175− file-embed >= 0.0.10.1 && < 0.0.12,
176− filepath >= 1.0 && < 1.5,
166+ filepath >= 1.0 && < 1.5,
177− lrucache >= 1.1.1 && < 1.3,
167+ lrucache >= 1.1.1 && < 1.3,
178− mtl >= 1 && < 2.3,
168+ mtl >= 1 && < 2.3,
179− network-uri >= 2.6 && < 2.7,
169+ network >= 2.6 && < 2.7,
180− optparse-applicative >= 0.12 && < 0.15,
170+ network-uri >= 2.6 && < 2.7,
171+ pandoc >= 1.14 && < 1.20,
172+ pandoc-citeproc >= 0.4 && < 0.11,
181− parsec >= 3.0 && < 3.2,
173+ parsec >= 3.0 && < 3.2,
182− process >= 1.6 && < 1.7,
174+ process >= 1.0 && < 1.5,
183− random >= 1.0 && < 1.2,
175+ random >= 1.0 && < 1.2,
176+ regex-base >= 0.93 && < 0.94,
184− regex-tdfa >= 1.1 && < 1.3,
177+ regex-tdfa >= 1.1 && < 1.3,
185− resourcet >= 1.1 && < 1.3,
178+ resourcet >= 1.1 && < 1.2,
186− scientific >= 0.3.4 && < 0.4,
179+ scientific >= 0.3.4 && < 0.4,
187− tagsoup >= 0.13.1 && < 0.15,
180+ tagsoup >= 0.13.1 && < 0.15,
188− template-haskell >= 2.14 && < 2.15,
189− text >= 0.11 && < 1.3,
181+ text >= 0.11 && < 1.3,
190− time >= 1.8 && < 1.10,
182+ time >= 1.4 && < 1.8,
191− time-locale-compat >= 0.1 && < 0.2,
183+ time-locale-compat >= 0.1 && < 0.2,
192− unordered-containers >= 0.2 && < 0.3,
184+ unordered-containers >= 0.2 && < 0.3,
193− vector >= 0.11 && < 0.13,
185+ vector >= 0.11 && < 0.13,
194− yaml >= 0.8.11 && < 0.12
186+ yaml >= 0.8.11 && < 0.9,
187+ optparse-applicative >= 0.12 && < 0.14
195
188
196 If flag(previewServer)
189 If flag(previewServer)
197 Build-depends:
190 Build-depends:
198 wai >= 3.2 && < 3.3,
191 wai >= 3.2 && < 3.3,
199 warp >= 3.2 && < 3.3,
192 warp >= 3.2 && < 3.3,
200 wai-app-static >= 3.1 && < 3.2,
193 wai-app-static >= 3.1 && < 3.2,
201− http-types >= 0.9 && < 0.13,
194+ http-types >= 0.9 && < 0.10,
202− fsnotify >= 0.2 && < 0.4
195+ fsnotify >= 0.2 && < 0.3,
196+ system-filepath >= 0.4.6 && <= 0.5
203 Cpp-options:
197 Cpp-options:
204 -DPREVIEW_SERVER
198 -DPREVIEW_SERVER
205 Other-modules:
199 Other-modules:
@@ -208,7 +202,8 @@ Library
208
202
209 If flag(watchServer)
203 If flag(watchServer)
210 Build-depends:
204 Build-depends:
211− fsnotify >= 0.2 && < 0.4
205+ fsnotify >= 0.2 && < 0.3,
206+ system-filepath >= 0.4.6 && <= 0.5
212 Cpp-options:
207 Cpp-options:
213 -DWATCH_SERVER
208 -DWATCH_SERVER
214 Other-modules:
209 Other-modules:
@@ -216,31 +211,16 @@ Library
216
211
217 If flag(checkExternal)
212 If flag(checkExternal)
218 Build-depends:
213 Build-depends:
219− http-conduit >= 2.2 && < 2.4,
214+ http-conduit >= 2.2 && < 2.3,
220− http-types >= 0.7 && < 0.13
215+ http-types >= 0.7 && < 0.10
221 Cpp-options:
216 Cpp-options:
222 -DCHECK_EXTERNAL
217 -DCHECK_EXTERNAL
223
218
224− If flag(usePandoc)
225− Exposed-Modules:
226− Hakyll.Web.Pandoc
227− Hakyll.Web.Pandoc.Biblio
228− Hakyll.Web.Pandoc.FileType
229− Other-Modules:
230− Hakyll.Web.Pandoc.Binary
231− Build-Depends:
232− pandoc >= 2.0.5 && < 2.8,
233− pandoc-citeproc >= 0.14 && < 0.17
234− Cpp-options:
235− -DUSE_PANDOC
236−
237Test-suite hakyll-tests
219Test-suite hakyll-tests
238− Type: exitcode-stdio-1.0
220+ Type: exitcode-stdio-1.0
239− Hs-source-dirs: tests
221+ Hs-source-dirs: src tests
240− Main-is: TestSuite.hs
222+ Main-is: TestSuite.hs
241− Ghc-options: -Wall -threaded
223+ Ghc-options: -Wall
242− Default-language: Haskell2010
243−
244 Other-modules:
224 Other-modules:
245 Hakyll.Core.Dependencies.Tests
225 Hakyll.Core.Dependencies.Tests
246 Hakyll.Core.Identifier.Tests
226 Hakyll.Core.Identifier.Tests
@@ -255,73 +235,90 @@ Test-suite hakyll-tests
255 Hakyll.Web.CompressCss.Tests
235 Hakyll.Web.CompressCss.Tests
256 Hakyll.Web.Html.RelativizeUrls.Tests
236 Hakyll.Web.Html.RelativizeUrls.Tests
257 Hakyll.Web.Html.Tests
237 Hakyll.Web.Html.Tests
258− Hakyll.Web.Tags.Tests
238+ Hakyll.Web.Pandoc.FileType.Tests
259 Hakyll.Web.Template.Context.Tests
239 Hakyll.Web.Template.Context.Tests
260 Hakyll.Web.Template.Tests
240 Hakyll.Web.Template.Tests
261 TestSuite.Util
241 TestSuite.Util
262
242
263 Build-Depends:
243 Build-Depends:
264− hakyll,
265− QuickCheck >= 2.8 && < 2.14,
244+ QuickCheck >= 2.8 && < 2.10,
266− tasty >= 0.11 && < 1.3,
245+ tasty >= 0.11 && < 0.12,
267− tasty-hunit >= 0.9 && < 0.11,
246+ tasty-hunit >= 0.9 && < 0.10,
268− tasty-quickcheck >= 0.8 && < 0.11,
247+ tasty-quickcheck >= 0.8 && < 0.9,
269 -- Copy pasted from hakyll dependencies:
248 -- Copy pasted from hakyll dependencies:
270− base >= 4.8 && < 5,
249+ base >= 4.8 && < 5,
250+ binary >= 0.5 && < 0.9,
251+ blaze-html >= 0.5 && < 0.9,
252+ blaze-markup >= 0.5.1 && < 0.8,
271− bytestring >= 0.9 && < 0.11,
253+ bytestring >= 0.9 && < 0.11,
272− containers >= 0.3 && < 0.7,
254+ containers >= 0.3 && < 0.6,
255+ cryptohash >= 0.7 && < 0.12,
256+ data-default >= 0.4 && < 0.8,
257+ deepseq >= 1.3 && < 1.5,
258+ directory >= 1.0 && < 1.4,
273− filepath >= 1.0 && < 1.5,
259+ filepath >= 1.0 && < 1.5,
260+ lrucache >= 1.1.1 && < 1.3,
261+ mtl >= 1 && < 2.3,
262+ network >= 2.6 && < 2.7,
263+ network-uri >= 2.6 && < 2.7,
264+ pandoc >= 1.14 && < 1.20,
265+ pandoc-citeproc >= 0.4 && < 0.11,
266+ parsec >= 3.0 && < 3.2,
267+ process >= 1.0 && < 1.5,
268+ random >= 1.0 && < 1.2,
269+ regex-base >= 0.93 && < 0.94,
270+ regex-tdfa >= 1.1 && < 1.3,
271+ resourcet >= 1.1 && < 1.2,
272+ scientific >= 0.3.4 && < 0.4,
273+ tagsoup >= 0.13.1 && < 0.15,
274− text >= 0.11 && < 1.3,
274+ text >= 0.11 && < 1.3,
275+ time >= 1.4 && < 1.8,
276+ time-locale-compat >= 0.1 && < 0.2,
275− unordered-containers >= 0.2 && < 0.3,
277+ unordered-containers >= 0.2 && < 0.3,
278+ vector >= 0.11 && < 0.13,
276− yaml >= 0.8.11 && < 0.12
279+ yaml >= 0.8.11 && < 0.9,
280+ optparse-applicative >= 0.12 && < 0.14
277
281
278 If flag(previewServer)
282 If flag(previewServer)
283+ Build-depends:
284+ wai >= 3.2 && < 3.3,
285+ warp >= 3.2 && < 3.3,
286+ wai-app-static >= 3.1 && < 3.2,
287+ http-types >= 0.9 && < 0.10,
288+ fsnotify >= 0.2 && < 0.3,
289+ system-filepath >= 0.4.6 && <= 0.5
279 Cpp-options:
290 Cpp-options:
280 -DPREVIEW_SERVER
291 -DPREVIEW_SERVER
292+ Other-modules:
293+ Hakyll.Preview.Poll
294+ Hakyll.Preview.Server
281
295
282 If flag(watchServer)
296 If flag(watchServer)
297+ Build-depends:
298+ fsnotify >= 0.2 && < 0.3,
299+ system-filepath >= 0.4.6 && <= 0.5
283 Cpp-options:
300 Cpp-options:
284 -DWATCH_SERVER
301 -DWATCH_SERVER
302+ Other-modules:
303+ Hakyll.Preview.Poll
285
304
286 If flag(checkExternal)
305 If flag(checkExternal)
306+ Build-depends:
307+ http-conduit >= 2.2 && < 2.3,
308+ http-types >= 0.7 && < 0.10
287 Cpp-options:
309 Cpp-options:
288 -DCHECK_EXTERNAL
310 -DCHECK_EXTERNAL
289
311
290− If flag(usePandoc)
291− Other-modules:
292− Hakyll.Web.Pandoc.FileType.Tests
293− Cpp-options:
294− -DUSE_PANDOC
295−
296Executable hakyll-init
312Executable hakyll-init
297− Main-is: Init.hs
298− Ghc-options: -Wall -threaded
313+ Ghc-options: -Wall
299− Hs-source-dirs: src
314+ Hs-source-dirs: src
300− Default-language: Haskell2010
315+ Main-is: Hakyll/Init.hs
301−
302− Other-modules:
303− Paths_hakyll
304
316
305 Build-depends:
317 Build-depends:
306− hakyll,
307 base >= 4 && < 5,
318 base >= 4 && < 5,
308 directory >= 1.0 && < 1.4,
319 directory >= 1.0 && < 1.4,
309 filepath >= 1.0 && < 1.5
320 filepath >= 1.0 && < 1.5
310
321
311−Executable hakyll-website
322+ Other-modules:
312− Main-is: site.hs
323+ Hakyll.Core.Util.File
313− Ghc-options: -Wall -threaded
324+ Paths_hakyll
314− Hs-source-dirs: web
315− Default-language: Haskell2010
316−
317− If flag(buildWebsite)
318− Buildable: True
319− Else
320− Buildable: False
321−
322− Build-depends:
323− hakyll,
324− base >= 4 && < 5,
325− directory >= 1.0 && < 1.4,
326− filepath >= 1.0 && < 1.5,
327− pandoc >= 2.0.5 && < 2.8
lib/Hakyll/Core/Identifier/Pattern/Internal.hsdeleted−92
@@ -1,92 +0,0 @@
1−-- | This internal module is mostly here to prevent CPP conflicting with Haskell
2−-- comments.
3−{-# LANGUAGE CPP #-}
4−module Hakyll.Core.Identifier.Pattern.Internal
5− ( GlobComponent (..)
6− , Pattern (..)
7− ) where
8−
9−
10−--------------------------------------------------------------------------------
11−import Data.Binary (Binary (..), getWord8, putWord8)
12−import Data.Set (Set)
13−
14−
15−--------------------------------------------------------------------------------
16−#if MIN_VERSION_base(4,9,0)
17−import Data.Semigroup (Semigroup (..))
18−#endif
19−
20−
21−--------------------------------------------------------------------------------
22−import Hakyll.Core.Identifier
23−
24−
25−--------------------------------------------------------------------------------
26−-- | Elements of a glob pattern
27−data GlobComponent
28− = Capture
29− | CaptureMany
30− | Literal String
31− deriving (Eq, Show)
32−
33−
34−--------------------------------------------------------------------------------
35−instance Binary GlobComponent where
36− put Capture = putWord8 0
37− put CaptureMany = putWord8 1
38− put (Literal s) = putWord8 2 >> put s
39−
40− get = getWord8 >>= \t -> case t of
41− 0 -> pure Capture
42− 1 -> pure CaptureMany
43− 2 -> Literal <$> get
44− _ -> error "Data.Binary.get: Invalid GlobComponent"
45−
46−
47−--------------------------------------------------------------------------------
48−-- | Type that allows matching on identifiers
49−data Pattern
50− = Everything
51− | Complement Pattern
52− | And Pattern Pattern
53− | Glob [GlobComponent]
54− | List (Set Identifier)
55− | Regex String
56− | Version (Maybe String)
57− deriving (Show)
58−
59−
60−--------------------------------------------------------------------------------
61−instance Binary Pattern where
62− put Everything = putWord8 0
63− put (Complement p) = putWord8 1 >> put p
64− put (And x y) = putWord8 2 >> put x >> put y
65− put (Glob g) = putWord8 3 >> put g
66− put (List is) = putWord8 4 >> put is
67− put (Regex r) = putWord8 5 >> put r
68− put (Version v) = putWord8 6 >> put v
69−
70− get = getWord8 >>= \t -> case t of
71− 0 -> pure Everything
72− 1 -> Complement <$> get
73− 2 -> And <$> get <*> get
74− 3 -> Glob <$> get
75− 4 -> List <$> get
76− 5 -> Regex <$> get
77− _ -> Version <$> get
78−
79−
80−--------------------------------------------------------------------------------
81−#if MIN_VERSION_base(4,9,0)
82−instance Semigroup Pattern where
83− (<>) = And
84−
85−instance Monoid Pattern where
86− mempty = Everything
87− mappend = (<>)
88−#else
89−instance Monoid Pattern where
90− mempty = Everything
91− mappend = And
92−#endif
lib/Hakyll/Main.hsdeleted−180
@@ -1,180 +0,0 @@
1−--------------------------------------------------------------------------------
2−-- | Module providing the main hakyll function and command-line argument parsing
3−{-# LANGUAGE CPP #-}
4−
5−module Hakyll.Main
6− ( hakyll
7− , hakyllWith
8− , hakyllWithArgs
9− , hakyllWithExitCode
10− , hakyllWithExitCodeAndArgs
11− , Options(..)
12− , Command(..)
13− ) where
14−
15−
16−--------------------------------------------------------------------------------
17−import System.Environment (getProgName)
18−import System.Exit (ExitCode (ExitSuccess), exitWith)
19−import System.IO.Unsafe (unsafePerformIO)
20−
21−
22−--------------------------------------------------------------------------------
23−import Data.Monoid ((<>))
24−import qualified Options.Applicative as OA
25−
26−
27−--------------------------------------------------------------------------------
28−import qualified Hakyll.Check as Check
29−import qualified Hakyll.Commands as Commands
30−import qualified Hakyll.Core.Configuration as Config
31−import qualified Hakyll.Core.Logger as Logger
32−import Hakyll.Core.Rules
33−
34−
35−--------------------------------------------------------------------------------
36−-- | This usually is the function with which the user runs the hakyll compiler
37−hakyll :: Rules a -> IO ()
38−hakyll = hakyllWith Config.defaultConfiguration
39−
40−--------------------------------------------------------------------------------
41−-- | A variant of 'hakyll' which allows the user to specify a custom
42−-- configuration
43−hakyllWith :: Config.Configuration -> Rules a -> IO ()
44−hakyllWith conf rules = hakyllWithExitCode conf rules >>= exitWith
45−
46−--------------------------------------------------------------------------------
47−-- | A variant of 'hakyll' which returns an 'ExitCode'
48−hakyllWithExitCode :: Config.Configuration -> Rules a -> IO ExitCode
49−hakyllWithExitCode conf rules = do
50− args <- defaultParser conf
51− hakyllWithExitCodeAndArgs conf args rules
52−
53−--------------------------------------------------------------------------------
54−-- | A variant of 'hakyll' which expects a 'Configuration' and command-line
55−-- 'Options'. This gives freedom to implement your own parsing.
56−hakyllWithArgs :: Config.Configuration -> Options -> Rules a -> IO ()
57−hakyllWithArgs conf args rules =
58− hakyllWithExitCodeAndArgs conf args rules >>= exitWith
59−
60−--------------------------------------------------------------------------------
61−hakyllWithExitCodeAndArgs :: Config.Configuration ->
62− Options -> Rules a -> IO ExitCode
63−hakyllWithExitCodeAndArgs conf args rules = do
64− let args' = optCommand args
65− verbosity' = if verbosity args then Logger.Debug else Logger.Message
66− check =
67− if internal_links args' then Check.InternalLinks else Check.All
68−
69− logger <- Logger.new verbosity'
70− invokeCommands args' conf check logger rules
71−
72−--------------------------------------------------------------------------------
73−defaultParser :: Config.Configuration -> IO Options
74−defaultParser conf =
75− OA.customExecParser (OA.prefs OA.showHelpOnError)
76− (OA.info (OA.helper <*> optionParser conf)
77− (OA.fullDesc <> OA.progDesc
78− (progName ++ " - Static site compiler created with Hakyll")))
79−
80−
81−--------------------------------------------------------------------------------
82−invokeCommands :: Command -> Config.Configuration ->
83− Check.Check -> Logger.Logger -> Rules a -> IO ExitCode
84−invokeCommands args conf check logger rules =
85− case args of
86− Build -> Commands.build conf logger rules
87− Check _ -> Commands.check conf logger check
88− Clean -> Commands.clean conf logger >> ok
89− Deploy -> Commands.deploy conf
90− Preview p -> Commands.preview conf logger rules p >> ok
91− Rebuild -> Commands.rebuild conf logger rules
92− Server _ _ -> Commands.server conf logger (host args) (port args) >> ok
93− Watch _ p s -> Commands.watch conf logger (host args) p (not s) rules >> ok
94− where
95− ok = return ExitSuccess
96−
97−
98−--------------------------------------------------------------------------------
99−
100−-- | The parsed command-line options.
101−data Options = Options {verbosity :: Bool, optCommand :: Command}
102− deriving (Show)
103−
104−-- | The command to run.
105−data Command
106− = Build
107− -- ^ Generate the site.
108− | Check {internal_links :: Bool}
109− -- ^ Validate the site output.
110− | Clean
111− -- ^ Clean up and remove cache.
112− | Deploy
113− -- ^ Upload/deploy your site.
114− | Preview {port :: Int}
115− -- ^ [DEPRECATED] Please use the watch command.
116− | Rebuild
117− -- ^ Clean and build again.
118− | Server {host :: String, port :: Int}
119− -- ^ Start a preview server.
120− | Watch {host :: String, port :: Int, no_server :: Bool }
121− -- ^ Autocompile on changes and start a preview server.
122− deriving (Show)
123−
124−{-# DEPRECATED Preview "Use Watch instead." #-}
125−
126−optionParser :: Config.Configuration -> OA.Parser Options
127−optionParser conf = Options <$> verboseParser <*> commandParser conf
128− where
129− verboseParser = OA.switch (OA.long "verbose" <> OA.short 'v' <> OA.help "Run in verbose mode")
130−
131−
132−commandParser :: Config.Configuration -> OA.Parser Command
133−commandParser conf = OA.subparser $ foldr ((<>) . produceCommand) mempty commands
134− where
135− portParser = OA.option OA.auto (OA.long "port" <> OA.help "Port to listen on" <> OA.value (Config.previewPort conf))
136− hostParser = OA.strOption (OA.long "host" <> OA.help "Host to bind on" <> OA.value (Config.previewHost conf))
137−
138− produceCommand (c,a,b) = OA.command c (OA.info (OA.helper <*> a) (b))
139−
140− commands =
141− [ ( "build"
142− , pure Build
143− , OA.fullDesc <> OA.progDesc "Generate the site"
144− )
145− , ( "check"
146− , pure Check <*> OA.switch (OA.long "internal-links" <> OA.help "Check internal links only")
147− , OA.fullDesc <> OA.progDesc "Validate the site output"
148− )
149− , ( "clean"
150− , pure Clean
151− , OA.fullDesc <> OA.progDesc "Clean up and remove cache"
152− )
153− , ( "deploy"
154− , pure Deploy
155− , OA.fullDesc <> OA.progDesc "Upload/deploy your site"
156− )
157− , ( "preview"
158− , pure Preview <*> portParser
159− , OA.fullDesc <> OA.progDesc "[DEPRECATED] Please use the watch command"
160− )
161− , ( "rebuild"
162− , pure Rebuild
163− , OA.fullDesc <> OA.progDesc "Clean and build again"
164− )
165− , ( "server"
166− , pure Server <*> hostParser <*> portParser
167− , OA.fullDesc <> OA.progDesc "Start a preview server"
168− )
169− , ( "watch"
170− , pure Watch <*> hostParser <*> portParser <*> OA.switch (OA.long "no-server" <> OA.help "Disable the built-in web server")
171− , OA.fullDesc <> OA.progDesc "Autocompile on changes and start a preview server. You can watch and recompile without running a server with --no-server."
172− )
173− ]
174−
175−
176−--------------------------------------------------------------------------------
177−-- | This is necessary because not everyone calls their program the same...
178−progName :: String
179−progName = unsafePerformIO getProgName
180−{-# NOINLINE progName #-}
lib/Hakyll/Web/CompressCss.hsdeleted−101
@@ -1,101 +0,0 @@
1−--------------------------------------------------------------------------------
2−-- | Module used for CSS compression. The compression is currently in a simple
3−-- state, but would typically reduce the number of bytes by about 25%.
4−module Hakyll.Web.CompressCss
5− ( compressCssCompiler
6− , compressCss
7− ) where
8−
9−
10−--------------------------------------------------------------------------------
11−import Data.Char (isSpace)
12−import Data.List (dropWhileEnd, isPrefixOf)
13−
14−
15−--------------------------------------------------------------------------------
16−import Hakyll.Core.Compiler
17−import Hakyll.Core.Item
18−import Hakyll.Core.Util.String
19−
20−
21−--------------------------------------------------------------------------------
22−-- | Compiler form of 'compressCss'
23−compressCssCompiler :: Compiler (Item String)
24−compressCssCompiler = fmap compressCss <$> getResourceString
25−
26−
27−--------------------------------------------------------------------------------
28−-- | Compress CSS to speed up your site.
29−compressCss :: String -> String
30−compressCss = withoutStrings (handleCalcExpressions compressSeparators . compressWhitespace)
31− . dropWhileEnd isSpace
32− . dropWhile isSpace
33− . stripComments
34−
35−
36−--------------------------------------------------------------------------------
37−-- | Compresses certain forms of separators.
38−compressSeparators :: String -> String
39−compressSeparators =
40− replaceAll "; *}" (const "}") .
41− replaceAll ";+" (const ";") .
42− replaceAll " *[{};,>+~!] *" (take 1 . dropWhile isSpace) .
43− replaceAll ": *" (take 1) -- not destroying pseudo selectors (#323)
44−
45−-- | Uses `compressCalcExpression` on all parenthesised calc expressions
46−-- and applies `transform` to all parts outside of them
47−handleCalcExpressions :: (String -> String) -> String -> String
48−handleCalcExpressions transform = top transform
49− where
50− top f "" = f ""
51− top f str | "calc(" `isPrefixOf` str = f "calc" ++ nested 0 compressCalcExpression (drop 4 str)
52− top f (x:xs) = top (f . (x:)) xs
53−
54− -- when called with depth=0, the first character must be a '('
55− nested :: Int -> (String -> String) -> String -> String
56− nested _ f "" = f "" -- shouldn't happen, mismatched nesting
57− nested depth f str | "calc(" `isPrefixOf` str = nested depth f (drop 4 str)
58− nested 1 f (')':xs) = f ")" ++ top transform xs
59− nested depth f (x:xs) = nested (case x of
60− '(' -> depth + 1
61− ')' -> depth - 1 -- assert: depth > 1
62− _ -> depth
63− ) (f . (x:)) xs
64−
65−-- | does not remove whitespace around + and -, which is important in calc() expressions
66−compressCalcExpression :: String -> String
67−compressCalcExpression =
68− replaceAll " *[*/] *| *\\)|\\( *" (take 1 . dropWhile isSpace)
69−
70−--------------------------------------------------------------------------------
71−-- | Compresses all whitespace.
72−compressWhitespace :: String -> String
73−compressWhitespace = replaceAll "[ \t\n\r]+" (const " ")
74−
75−--------------------------------------------------------------------------------
76−-- | Function that strips CSS comments away (outside of strings).
77−stripComments :: String -> String
78−stripComments "" = ""
79−stripComments ('/':'*':str) = stripComments $ eatComment str
80−stripComments (x:xs) | x `elem` "\"'" = retainString x xs stripComments
81− | otherwise = x : stripComments xs
82−
83−eatComment :: String -> String
84−eatComment "" = ""
85−eatComment ('*':'/':str) = str
86−eatComment (_:str) = eatComment str
87−
88−
89−--------------------------------------------------------------------------------
90−-- | Helper functions to handle string tokens correctly.
91−
92−-- TODO: handle backslash escapes
93−withoutStrings :: (String -> String) -> String -> String
94−withoutStrings f str = case span (`notElem` "\"'") str of
95− (text, "") -> f text
96− (text, d:rest) -> f text ++ retainString d rest (withoutStrings f)
97−
98−retainString :: Char -> String -> (String -> String) -> String
99−retainString delim str cont = case span (/= delim) str of
100− (val, "") -> delim : val
101− (val, _:rest) -> delim : val ++ delim : cont rest
lib/Data/List/Extended.hs → src/Data/List/Extended.hsrenamed

The content is the same.

lib/Data/Yaml/Extended.hs → src/Data/Yaml/Extended.hsrenamed

The content is the same.

lib/Hakyll.hs → src/Hakyll.hsrenamed+1−5
@@ -20,12 +20,10 @@ module Hakyll
20 , module Hakyll.Web.Feed
20 , module Hakyll.Web.Feed
21 , module Hakyll.Web.Html
21 , module Hakyll.Web.Html
22 , module Hakyll.Web.Html.RelativizeUrls
22 , module Hakyll.Web.Html.RelativizeUrls
23− , module Hakyll.Web.Paginate
24−#ifdef USE_PANDOC
25 , module Hakyll.Web.Pandoc
23 , module Hakyll.Web.Pandoc
24+ , module Hakyll.Web.Paginate
26 , module Hakyll.Web.Pandoc.Biblio
25 , module Hakyll.Web.Pandoc.Biblio
27 , module Hakyll.Web.Pandoc.FileType
26 , module Hakyll.Web.Pandoc.FileType
28−#endif
29 , module Hakyll.Web.Redirect
27 , module Hakyll.Web.Redirect
30 , module Hakyll.Web.Tags
28 , module Hakyll.Web.Tags
31 , module Hakyll.Web.Template
29 , module Hakyll.Web.Template
@@ -54,11 +52,9 @@ import Hakyll.Web.Feed
54import Hakyll.Web.Html
52import Hakyll.Web.Html
55import Hakyll.Web.Html.RelativizeUrls
53import Hakyll.Web.Html.RelativizeUrls
56import Hakyll.Web.Paginate
54import Hakyll.Web.Paginate
57−#ifdef USE_PANDOC
58import Hakyll.Web.Pandoc
55import Hakyll.Web.Pandoc
59import Hakyll.Web.Pandoc.Biblio
56import Hakyll.Web.Pandoc.Biblio
60import Hakyll.Web.Pandoc.FileType
57import Hakyll.Web.Pandoc.FileType
61−#endif
62import Hakyll.Web.Redirect
58import Hakyll.Web.Redirect
63import Hakyll.Web.Tags
59import Hakyll.Web.Tags
64import Hakyll.Web.Template
60import Hakyll.Web.Template
lib/Hakyll/Check.hs → src/Hakyll/Check.hsrenamed+1−13
@@ -17,11 +17,9 @@ import Control.Monad.Reader (ReaderT, ask, runReaderT)
17import Control.Monad.State (StateT, get, modify, runStateT)
17import Control.Monad.State (StateT, get, modify, runStateT)
18import Control.Monad.Trans (liftIO)
18import Control.Monad.Trans (liftIO)
19import Control.Monad.Trans.Resource (runResourceT)
19import Control.Monad.Trans.Resource (runResourceT)
20+import Data.ByteString.Char8 (unpack)
20import Data.List (isPrefixOf)
21import Data.List (isPrefixOf)
21import qualified Data.Map.Lazy as Map
22import qualified Data.Map.Lazy as Map
22−#if MIN_VERSION_base(4,9,0)
23−import Data.Semigroup (Semigroup (..))
24−#endif
25import Network.URI (unEscapeString)
23import Network.URI (unEscapeString)
26import System.Directory (doesDirectoryExist,
24import System.Directory (doesDirectoryExist,
27 doesFileExist)
25 doesFileExist)
@@ -88,20 +86,10 @@ data CheckerWrite = CheckerWrite
88
86
89
87
90--------------------------------------------------------------------------------
88--------------------------------------------------------------------------------
91−#if MIN_VERSION_base(4,9,0)
92−instance Semigroup CheckerWrite where
93− (<>) (CheckerWrite f1 o1) (CheckerWrite f2 o2) =
94− CheckerWrite (f1 + f2) (o1 + o2)
95−
96−instance Monoid CheckerWrite where
97− mempty = CheckerWrite 0 0
98− mappend = (<>)
99−#else
100instance Monoid CheckerWrite where
89instance Monoid CheckerWrite where
101 mempty = CheckerWrite 0 0
90 mempty = CheckerWrite 0 0
102 mappend (CheckerWrite f1 o1) (CheckerWrite f2 o2) =
91 mappend (CheckerWrite f1 o1) (CheckerWrite f2 o2) =
103 CheckerWrite (f1 + f2) (o1 + o2)
92 CheckerWrite (f1 + f2) (o1 + o2)
104−#endif
105
93
106
94
107--------------------------------------------------------------------------------
95--------------------------------------------------------------------------------
lib/Hakyll/Commands.hs → src/Hakyll/Commands.hsrenamed+2−6
@@ -2,8 +2,7 @@
2-- | Implementation of Hakyll commands: build, preview...
2-- | Implementation of Hakyll commands: build, preview...
3{-# LANGUAGE CPP #-}
3{-# LANGUAGE CPP #-}
4module Hakyll.Commands
4module Hakyll.Commands
5− ( Check(..)
6− , build
5+ ( build
7 , check
6 , check
8 , clean
7 , clean
9 , preview
8 , preview
@@ -16,11 +15,9 @@ module Hakyll.Commands
16
15
17--------------------------------------------------------------------------------
16--------------------------------------------------------------------------------
18import Control.Concurrent
17import Control.Concurrent
19−import System.Exit (ExitCode)
18+import System.Exit (ExitCode, exitWith)
20−
21
19
22--------------------------------------------------------------------------------
20--------------------------------------------------------------------------------
23−import Hakyll.Check (Check(..))
24import qualified Hakyll.Check as Check
21import qualified Hakyll.Check as Check
25import Hakyll.Core.Configuration
22import Hakyll.Core.Configuration
26import Hakyll.Core.Logger (Logger)
23import Hakyll.Core.Logger (Logger)
@@ -30,7 +27,6 @@ import Hakyll.Core.Rules.Internal
30import Hakyll.Core.Runtime
27import Hakyll.Core.Runtime
31import Hakyll.Core.Util.File
28import Hakyll.Core.Util.File
32
29
33−
34--------------------------------------------------------------------------------
30--------------------------------------------------------------------------------
35#ifdef WATCH_SERVER
31#ifdef WATCH_SERVER
36import Hakyll.Preview.Poll (watchUpdates)
32import Hakyll.Preview.Poll (watchUpdates)
lib/Hakyll/Core/Compiler.hs → src/Hakyll/Core/Compiler.hsrenamed+2−44
@@ -24,16 +24,13 @@ module Hakyll.Core.Compiler
24 , cached
24 , cached
25 , unsafeCompiler
25 , unsafeCompiler
26 , debugCompiler
26 , debugCompiler
27− , noResult
28− , withErrorMessage
29 ) where
27 ) where
30
28
31
29
32--------------------------------------------------------------------------------
30--------------------------------------------------------------------------------
33−import Control.Monad (unless, when, (>=>))
31+import Control.Monad (when)
34import Data.Binary (Binary)
32import Data.Binary (Binary)
35import Data.ByteString.Lazy (ByteString)
33import Data.ByteString.Lazy (ByteString)
36−import qualified Data.List.NonEmpty as NonEmpty
37import Data.Typeable (Typeable)
34import Data.Typeable (Typeable)
38import System.Environment (getProgName)
35import System.Environment (getProgName)
39import System.FilePath (takeExtension)
36import System.FilePath (takeExtension)
@@ -65,7 +62,6 @@ getUnderlyingExtension = takeExtension . toFilePath <$> getUnderlying
65
62
66
63
67--------------------------------------------------------------------------------
64--------------------------------------------------------------------------------
68−-- | Create an item from the underlying identifier and a given value.
69makeItem :: a -> Compiler (Item a)
65makeItem :: a -> Compiler (Item a)
70makeItem x = do
66makeItem x = do
71 identifier <- getUnderlying
67 identifier <- getUnderlying
@@ -145,10 +141,6 @@ saveSnapshot snapshot item = do
145
141
146
142
147--------------------------------------------------------------------------------
143--------------------------------------------------------------------------------
148−-- | Turn on caching for a compilation value to avoid recomputing it
149−-- on subsequent Hakyll runs.
150−-- The storage key consists of the underlying identifier of the compiled
151−-- ressource and the given name.
152cached :: (Binary a, Typeable a)
144cached :: (Binary a, Typeable a)
153 => String
145 => String
154 -> Compiler a
146 -> Compiler a
@@ -157,10 +149,6 @@ cached name compiler = do
157 id' <- compilerUnderlying <$> compilerAsk
149 id' <- compilerUnderlying <$> compilerAsk
158 store <- compilerStore <$> compilerAsk
150 store <- compilerStore <$> compilerAsk
159 provider <- compilerProvider <$> compilerAsk
151 provider <- compilerProvider <$> compilerAsk
160−
161− -- Give a better error message when the resource is not there at all.
162− unless (resourceExists provider id') $ fail $ itDoesntEvenExist id'
163−
164 let modified = resourceModified provider id'
152 let modified = resourceModified provider id'
165 if modified
153 if modified
166 then do
154 then do
@@ -178,44 +166,14 @@ cached name compiler = do
178 "Hakyll.Core.Compiler.cached: Cache corrupt! " ++
166 "Hakyll.Core.Compiler.cached: Cache corrupt! " ++
179 "Try running: " ++ progName ++ " clean"
167 "Try running: " ++ progName ++ " clean"
180
168
181− itDoesntEvenExist id' =
182− "Hakyll.Core.Compiler.cached: You are trying to (perhaps " ++
183− "indirectly) use `cached` on a non-existing resource: there " ++
184− "is no file backing " ++ show id'
185−
186
169
187--------------------------------------------------------------------------------
170--------------------------------------------------------------------------------
188−-- | Run an IO computation without dependencies in a Compiler
189unsafeCompiler :: IO a -> Compiler a
171unsafeCompiler :: IO a -> Compiler a
190unsafeCompiler = compilerUnsafeIO
172unsafeCompiler = compilerUnsafeIO
191
173
192
174
193--------------------------------------------------------------------------------
175--------------------------------------------------------------------------------
194−-- | Fail so that it is treated as non-defined in an @\$if()\$@ branching
195−-- "Hakyll.Web.Template" macro, and alternative
196−-- 'Hakyll.Web.Template.Context.Context's are tried
197−--
198−-- @since 4.13.0
199−noResult :: String -> Compiler a
200−noResult = compilerNoResult . return
201−
202−
203−--------------------------------------------------------------------------------
204−-- | Prepend an error line to the error, if there is one. This allows you to
205−-- add helpful context to error messages.
206−--
207−-- @since 4.13.0
208−withErrorMessage :: String -> Compiler a -> Compiler a
209−withErrorMessage x = do
210− compilerTry >=> either (compilerResult . CompilerError . prepend) return
211− where
212− prepend (CompilationFailure es) = CompilationFailure (x `NonEmpty.cons` es)
213− prepend (CompilationNoResult es) = CompilationNoResult (x : es)
214−
215−
216−--------------------------------------------------------------------------------
217−-- | Compiler for debugging purposes.
176+-- | Compiler for debugging purposes
218−-- Passes a message to the debug logger that is printed in verbose mode.
219debugCompiler :: String -> Compiler ()
177debugCompiler :: String -> Compiler ()
220debugCompiler msg = do
178debugCompiler msg = do
221 logger <- compilerLogger <$> compilerAsk
179 logger <- compilerLogger <$> compilerAsk
lib/Hakyll/Core/Compiler/Internal.hs → src/Hakyll/Core/Compiler/Internal.hsrenamed+41−140
@@ -1,7 +1,5 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2-- | Internally used compiler module
2-- | Internally used compiler module
3−{-# LANGUAGE CPP #-}
4−{-# LANGUAGE DeriveFunctor #-}
5{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
7{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -11,26 +9,19 @@ module Hakyll.Core.Compiler.Internal
11 Snapshot
9 Snapshot
12 , CompilerRead (..)
10 , CompilerRead (..)
13 , CompilerWrite (..)
11 , CompilerWrite (..)
14− , CompilerErrors (..)
15 , CompilerResult (..)
12 , CompilerResult (..)
16 , Compiler (..)
13 , Compiler (..)
17 , runCompiler
14 , runCompiler
18
15
19 -- * Core operations
16 -- * Core operations
20− , compilerResult
21 , compilerTell
17 , compilerTell
22 , compilerAsk
18 , compilerAsk
23− , compilerUnsafeIO
24−
25− -- * Error operations
26 , compilerThrow
19 , compilerThrow
27− , compilerNoResult
28 , compilerCatch
20 , compilerCatch
29− , compilerTry
21+ , compilerResult
30− , compilerErrorMessages
22+ , compilerUnsafeIO
31
23
32 -- * Utilities
24 -- * Utilities
33− , compilerDebugEntries
34 , compilerTellDependencies
25 , compilerTellDependencies
35 , compilerTellCacheHits
26 , compilerTellCacheHits
36 ) where
27 ) where
@@ -40,12 +31,7 @@ module Hakyll.Core.Compiler.Internal
40import Control.Applicative (Alternative (..))
31import Control.Applicative (Alternative (..))
41import Control.Exception (SomeException, handle)
32import Control.Exception (SomeException, handle)
42import Control.Monad (forM_)
33import Control.Monad (forM_)
43−import Control.Monad.Except (MonadError (..))
34+import Control.Monad.Except (MonadError (..))
44−import Data.List.NonEmpty (NonEmpty (..))
45−import qualified Data.List.NonEmpty as NonEmpty
46−#if MIN_VERSION_base(4,9,0)
47−import Data.Semigroup (Semigroup (..))
48−#endif
49import Data.Set (Set)
35import Data.Set (Set)
50import qualified Data.Set as S
36import qualified Data.Set as S
51
37
@@ -55,6 +41,7 @@ import Hakyll.Core.Configuration
55import Hakyll.Core.Dependencies
41import Hakyll.Core.Dependencies
56import Hakyll.Core.Identifier
42import Hakyll.Core.Identifier
57import Hakyll.Core.Identifier.Pattern
43import Hakyll.Core.Identifier.Pattern
44+import Hakyll.Core.Logger (Logger)
58import qualified Hakyll.Core.Logger as Logger
45import qualified Hakyll.Core.Logger as Logger
59import Hakyll.Core.Metadata
46import Hakyll.Core.Metadata
60import Hakyll.Core.Provider
47import Hakyll.Core.Provider
@@ -84,7 +71,7 @@ data CompilerRead = CompilerRead
84 , -- | Compiler store
71 , -- | Compiler store
85 compilerStore :: Store
72 compilerStore :: Store
86 , -- | Logger
73 , -- | Logger
87− compilerLogger :: Logger.Logger
74+ compilerLogger :: Logger
88 }
75 }
89
76
90
77
@@ -96,46 +83,18 @@ data CompilerWrite = CompilerWrite
96
83
97
84
98--------------------------------------------------------------------------------
85--------------------------------------------------------------------------------
99−#if MIN_VERSION_base(4,9,0)
100−instance Semigroup CompilerWrite where
101− (<>) (CompilerWrite d1 h1) (CompilerWrite d2 h2) =
102− CompilerWrite (d1 ++ d2) (h1 + h2)
103−
104−instance Monoid CompilerWrite where
105− mempty = CompilerWrite [] 0
106− mappend = (<>)
107−#else
108instance Monoid CompilerWrite where
86instance Monoid CompilerWrite where
109 mempty = CompilerWrite [] 0
87 mempty = CompilerWrite [] 0
110 mappend (CompilerWrite d1 h1) (CompilerWrite d2 h2) =
88 mappend (CompilerWrite d1 h1) (CompilerWrite d2 h2) =
111 CompilerWrite (d1 ++ d2) (h1 + h2)
89 CompilerWrite (d1 ++ d2) (h1 + h2)
112−#endif
113
90
114
91
115--------------------------------------------------------------------------------
92--------------------------------------------------------------------------------
116−-- | Distinguishes reasons in a 'CompilerError'
93+data CompilerResult a where
117−data CompilerErrors a
118− -- | One or more exceptions occured during compilation
119− = CompilationFailure (NonEmpty a)
120− -- | Absence of any result, most notably in template contexts. May still
121− -- have error messages.
122− | CompilationNoResult [a]
123− deriving Functor
124−
125−
126−-- | Unwrap a `CompilerErrors`
127−compilerErrorMessages :: CompilerErrors a -> [a]
128−compilerErrorMessages (CompilationFailure x) = NonEmpty.toList x
129−compilerErrorMessages (CompilationNoResult x) = x
130−
131−
132−--------------------------------------------------------------------------------
133−-- | An intermediate result of a compilation step
134−data CompilerResult a
135− = CompilerDone a CompilerWrite
94+ CompilerDone :: a -> CompilerWrite -> CompilerResult a
136− | CompilerSnapshot Snapshot (Compiler a)
95+ CompilerSnapshot :: Snapshot -> Compiler a -> CompilerResult a
96+ CompilerError :: [String] -> CompilerResult a
137− | CompilerRequire (Identifier, Snapshot) (Compiler a)
97+ CompilerRequire :: (Identifier, Snapshot) -> Compiler a -> CompilerResult a
138− | CompilerError (CompilerErrors String)
139
98
140
99
141--------------------------------------------------------------------------------
100--------------------------------------------------------------------------------
@@ -153,14 +112,14 @@ instance Functor Compiler where
153 return $ case res of
112 return $ case res of
154 CompilerDone x w -> CompilerDone (f x) w
113 CompilerDone x w -> CompilerDone (f x) w
155 CompilerSnapshot s c' -> CompilerSnapshot s (fmap f c')
114 CompilerSnapshot s c' -> CompilerSnapshot s (fmap f c')
156− CompilerRequire i c' -> CompilerRequire i (fmap f c')
157 CompilerError e -> CompilerError e
115 CompilerError e -> CompilerError e
116+ CompilerRequire i c' -> CompilerRequire i (fmap f c')
158 {-# INLINE fmap #-}
117 {-# INLINE fmap #-}
159
118
160
119
161--------------------------------------------------------------------------------
120--------------------------------------------------------------------------------
162instance Monad Compiler where
121instance Monad Compiler where
163− return x = compilerResult $ CompilerDone x mempty
122+ return x = Compiler $ \_ -> return $ CompilerDone x mempty
164 {-# INLINE return #-}
123 {-# INLINE return #-}
165
124
166 Compiler c >>= f = Compiler $ \r -> do
125 Compiler c >>= f = Compiler $ \r -> do
@@ -173,14 +132,14 @@ instance Monad Compiler where
173 CompilerSnapshot s c' -> CompilerSnapshot s $ do
132 CompilerSnapshot s c' -> CompilerSnapshot s $ do
174 compilerTell w -- Save dependencies!
133 compilerTell w -- Save dependencies!
175 c'
134 c'
135+ CompilerError e -> CompilerError e
176 CompilerRequire i c' -> CompilerRequire i $ do
136 CompilerRequire i c' -> CompilerRequire i $ do
177 compilerTell w -- Save dependencies!
137 compilerTell w -- Save dependencies!
178 c'
138 c'
179− CompilerError e -> CompilerError e
180
139
181 CompilerSnapshot s c' -> return $ CompilerSnapshot s (c' >>= f)
140 CompilerSnapshot s c' -> return $ CompilerSnapshot s (c' >>= f)
182− CompilerRequire i c' -> return $ CompilerRequire i (c' >>= f)
183 CompilerError e -> return $ CompilerError e
141 CompilerError e -> return $ CompilerError e
142+ CompilerRequire i c' -> return $ CompilerRequire i (c' >>= f)
184 {-# INLINE (>>=) #-}
143 {-# INLINE (>>=) #-}
185
144
186 fail = compilerThrow . return
145 fail = compilerThrow . return
@@ -197,145 +156,87 @@ instance Applicative Compiler where
197
156
198
157
199--------------------------------------------------------------------------------
158--------------------------------------------------------------------------------
200−-- | Access provided metadata from anywhere
201instance MonadMetadata Compiler where
159instance MonadMetadata Compiler where
202 getMetadata = compilerGetMetadata
160 getMetadata = compilerGetMetadata
203 getMatches = compilerGetMatches
161 getMatches = compilerGetMatches
204
162
205
163
206--------------------------------------------------------------------------------
164--------------------------------------------------------------------------------
207−-- | Compilation may fail with multiple error messages.
208−-- 'catchError' handles errors from 'throwError', 'fail' and 'Hakyll.Core.Compiler.noResult'
209instance MonadError [String] Compiler where
165instance MonadError [String] Compiler where
210− throwError = compilerThrow
166+ throwError = compilerThrow
211− catchError c = compilerCatch c . (. compilerErrorMessages)
167+ catchError = compilerCatch
212
168
213
169
214--------------------------------------------------------------------------------
170--------------------------------------------------------------------------------
215−-- | Like 'unCompiler' but treating IO exceptions as 'CompilerError's
216runCompiler :: Compiler a -> CompilerRead -> IO (CompilerResult a)
171runCompiler :: Compiler a -> CompilerRead -> IO (CompilerResult a)
217runCompiler compiler read' = handle handler $ unCompiler compiler read'
172runCompiler compiler read' = handle handler $ unCompiler compiler read'
218 where
173 where
219 handler :: SomeException -> IO (CompilerResult a)
174 handler :: SomeException -> IO (CompilerResult a)
220− handler e = return $ CompilerError $ CompilationFailure $ show e :| []
175+ handler e = return $ CompilerError [show e]
221
176
222
177
223--------------------------------------------------------------------------------
178--------------------------------------------------------------------------------
224−-- | Trying alternative compilers if the first fails, regardless whether through
225−-- 'fail', 'throwError' or 'Hakyll.Core.Compiler.noResult'.
226−-- Aggregates error messages if all fail.
227instance Alternative Compiler where
179instance Alternative Compiler where
228− empty = compilerNoResult []
180+ empty = compilerThrow []
229− x <|> y = x `compilerCatch` (\rx -> y `compilerCatch` (\ry ->
181+ x <|> y = compilerCatch x $ \es -> do
230− case (rx, ry) of
182+ logger <- compilerLogger <$> compilerAsk
231− (CompilationFailure xs, CompilationFailure ys) ->
183+ forM_ es $ \e -> compilerUnsafeIO $ Logger.debug logger $
232− compilerThrow $ NonEmpty.toList xs ++ NonEmpty.toList ys
233− (CompilationFailure xs, CompilationNoResult ys) ->
234− debug ys >> compilerThrow (NonEmpty.toList xs)
235− (CompilationNoResult xs, CompilationFailure ys) ->
236− debug xs >> compilerThrow (NonEmpty.toList ys)
237− (CompilationNoResult xs, CompilationNoResult ys) -> compilerNoResult $ xs ++ ys
238− ))
239− where
240− debug = compilerDebugEntries "Hakyll.Core.Compiler.Internal: Alternative fail suppressed"
184+ "Hakyll.Core.Compiler.Internal: Alternative failed: " ++ e
185+ y
241 {-# INLINE (<|>) #-}
186 {-# INLINE (<|>) #-}
242
187
243
188
244--------------------------------------------------------------------------------
189--------------------------------------------------------------------------------
245−-- | Put the result back in a compiler
246−compilerResult :: CompilerResult a -> Compiler a
247−compilerResult x = Compiler $ \_ -> return x
248−{-# INLINE compilerResult #-}
249−
250−
251−--------------------------------------------------------------------------------
252−-- | Get the current environment
253compilerAsk :: Compiler CompilerRead
190compilerAsk :: Compiler CompilerRead
254compilerAsk = Compiler $ \r -> return $ CompilerDone r mempty
191compilerAsk = Compiler $ \r -> return $ CompilerDone r mempty
255{-# INLINE compilerAsk #-}
192{-# INLINE compilerAsk #-}
256
193
257
194
258--------------------------------------------------------------------------------
195--------------------------------------------------------------------------------
259−-- | Put a 'CompilerWrite'
260compilerTell :: CompilerWrite -> Compiler ()
196compilerTell :: CompilerWrite -> Compiler ()
261−compilerTell = compilerResult . CompilerDone ()
197+compilerTell deps = Compiler $ \_ -> return $ CompilerDone () deps
262{-# INLINE compilerTell #-}
198{-# INLINE compilerTell #-}
263
199
264
200
265--------------------------------------------------------------------------------
201--------------------------------------------------------------------------------
266−-- | Run an IO computation without dependencies in a Compiler
267−compilerUnsafeIO :: IO a -> Compiler a
268−compilerUnsafeIO io = Compiler $ \_ -> do
269− x <- io
270− return $ CompilerDone x mempty
271−{-# INLINE compilerUnsafeIO #-}
272−
273−
274−--------------------------------------------------------------------------------
275−-- | Throw errors in the 'Compiler'.
276−--
277−-- If no messages are given, this is considered a 'CompilationNoResult' error.
278−-- Otherwise, it is treated as a proper compilation failure.
279compilerThrow :: [String] -> Compiler a
202compilerThrow :: [String] -> Compiler a
280−compilerThrow = compilerResult . CompilerError .
203+compilerThrow es = Compiler $ \_ -> return $ CompilerError es
281− maybe (CompilationNoResult []) CompilationFailure .
204+{-# INLINE compilerThrow #-}
282− NonEmpty.nonEmpty
283−
284−-- | Put a 'CompilerError' with multiple messages as 'CompilationNoResult'
285−compilerNoResult :: [String] -> Compiler a
286−compilerNoResult = compilerResult . CompilerError . CompilationNoResult
287
205
288
206
289--------------------------------------------------------------------------------
207--------------------------------------------------------------------------------
290−-- | Allows to distinguish 'CompilerError's and branch on them with 'Either'
291−--
292−-- prop> compilerTry = (`compilerCatch` return . Left) . fmap Right
293−compilerTry :: Compiler a -> Compiler (Either (CompilerErrors String) a)
294−compilerTry (Compiler x) = Compiler $ \r -> do
295− res <- x r
296− case res of
297− CompilerDone res' w -> return (CompilerDone (Right res') w)
298− CompilerSnapshot s c -> return (CompilerSnapshot s (compilerTry c))
299− CompilerRequire i c -> return (CompilerRequire i (compilerTry c))
300− CompilerError e -> return (CompilerDone (Left e) mempty)
301−{-# INLINE compilerTry #-}
302−
303−
304−--------------------------------------------------------------------------------
305−-- | Allows you to recover from 'CompilerError's.
306−-- Uses the same parameter order as 'catchError' so that it can be used infix.
307−--
308−-- prop> c `compilerCatch` f = compilerTry c >>= either f return
309−compilerCatch :: Compiler a -> (CompilerErrors String -> Compiler a) -> Compiler a
208+compilerCatch :: Compiler a -> ([String] -> Compiler a) -> Compiler a
310compilerCatch (Compiler x) f = Compiler $ \r -> do
209compilerCatch (Compiler x) f = Compiler $ \r -> do
311 res <- x r
210 res <- x r
312 case res of
211 case res of
313 CompilerDone res' w -> return (CompilerDone res' w)
212 CompilerDone res' w -> return (CompilerDone res' w)
314 CompilerSnapshot s c -> return (CompilerSnapshot s (compilerCatch c f))
213 CompilerSnapshot s c -> return (CompilerSnapshot s (compilerCatch c f))
315− CompilerRequire i c -> return (CompilerRequire i (compilerCatch c f))
316 CompilerError e -> unCompiler (f e) r
214 CompilerError e -> unCompiler (f e) r
215+ CompilerRequire i c -> return (CompilerRequire i (compilerCatch c f))
317{-# INLINE compilerCatch #-}
216{-# INLINE compilerCatch #-}
318
217
319
218
320--------------------------------------------------------------------------------
219--------------------------------------------------------------------------------
321−compilerDebugLog :: [String] -> Compiler ()
220+-- | Put the result back in a compiler
322−compilerDebugLog ms = do
221+compilerResult :: CompilerResult a -> Compiler a
323− logger <- compilerLogger <$> compilerAsk
222+compilerResult x = Compiler $ \_ -> return x
324− compilerUnsafeIO $ forM_ ms $ Logger.debug logger
223+{-# INLINE compilerResult #-}
224+
325
225
326--------------------------------------------------------------------------------
226--------------------------------------------------------------------------------
327−-- | Pass a list of messages with a heading to the debug logger
227+compilerUnsafeIO :: IO a -> Compiler a
328−compilerDebugEntries :: String -> [String] -> Compiler ()
228+compilerUnsafeIO io = Compiler $ \_ -> do
329−compilerDebugEntries msg = compilerDebugLog . (msg:) . map indent
229+ x <- io
330− where
230+ return $ CompilerDone x mempty
331− indent = unlines . map (" "++) . lines
231+{-# INLINE compilerUnsafeIO #-}
332
232
333
233
334--------------------------------------------------------------------------------
234--------------------------------------------------------------------------------
335compilerTellDependencies :: [Dependency] -> Compiler ()
235compilerTellDependencies :: [Dependency] -> Compiler ()
336compilerTellDependencies ds = do
236compilerTellDependencies ds = do
337− compilerDebugLog $ map (\d ->
237+ logger <- compilerLogger <$> compilerAsk
238+ forM_ ds $ \d -> compilerUnsafeIO $ Logger.debug logger $
338− "Hakyll.Core.Compiler.Internal: Adding dependency: " ++ show d) ds
239+ "Hakyll.Core.Compiler.Internal: Adding dependency: " ++ show d
339 compilerTell mempty {compilerDependencies = ds}
240 compilerTell mempty {compilerDependencies = ds}
340{-# INLINE compilerTellDependencies #-}
241{-# INLINE compilerTellDependencies #-}
341
242
lib/Hakyll/Core/Compiler/Require.hs → src/Hakyll/Core/Compiler/Require.hsrenamed−2
@@ -91,7 +91,6 @@ loadBody id' = loadSnapshotBody id' final
91
91
92
92
93--------------------------------------------------------------------------------
93--------------------------------------------------------------------------------
94−-- | A shortcut for only requiring the body for a specific snapshot of an item
95loadSnapshotBody :: (Binary a, Typeable a)
94loadSnapshotBody :: (Binary a, Typeable a)
96 => Identifier -> Snapshot -> Compiler a
95 => Identifier -> Snapshot -> Compiler a
97loadSnapshotBody id' snapshot = fmap itemBody $ loadSnapshot id' snapshot
96loadSnapshotBody id' snapshot = fmap itemBody $ loadSnapshot id' snapshot
@@ -104,7 +103,6 @@ loadAll pattern = loadAllSnapshots pattern final
104
103
105
104
106--------------------------------------------------------------------------------
105--------------------------------------------------------------------------------
107−-- | Load a specific snapshot for each of dynamic list of items
108loadAllSnapshots :: (Binary a, Typeable a)
106loadAllSnapshots :: (Binary a, Typeable a)
109 => Pattern -> Snapshot -> Compiler [Item a]
107 => Pattern -> Snapshot -> Compiler [Item a]
110loadAllSnapshots pattern snapshot = do
108loadAllSnapshots pattern snapshot = do
lib/Hakyll/Core/Configuration.hs → src/Hakyll/Core/Configuration.hsrenamed

The content is the same.

lib/Hakyll/Core/Dependencies.hs → src/Hakyll/Core/Dependencies.hsrenamed

The content is the same.

lib/Hakyll/Core/File.hs → src/Hakyll/Core/File.hsrenamed+3−11
@@ -1,6 +1,5 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2-- | Exports simple compilers to just copy files
2-- | Exports simple compilers to just copy files
3−{-# LANGUAGE CPP #-}
4{-# LANGUAGE DeriveDataTypeable #-}
3{-# LANGUAGE DeriveDataTypeable #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6module Hakyll.Core.File
5module Hakyll.Core.File
@@ -14,12 +13,7 @@ module Hakyll.Core.File
14--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
15import Data.Binary (Binary (..))
14import Data.Binary (Binary (..))
16import Data.Typeable (Typeable)
15import Data.Typeable (Typeable)
17−#if MIN_VERSION_directory(1,2,6)
18−import System.Directory (copyFileWithMetadata)
19−#else
20−import System.Directory (copyFile)
16+import System.Directory (copyFile, doesFileExist,
21−#endif
22−import System.Directory (doesFileExist,
23 renameFile)
17 renameFile)
24import System.FilePath ((</>))
18import System.FilePath ((</>))
25import System.Random (randomIO)
19import System.Random (randomIO)
@@ -44,11 +38,9 @@ newtype CopyFile = CopyFile FilePath
44
38
45--------------------------------------------------------------------------------
39--------------------------------------------------------------------------------
46instance Writable CopyFile where
40instance Writable CopyFile where
47−#if MIN_VERSION_directory(1,2,6)
48− write dst (Item _ (CopyFile src)) = copyFileWithMetadata src dst
49−#else
50 write dst (Item _ (CopyFile src)) = copyFile src dst
41 write dst (Item _ (CopyFile src)) = copyFile src dst
51−#endif
42+
43+
52--------------------------------------------------------------------------------
44--------------------------------------------------------------------------------
53copyFileCompiler :: Compiler (Item CopyFile)
45copyFileCompiler :: Compiler (Item CopyFile)
54copyFileCompiler = do
46copyFileCompiler = do
lib/Hakyll/Core/Identifier.hs → src/Hakyll/Core/Identifier.hsrenamed+1−1
@@ -62,7 +62,7 @@ instance Show Identifier where
62
62
63--------------------------------------------------------------------------------
63--------------------------------------------------------------------------------
64-- | Parse an identifier from a string
64-- | Parse an identifier from a string
65−fromFilePath :: FilePath -> Identifier
65+fromFilePath :: String -> Identifier
66fromFilePath = Identifier Nothing .
66fromFilePath = Identifier Nothing .
67 intercalate "/" . filter (not . null) . split'
67 intercalate "/" . filter (not . null) . split'
68 where
68 where
lib/Hakyll/Core/Identifier/Pattern.hs → src/Hakyll/Core/Identifier/Pattern.hsrenamed+72−14
@@ -27,8 +27,7 @@
27-- * @\"foo\/*.html\"@ will match all HTML files in the @\"foo\/\"@ directory.
27-- * @\"foo\/*.html\"@ will match all HTML files in the @\"foo\/\"@ directory.
28--
28--
29-- The 'capture' function allows the user to get access to the elements captured
29-- The 'capture' function allows the user to get access to the elements captured
30−-- by the capture elements in a glob or regex pattern.
30+-- by the capture elements in the pattern.
31−{-# OPTIONS_GHC -fno-warn-orphans #-}
32module Hakyll.Core.Identifier.Pattern
31module Hakyll.Core.Identifier.Pattern
33 ( -- * The pattern type
32 ( -- * The pattern type
34 Pattern
33 Pattern
@@ -58,22 +57,77 @@ module Hakyll.Core.Identifier.Pattern
58
57
59
58
60--------------------------------------------------------------------------------
59--------------------------------------------------------------------------------
61−import Control.Arrow ((&&&), (>>>))
60+import Control.Arrow ((&&&), (>>>))
62−import Control.Monad (msum)
61+import Control.Monad (msum)
62+import Data.Binary (Binary (..), getWord8, putWord8)
63−import Data.List (inits, isPrefixOf,
63+import Data.List (inits, isPrefixOf, tails)
64− tails)
65−import Data.Maybe (isJust)
64+import Data.Maybe (isJust)
65+import Data.Set (Set)
66−import qualified Data.Set as S
66+import qualified Data.Set as S
67
67
68
68
69--------------------------------------------------------------------------------
69--------------------------------------------------------------------------------
70−import GHC.Exts (IsString, fromString)
70+import GHC.Exts (IsString, fromString)
71−import Text.Regex.TDFA ((=~))
71+import Text.Regex.TDFA ((=~))
72
72
73
73
74--------------------------------------------------------------------------------
74--------------------------------------------------------------------------------
75import Hakyll.Core.Identifier
75import Hakyll.Core.Identifier
76−import Hakyll.Core.Identifier.Pattern.Internal
76+
77+
78+--------------------------------------------------------------------------------
79+-- | Elements of a glob pattern
80+data GlobComponent
81+ = Capture
82+ | CaptureMany
83+ | Literal String
84+ deriving (Eq, Show)
85+
86+
87+--------------------------------------------------------------------------------
88+instance Binary GlobComponent where
89+ put Capture = putWord8 0
90+ put CaptureMany = putWord8 1
91+ put (Literal s) = putWord8 2 >> put s
92+
93+ get = getWord8 >>= \t -> case t of
94+ 0 -> pure Capture
95+ 1 -> pure CaptureMany
96+ 2 -> Literal <$> get
97+ _ -> error "Data.Binary.get: Invalid GlobComponent"
98+
99+
100+--------------------------------------------------------------------------------
101+-- | Type that allows matching on identifiers
102+data Pattern
103+ = Everything
104+ | Complement Pattern
105+ | And Pattern Pattern
106+ | Glob [GlobComponent]
107+ | List (Set Identifier)
108+ | Regex String
109+ | Version (Maybe String)
110+ deriving (Show)
111+
112+
113+--------------------------------------------------------------------------------
114+instance Binary Pattern where
115+ put Everything = putWord8 0
116+ put (Complement p) = putWord8 1 >> put p
117+ put (And x y) = putWord8 2 >> put x >> put y
118+ put (Glob g) = putWord8 3 >> put g
119+ put (List is) = putWord8 4 >> put is
120+ put (Regex r) = putWord8 5 >> put r
121+ put (Version v) = putWord8 6 >> put v
122+
123+ get = getWord8 >>= \t -> case t of
124+ 0 -> pure Everything
125+ 1 -> Complement <$> get
126+ 2 -> And <$> get <*> get
127+ 3 -> Glob <$> get
128+ 4 -> List <$> get
129+ 5 -> Regex <$> get
130+ _ -> Version <$> get
77
131
78
132
79--------------------------------------------------------------------------------
133--------------------------------------------------------------------------------
@@ -81,6 +135,12 @@ instance IsString Pattern where
81 fromString = fromGlob
135 fromString = fromGlob
82
136
83
137
138+--------------------------------------------------------------------------------
139+instance Monoid Pattern where
140+ mempty = Everything
141+ mappend = (.&&.)
142+
143+
84--------------------------------------------------------------------------------
144--------------------------------------------------------------------------------
85-- | Parse a pattern from a string
145-- | Parse a pattern from a string
86fromGlob :: String -> Pattern
146fromGlob :: String -> Pattern
@@ -200,11 +260,9 @@ splits = inits &&& tails >>> uncurry zip >>> reverse
200
260
201
261
202--------------------------------------------------------------------------------
262--------------------------------------------------------------------------------
203−-- | Match a glob or regex pattern against an identifier, generating a list of captures
263+-- | Match a glob against a pattern, generating a list of captures
204capture :: Pattern -> Identifier -> Maybe [String]
264capture :: Pattern -> Identifier -> Maybe [String]
205capture (Glob p) i = capture' p (toFilePath i)
265capture (Glob p) i = capture' p (toFilePath i)
206−capture (Regex pat) i = Just groups
207− where (_, _, _, groups) = ((toFilePath i) =~ pat) :: (String, String, String, [String])
208capture _ _ = Nothing
266capture _ _ = Nothing
209
267
210
268
lib/Hakyll/Core/Item.hs → src/Hakyll/Core/Item.hsrenamed

The content is the same.

lib/Hakyll/Core/Item/SomeItem.hs → src/Hakyll/Core/Item/SomeItem.hsrenamed

The content is the same.

lib/Hakyll/Core/Logger.hs → src/Hakyll/Core/Logger.hsrenamed+3−9
@@ -18,7 +18,6 @@ import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
18import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)
18import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)
19import Control.Monad (forever)
19import Control.Monad (forever)
20import Control.Monad.Trans (MonadIO, liftIO)
20import Control.Monad.Trans (MonadIO, liftIO)
21−import Data.List (intercalate)
22import Prelude hiding (error)
21import Prelude hiding (error)
23
22
24
23
@@ -80,7 +79,7 @@ string l v m
80
79
81--------------------------------------------------------------------------------
80--------------------------------------------------------------------------------
82error :: MonadIO m => Logger -> String -> m ()
81error :: MonadIO m => Logger -> String -> m ()
83−error l m = string l Error $ " [ERROR] " ++ indent m
82+error l m = string l Error $ " [ERROR] " ++ m
84
83
85
84
86--------------------------------------------------------------------------------
85--------------------------------------------------------------------------------
@@ -90,14 +89,9 @@ header l = string l Message
90
89
91--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
92message :: MonadIO m => Logger -> String -> m ()
91message :: MonadIO m => Logger -> String -> m ()
93−message l m = string l Message $ " " ++ indent m
92+message l m = string l Message $ " " ++ m
94
93
95
94
96--------------------------------------------------------------------------------
95--------------------------------------------------------------------------------
97debug :: MonadIO m => Logger -> String -> m ()
96debug :: MonadIO m => Logger -> String -> m ()
98−debug l m = string l Debug $ " [DEBUG] " ++ indent m
97+debug l m = string l Debug $ " [DEBUG] " ++ m
99−
100−
101−--------------------------------------------------------------------------------
102−indent :: String -> String
103−indent = intercalate "\n " . lines
lib/Hakyll/Core/Metadata.hs → src/Hakyll/Core/Metadata.hsrenamed

The content is the same.

lib/Hakyll/Core/Provider.hs → src/Hakyll/Core/Provider.hsrenamed

The content is the same.

lib/Hakyll/Core/Provider/Internal.hs → src/Hakyll/Core/Provider/Internal.hsrenamed

The content is the same.

lib/Hakyll/Core/Provider/Metadata.hs → src/Hakyll/Core/Provider/Metadata.hsrenamed+2−3
@@ -27,7 +27,6 @@ import Hakyll.Core.Identifier
27import Hakyll.Core.Metadata
27import Hakyll.Core.Metadata
28import Hakyll.Core.Provider.Internal
28import Hakyll.Core.Provider.Internal
29import System.IO as IO
29import System.IO as IO
30−import System.IO.Error (modifyIOError, ioeSetLocation)
31
30
32
31
33--------------------------------------------------------------------------------
32--------------------------------------------------------------------------------
@@ -52,7 +51,7 @@ loadMetadata p identifier = do
52--------------------------------------------------------------------------------
51--------------------------------------------------------------------------------
53loadMetadataHeader :: FilePath -> IO (Metadata, String)
52loadMetadataHeader :: FilePath -> IO (Metadata, String)
54loadMetadataHeader fp = do
53loadMetadataHeader fp = do
55− fileContent <- modifyIOError (`ioeSetLocation` "loadMetadataHeader") $ readFile fp
54+ fileContent <- readFile fp
56 case parsePage fileContent of
55 case parsePage fileContent of
57 Right x -> return x
56 Right x -> return x
58 Left err -> throwIO $ MetadataException fp err
57 Left err -> throwIO $ MetadataException fp err
@@ -61,7 +60,7 @@ loadMetadataHeader fp = do
61--------------------------------------------------------------------------------
60--------------------------------------------------------------------------------
62loadMetadataFile :: FilePath -> IO Metadata
61loadMetadataFile :: FilePath -> IO Metadata
63loadMetadataFile fp = do
62loadMetadataFile fp = do
64− fileContent <- modifyIOError (`ioeSetLocation` "loadMetadataFile") $ B.readFile fp
63+ fileContent <- B.readFile fp
65 let errOrMeta = Yaml.decodeEither' fileContent
64 let errOrMeta = Yaml.decodeEither' fileContent
66 either (fail . show) return errOrMeta
65 either (fail . show) return errOrMeta
67
66
lib/Hakyll/Core/Provider/MetadataCache.hs → src/Hakyll/Core/Provider/MetadataCache.hsrenamed

The content is the same.

lib/Hakyll/Core/Routes.hs → src/Hakyll/Core/Routes.hsrenamed−17
@@ -25,7 +25,6 @@
25-- not appear in your site directory.
25-- not appear in your site directory.
26--
26--
27-- * If an item matches multiple routes, the first rule will be chosen.
27-- * If an item matches multiple routes, the first rule will be chosen.
28−{-# LANGUAGE CPP #-}
29{-# LANGUAGE Rank2Types #-}
28{-# LANGUAGE Rank2Types #-}
30module Hakyll.Core.Routes
29module Hakyll.Core.Routes
31 ( UsedMetadata
30 ( UsedMetadata
@@ -43,9 +42,6 @@ module Hakyll.Core.Routes
43
42
44
43
45--------------------------------------------------------------------------------
44--------------------------------------------------------------------------------
46−#if MIN_VERSION_base(4,9,0)
47−import Data.Semigroup (Semigroup (..))
48−#endif
49import System.FilePath (replaceExtension)
45import System.FilePath (replaceExtension)
50
46
51
47
@@ -78,18 +74,6 @@ newtype Routes = Routes
78
74
79
75
80--------------------------------------------------------------------------------
76--------------------------------------------------------------------------------
81−#if MIN_VERSION_base(4,9,0)
82−instance Semigroup Routes where
83− (<>) (Routes f) (Routes g) = Routes $ \p id' -> do
84− (mfp, um) <- f p id'
85− case mfp of
86− Nothing -> g p id'
87− Just _ -> return (mfp, um)
88−
89−instance Monoid Routes where
90− mempty = Routes $ \_ _ -> return (Nothing, False)
91− mappend = (<>)
92−#else
93instance Monoid Routes where
77instance Monoid Routes where
94 mempty = Routes $ \_ _ -> return (Nothing, False)
78 mempty = Routes $ \_ _ -> return (Nothing, False)
95 mappend (Routes f) (Routes g) = Routes $ \p id' -> do
79 mappend (Routes f) (Routes g) = Routes $ \p id' -> do
@@ -97,7 +81,6 @@ instance Monoid Routes where
97 case mfp of
81 case mfp of
98 Nothing -> g p id'
82 Nothing -> g p id'
99 Just _ -> return (mfp, um)
83 Just _ -> return (mfp, um)
100−#endif
101
84
102
85
103--------------------------------------------------------------------------------
86--------------------------------------------------------------------------------
lib/Hakyll/Core/Rules.hs → src/Hakyll/Core/Rules.hsrenamed

The content is the same.

lib/Hakyll/Core/Rules/Internal.hs → src/Hakyll/Core/Rules/Internal.hsrenamed−14
@@ -1,5 +1,4 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2−{-# LANGUAGE CPP #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE Rank2Types #-}
3{-# LANGUAGE Rank2Types #-}
5module Hakyll.Core.Rules.Internal
4module Hakyll.Core.Rules.Internal
@@ -17,9 +16,6 @@ import Control.Monad.Reader (ask)
17import Control.Monad.RWS (RWST, runRWST)
16import Control.Monad.RWS (RWST, runRWST)
18import Control.Monad.Trans (liftIO)
17import Control.Monad.Trans (liftIO)
19import qualified Data.Map as M
18import qualified Data.Map as M
20−#if MIN_VERSION_base(4,9,0)
21−import Data.Semigroup (Semigroup (..))
22−#endif
23import Data.Set (Set)
19import Data.Set (Set)
24
20
25
21
@@ -56,20 +52,10 @@ data RuleSet = RuleSet
56
52
57
53
58--------------------------------------------------------------------------------
54--------------------------------------------------------------------------------
59−#if MIN_VERSION_base(4,9,0)
60−instance Semigroup RuleSet where
61− (<>) (RuleSet r1 c1 s1 p1) (RuleSet r2 c2 s2 p2) =
62− RuleSet (mappend r1 r2) (mappend c1 c2) (mappend s1 s2) (p1 .||. p2)
63−
64−instance Monoid RuleSet where
65− mempty = RuleSet mempty mempty mempty mempty
66− mappend = (<>)
67−#else
68instance Monoid RuleSet where
55instance Monoid RuleSet where
69 mempty = RuleSet mempty mempty mempty mempty
56 mempty = RuleSet mempty mempty mempty mempty
70 mappend (RuleSet r1 c1 s1 p1) (RuleSet r2 c2 s2 p2) =
57 mappend (RuleSet r1 c1 s1 p1) (RuleSet r2 c2 s2 p2) =
71 RuleSet (mappend r1 r2) (mappend c1 c2) (mappend s1 s2) (p1 .||. p2)
58 RuleSet (mappend r1 r2) (mappend c1 c2) (mappend s1 s2) (p1 .||. p2)
72−#endif
73
59
74
60
75--------------------------------------------------------------------------------
61--------------------------------------------------------------------------------
lib/Hakyll/Core/Runtime.hs → src/Hakyll/Core/Runtime.hsrenamed+3−3
@@ -199,9 +199,9 @@ chase trail id'
199 result <- liftIO $ runCompiler compiler read'
199 result <- liftIO $ runCompiler compiler read'
200 case result of
200 case result of
201 -- Rethrow error
201 -- Rethrow error
202− CompilerError e -> throwError $ case compilerErrorMessages e of
202+ CompilerError [] -> throwError
203− [] -> "Compiler failed but no info given, try running with -v?"
203+ "Compiler failed but no info given, try running with -v?"
204− es -> intercalate "; " es
204+ CompilerError es -> throwError $ intercalate "; " es
205
205
206 -- Signal that a snapshot was saved ->
206 -- Signal that a snapshot was saved ->
207 CompilerSnapshot snapshot c -> do
207 CompilerSnapshot snapshot c -> do
lib/Hakyll/Core/Store.hs → src/Hakyll/Core/Store.hsrenamed+23−26
@@ -16,6 +16,7 @@ module Hakyll.Core.Store
16
16
17
17
18--------------------------------------------------------------------------------
18--------------------------------------------------------------------------------
19+import Control.Exception (IOException, handle)
19import qualified Crypto.Hash.MD5 as MD5
20import qualified Crypto.Hash.MD5 as MD5
20import Data.Binary (Binary, decode, encodeFile)
21import Data.Binary (Binary, decode, encodeFile)
21import qualified Data.ByteString as B
22import qualified Data.ByteString as B
@@ -26,13 +27,11 @@ import Data.Maybe (isJust)
26import qualified Data.Text as T
27import qualified Data.Text as T
27import qualified Data.Text.Encoding as T
28import qualified Data.Text.Encoding as T
28import Data.Typeable (TypeRep, Typeable, cast, typeOf)
29import Data.Typeable (TypeRep, Typeable, cast, typeOf)
29−import Numeric (showHex)
30import System.Directory (createDirectoryIfMissing)
30import System.Directory (createDirectoryIfMissing)
31import System.Directory (doesFileExist, removeFile)
31import System.Directory (doesFileExist, removeFile)
32import System.FilePath ((</>))
32import System.FilePath ((</>))
33import System.IO (IOMode (..), hClose, openFile)
33import System.IO (IOMode (..), hClose, openFile)
34−import System.IO.Error (catchIOError, ioeSetFileName,
34+import Text.Printf (printf)
35− ioeSetLocation, modifyIOError)
36
35
37
36
38--------------------------------------------------------------------------------
37--------------------------------------------------------------------------------
@@ -85,14 +84,6 @@ new inMemory directory = do
85 where
84 where
86 csize = Just 500
85 csize = Just 500
87
86
88−--------------------------------------------------------------------------------
89−withStore :: Store -> String -> (String -> FilePath -> IO a) -> [String] -> IO a
90−withStore store loc run identifier = modifyIOError handle $ run key path
91− where
92− key = hash identifier
93− path = storeDirectory store </> key
94− handle e = e `ioeSetFileName` (path ++ " for " ++ intercalate "/" identifier)
95− `ioeSetLocation` ("Store." ++ loc)
96
87
97--------------------------------------------------------------------------------
88--------------------------------------------------------------------------------
98-- | Auxiliary: add an item to the in-memory cache
89-- | Auxiliary: add an item to the in-memory cache
@@ -133,16 +124,17 @@ cacheDelete (Store _ (Just lru)) key = do
133--------------------------------------------------------------------------------
124--------------------------------------------------------------------------------
134-- | Store an item
125-- | Store an item
135set :: (Binary a, Typeable a) => Store -> [String] -> a -> IO ()
126set :: (Binary a, Typeable a) => Store -> [String] -> a -> IO ()
136−set store identifier value = withStore store "set" (\key path -> do
127+set store identifier value = do
137− encodeFile path value
128+ encodeFile (storeDirectory store </> key) value
138 cacheInsert store key value
129 cacheInsert store key value
130+ where
139− ) identifier
131+ key = hash identifier
140
132
141
133
142--------------------------------------------------------------------------------
134--------------------------------------------------------------------------------
143-- | Load an item
135-- | Load an item
144get :: (Binary a, Typeable a) => Store -> [String] -> IO (Result a)
136get :: (Binary a, Typeable a) => Store -> [String] -> IO (Result a)
145−get store = withStore store "get" $ \key path -> do
137+get store identifier = do
146 -- First check the in-memory map
138 -- First check the in-memory map
147 ref <- cacheLookup store key
139 ref <- cacheLookup store key
148 case ref of
140 case ref of
@@ -154,14 +146,17 @@ get store = withStore store "get" $ \key path -> do
154 then return NotFound
146 then return NotFound
155 -- Found in the filesystem
147 -- Found in the filesystem
156 else do
148 else do
157− v <- decodeClose path
149+ v <- decodeClose
158 cacheInsert store key v
150 cacheInsert store key v
159 return $ Found v
151 return $ Found v
160 -- Found in the in-memory map (or wrong type), just return
152 -- Found in the in-memory map (or wrong type), just return
161 s -> return s
153 s -> return s
162 where
154 where
155+ key = hash identifier
156+ path = storeDirectory store </> key
157+
163 -- 'decodeFile' from Data.Binary which closes the file ASAP
158 -- 'decodeFile' from Data.Binary which closes the file ASAP
164− decodeClose path = do
159+ decodeClose = do
165 h <- openFile path ReadMode
160 h <- openFile path ReadMode
166 lbs <- BL.hGetContents h
161 lbs <- BL.hGetContents h
167 BL.length lbs `seq` hClose h
162 BL.length lbs `seq` hClose h
@@ -171,30 +166,32 @@ get store = withStore store "get" $ \key path -> do
171--------------------------------------------------------------------------------
166--------------------------------------------------------------------------------
172-- | Strict function
167-- | Strict function
173isMember :: Store -> [String] -> IO Bool
168isMember :: Store -> [String] -> IO Bool
174−isMember store = withStore store "isMember" $ \key path -> do
169+isMember store identifier = do
175 inCache <- cacheIsMember store key
170 inCache <- cacheIsMember store key
176 if inCache then return True else doesFileExist path
171 if inCache then return True else doesFileExist path
172+ where
173+ key = hash identifier
174+ path = storeDirectory store </> key
177
175
178
176
179--------------------------------------------------------------------------------
177--------------------------------------------------------------------------------
180-- | Delete an item
178-- | Delete an item
181delete :: Store -> [String] -> IO ()
179delete :: Store -> [String] -> IO ()
182−delete store = withStore store "delete" $ \key path -> do
180+delete store identifier = do
183 cacheDelete store key
181 cacheDelete store key
184− deleteFile path
182+ deleteFile $ storeDirectory store </> key
183+ where
184+ key = hash identifier
185
185
186
186
187--------------------------------------------------------------------------------
187--------------------------------------------------------------------------------
188-- | Delete a file unless it doesn't exist...
188-- | Delete a file unless it doesn't exist...
189deleteFile :: FilePath -> IO ()
189deleteFile :: FilePath -> IO ()
190−deleteFile = (`catchIOError` \_ -> return ()) . removeFile
190+deleteFile = handle (\(_ :: IOException) -> return ()) . removeFile
191
191
192
192
193--------------------------------------------------------------------------------
193--------------------------------------------------------------------------------
194-- | Mostly meant for internal usage
194-- | Mostly meant for internal usage
195hash :: [String] -> String
195hash :: [String] -> String
196+hash = concatMap (printf "%02x") . B.unpack .
196−hash = toHex . B.unpack . MD5.hash . T.encodeUtf8 . T.pack . intercalate "/"
197+ MD5.hash . T.encodeUtf8 . T.pack . intercalate "/"
197− where
198− toHex [] = ""
199− toHex (x : xs) | x < 16 = '0' : showHex x (toHex xs)
200− | otherwise = showHex x (toHex xs)
lib/Hakyll/Core/UnixFilter.hs → src/Hakyll/Core/UnixFilter.hsrenamed+1−2
@@ -92,8 +92,7 @@ unixFilterWith writer reader programName args input = do
92 ExitSuccess -> return output
92 ExitSuccess -> return output
93 ExitFailure e -> fail $
93 ExitFailure e -> fail $
94 "Hakyll.Core.UnixFilter.unixFilterWith: " ++
94 "Hakyll.Core.UnixFilter.unixFilterWith: " ++
95− unwords (programName : args) ++ " gave exit code " ++ show e ++
95+ unwords (programName : args) ++ " gave exit code " ++ show e
96− ". (Error: " ++ err ++ ")"
97
96
98
97
99--------------------------------------------------------------------------------
98--------------------------------------------------------------------------------
lib/Hakyll/Core/Util/File.hs → src/Hakyll/Core/Util/File.hsrenamed

The content is the same.

lib/Hakyll/Core/Util/Parser.hs → src/Hakyll/Core/Util/Parser.hsrenamed+1
@@ -2,6 +2,7 @@
2-- | Parser utilities
2-- | Parser utilities
3module Hakyll.Core.Util.Parser
3module Hakyll.Core.Util.Parser
4 ( metadataKey
4 ( metadataKey
5+ , reservedKeys
5 ) where
6 ) where
6
7
7
8
lib/Hakyll/Core/Util/String.hs → src/Hakyll/Core/Util/String.hsrenamed+1−1
@@ -27,7 +27,7 @@ trim = reverse . trim' . reverse . trim'
27--------------------------------------------------------------------------------
27--------------------------------------------------------------------------------
28-- | A simple (but inefficient) regex replace funcion
28-- | A simple (but inefficient) regex replace funcion
29replaceAll :: String -- ^ Pattern
29replaceAll :: String -- ^ Pattern
30− -> (String -> String) -- ^ Replacement (called on match)
30+ -> (String -> String) -- ^ Replacement (called on capture)
31 -> String -- ^ Source string
31 -> String -- ^ Source string
32 -> String -- ^ Result
32 -> String -- ^ Result
33replaceAll pattern f source = replaceAll' source
33replaceAll pattern f source = replaceAll' source
lib/Hakyll/Core/Writable.hs → src/Hakyll/Core/Writable.hsrenamed

The content is the same.

src/Init.hs → src/Hakyll/Init.hsrenamed+17−44
@@ -6,12 +6,12 @@ module Main
6
6
7--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
8import Control.Arrow (first)
8import Control.Arrow (first)
9−import Control.Monad (forM, forM_)
9+import Control.Monad (forM_)
10import Data.Char (isAlphaNum, isNumber)
10import Data.Char (isAlphaNum, isNumber)
11−import Data.List (foldl', intercalate, isPrefixOf)
11+import Data.List (foldl')
12+import Data.List (intercalate, isPrefixOf)
12import Data.Version (Version (..))
13import Data.Version (Version (..))
13−import System.Directory (canonicalizePath, copyFile,
14+import System.Directory (canonicalizePath, copyFile)
14− doesFileExist)
15import System.Environment (getArgs, getProgName)
15import System.Environment (getArgs, getProgName)
16import System.Exit (exitFailure)
16import System.Exit (exitFailure)
17import System.FilePath (splitDirectories, (</>))
17import System.FilePath (splitDirectories, (</>))
@@ -22,10 +22,6 @@ import Hakyll.Core.Util.File
22import Paths_hakyll
22import Paths_hakyll
23
23
24
24
25−--------------------------------------------------------------------------------
26−import Prelude
27−
28−
29--------------------------------------------------------------------------------
25--------------------------------------------------------------------------------
30main :: IO ()
26main :: IO ()
31main = do
27main = do
@@ -41,44 +37,21 @@ main = do
41 -- If dstDir begins with hyphens, the guard will prevent it from creating
37 -- If dstDir begins with hyphens, the guard will prevent it from creating
42 -- directory with that name so we can fall to the second alternative
38 -- directory with that name so we can fall to the second alternative
43 -- which prints a usage info for user.
39 -- which prints a usage info for user.
44− [dstDir] | not ("-" `isPrefixOf` dstDir) ->
40+ [dstDir] | not ("-" `isPrefixOf` dstDir) -> do
45− createFiles False srcDir files dstDir
41+ forM_ files $ \file -> do
46− ["-f", dstDir] ->
42+ let dst = dstDir </> file
47− createFiles True srcDir files dstDir
43+ src = srcDir </> file
48− _ -> do
44+ putStrLn $ "Creating " ++ dst
49− putStrLn $ "Usage: " ++ progName ++ "[-f] <directory>"
45+ makeDirectories dst
50− exitFailure
46+ copyFile src dst
51
47
52− where
53− createFiles force srcDir files dstDir = do
54 name <- makeName dstDir
48 name <- makeName dstDir
55 let cabalPath = dstDir </> name ++ ".cabal"
49 let cabalPath = dstDir </> name ++ ".cabal"
56−
57− diff <- if force then return []
58− else existingFiles dstDir (cabalPath : files)
59−
60− case diff of
61− [] -> do
62− forM_ files $ \file -> do
63− let dst = dstDir </> file
64− src = srcDir </> file
65− putStrLn $ "Creating " ++ dst
50+ putStrLn $ "Creating " ++ cabalPath
66− makeDirectories dst
67− copyFile src dst
68−
69− putStrLn $ "Creating " ++ cabalPath
70− createCabal cabalPath name
51+ createCabal cabalPath name
71− fs -> do
52+ _ -> do
72− putStrLn $ "The following files will be overwritten:"
53+ putStrLn $ "Usage: " ++ progName ++ " <directory>"
73− mapM_ putStrLn fs
74− putStrLn $ "Use -f to overwrite them"
75− exitFailure
54+ exitFailure
76−
77−existingFiles :: FilePath -> [FilePath] -> IO [FilePath]
78−existingFiles dstDir files = fmap concat $ forM files $ \file -> do
79− let dst = dstDir </> file
80− exists <- doesFileExist dst
81− return $ if exists then [dst] else []
82
55
83-- | Figure out a good cabal package name from the given (existing) directory
56-- | Figure out a good cabal package name from the given (existing) directory
84-- name
57-- name
@@ -104,7 +77,7 @@ makeName dstDir = do
104 safeLast = foldl' (\_ x -> Just x) Nothing
77 safeLast = foldl' (\_ x -> Just x) Nothing
105
78
106createCabal :: FilePath -> String -> IO ()
79createCabal :: FilePath -> String -> IO ()
107−createCabal path name =
80+createCabal path name = do
108 writeFile path $ unlines [
81 writeFile path $ unlines [
109 "name: " ++ name
82 "name: " ++ name
110 , "version: 0.1.0.0"
83 , "version: 0.1.0.0"
src/Hakyll/Main.hsnew file+110
@@ -0,0 +1,110 @@
1+--------------------------------------------------------------------------------
2+-- | Module providing the main hakyll function and command-line argument parsing
3+{-# LANGUAGE CPP #-}
4+{-# LANGUAGE DeriveDataTypeable #-}
5+module Hakyll.Main
6+ ( hakyll
7+ , hakyllWith
8+ , hakyllWithExitCode
9+ ) where
10+
11+
12+--------------------------------------------------------------------------------
13+import System.Environment (getProgName)
14+import System.IO.Unsafe (unsafePerformIO)
15+import System.Exit (ExitCode(ExitSuccess), exitWith)
16+
17+
18+--------------------------------------------------------------------------------
19+import Data.Monoid ((<>))
20+import Options.Applicative
21+
22+
23+--------------------------------------------------------------------------------
24+import qualified Hakyll.Check as Check
25+import qualified Hakyll.Commands as Commands
26+import qualified Hakyll.Core.Configuration as Config
27+import qualified Hakyll.Core.Logger as Logger
28+import Hakyll.Core.Rules
29+
30+
31+--------------------------------------------------------------------------------
32+-- | This usualy is the function with which the user runs the hakyll compiler
33+hakyll :: Rules a -> IO ()
34+hakyll = hakyllWith Config.defaultConfiguration
35+
36+--------------------------------------------------------------------------------
37+-- | A variant of 'hakyll' which allows the user to specify a custom
38+-- configuration
39+hakyllWith :: Config.Configuration -> Rules a -> IO ()
40+hakyllWith conf rules = hakyllWithExitCode conf rules >>= exitWith
41+
42+hakyllWithExitCode :: Config.Configuration -> Rules a -> IO ExitCode
43+hakyllWithExitCode conf rules = do
44+ args' <- customExecParser (prefs showHelpOnError) (info (helper <*> optionParser conf) (fullDesc <> progDesc (progName ++ " - Static site compiler created with Hakyll")))
45+ let args'' = optCommand args'
46+
47+ let verbosity' = if verbosity args' then Logger.Debug else Logger.Message
48+ check' =
49+ if internal_links args'' then Check.InternalLinks else Check.All
50+
51+ logger <- Logger.new verbosity'
52+
53+ case args'' of
54+ Build -> Commands.build conf logger rules
55+ Check _ -> Commands.check conf logger check'
56+ Clean -> Commands.clean conf logger >> ok
57+ Deploy -> Commands.deploy conf
58+ Preview p -> Commands.preview conf logger rules p >> ok
59+ Rebuild -> Commands.rebuild conf logger rules
60+ Server _ _ -> Commands.server conf logger (host args'') (port args'') >> ok
61+ Watch _ p s -> Commands.watch conf logger (host args'') p (not s) rules >> ok
62+ where
63+ ok = return ExitSuccess
64+
65+
66+--------------------------------------------------------------------------------
67+
68+data Options = Options {verbosity :: Bool, optCommand :: Command}
69+ deriving (Show)
70+
71+data Command
72+ = Build
73+ | Check {internal_links :: Bool}
74+ | Clean
75+ | Deploy
76+ | Preview {port :: Int}
77+ | Rebuild
78+ | Server {host :: String, port :: Int}
79+ | Watch {host :: String, port :: Int, no_server :: Bool }
80+ deriving (Show)
81+
82+optionParser :: Config.Configuration -> Parser Options
83+optionParser conf = Options <$> verboseParser <*> (commandParser conf)
84+ where
85+ verboseParser = switch (long "verbose" <> short 'v' <> help "Run in verbose mode")
86+
87+
88+commandParser :: Config.Configuration -> Parser Command
89+commandParser conf = subparser $ foldr ((<>) . produceCommand) mempty commands
90+ where
91+ produceCommand (a,b) = command a (info (helper <*> (fst b)) (snd b))
92+ portParser = option auto (long "port" <> help "Port to listen on" <> value (Config.previewPort conf))
93+ hostParser = strOption (long "host" <> help "Host to bind on" <> value (Config.previewHost conf))
94+ commands = [
95+ ("build",(pure Build,fullDesc <> progDesc "Generate the site")),
96+ ("check",(pure Check <*> switch (long "internal-links" <> help "Check internal links only"), fullDesc <> progDesc "Validate the site output")),
97+ ("clean",(pure Clean,fullDesc <> progDesc "Clean up and remove cache")),
98+ ("deploy",(pure Deploy,fullDesc <> progDesc "Upload/deploy your site")),
99+ ("preview",(pure Preview <*> portParser,fullDesc <> progDesc "[DEPRECATED] Please use the watch command")),
100+ ("rebuild",(pure Rebuild,fullDesc <> progDesc "Clean and build again")),
101+ ("server",(pure Server <*> hostParser <*> portParser,fullDesc <> progDesc "Start a preview server")),
102+ ("watch",(pure Watch <*> hostParser <*> portParser <*> switch (long "no-server" <> help "Disable the built-in web server"),fullDesc <> progDesc "Autocompile on changes and start a preview server. You can watch and recompile without running a server with --no-server."))
103+ ]
104+
105+
106+--------------------------------------------------------------------------------
107+-- | This is necessary because not everyone calls their program the same...
108+progName :: String
109+progName = unsafePerformIO getProgName
110+{-# NOINLINE progName #-}
lib/Hakyll/Preview/Poll.hs → src/Hakyll/Preview/Poll.hsrenamed+18−8
@@ -14,7 +14,8 @@ import Control.Exception (AsyncException, fromException,
14import Control.Monad (forever, void, when)
14import Control.Monad (forever, void, when)
15import System.Directory (canonicalizePath)
15import System.Directory (canonicalizePath)
16import System.FilePath (pathSeparators)
16import System.FilePath (pathSeparators)
17−import qualified System.FSNotify as FSNotify
17+import System.FSNotify (Event (..), startManager,
18+ watchTree)
18
19
19#ifdef mingw32_HOST_OS
20#ifdef mingw32_HOST_OS
20import Control.Concurrent (threadDelay)
21import Control.Concurrent (threadDelay)
@@ -43,12 +44,12 @@ watchUpdates conf update = do
43 shouldBuild <- newEmptyMVar
44 shouldBuild <- newEmptyMVar
44 pattern <- update
45 pattern <- update
45 fullProviderDir <- canonicalizePath $ providerDirectory conf
46 fullProviderDir <- canonicalizePath $ providerDirectory conf
46− manager <- FSNotify.startManager
47+ manager <- startManager
47
48
48 let allowed event = do
49 let allowed event = do
49 -- Absolute path of the changed file. This must be inside provider
50 -- Absolute path of the changed file. This must be inside provider
50 -- dir, since that's the only dir we're watching.
51 -- dir, since that's the only dir we're watching.
51− let path = FSNotify.eventPath event
52+ let path = eventPath event
52 relative = dropWhile (`elem` pathSeparators) $
53 relative = dropWhile (`elem` pathSeparators) $
53 drop (length fullProviderDir) path
54 drop (length fullProviderDir) path
54 identifier = fromFilePath relative
55 identifier = fromFilePath relative
@@ -68,7 +69,7 @@ watchUpdates conf update = do
68
69
69 -- Send an event whenever something occurs so that the thread described
70 -- Send an event whenever something occurs so that the thread described
70 -- above will do a build.
71 -- above will do a build.
71− void $ FSNotify.watchTree manager providerDir (not . isRemove) $ \event -> do
72+ void $ watchTree manager providerDir (not . isRemove) $ \event -> do
72 allowed' <- allowed event
73 allowed' <- allowed event
73 when allowed' $ void $ tryPutMVar shouldBuild event
74 when allowed' $ void $ tryPutMVar shouldBuild event
74 where
75 where
@@ -76,7 +77,7 @@ watchUpdates conf update = do
76 update' _ _ = void update
77 update' _ _ = void update
77#else
78#else
78 update' event provider = do
79 update' event provider = do
79− let path = provider </> FSNotify.eventPath event
80+ let path = provider </> eventPath event
80 -- on windows, a 'Modified' event is also sent on file deletion
81 -- on windows, a 'Modified' event is also sent on file deletion
81 fileExists <- doesFileExist path
82 fileExists <- doesFileExist path
82
83
@@ -104,6 +105,15 @@ watchUpdates conf update = do
104
105
105
106
106--------------------------------------------------------------------------------
107--------------------------------------------------------------------------------
108+eventPath :: Event -> FilePath
109+eventPath evt = evtPath evt
110+ where
111+ evtPath (Added p _) = p
112+ evtPath (Modified p _) = p
113+ evtPath (Removed p _) = p
114+
115+
116+--------------------------------------------------------------------------------
107−isRemove :: FSNotify.Event -> Bool
117+isRemove :: Event -> Bool
108−isRemove (FSNotify.Removed {}) = True
118+isRemove (Removed _ _) = True
109−isRemove _ = False
119+isRemove _ = False
lib/Hakyll/Preview/Server.hs → src/Hakyll/Preview/Server.hsrenamed

The content is the same.

src/Hakyll/Web/CompressCss.hsnew file+85
@@ -0,0 +1,85 @@
1+--------------------------------------------------------------------------------
2+-- | Module used for CSS compression. The compression is currently in a simple
3+-- state, but would typically reduce the number of bytes by about 25%.
4+module Hakyll.Web.CompressCss
5+ ( compressCssCompiler
6+ , compressCss
7+ ) where
8+
9+
10+--------------------------------------------------------------------------------
11+import Data.List (isPrefixOf)
12+
13+
14+--------------------------------------------------------------------------------
15+import Hakyll.Core.Compiler
16+import Hakyll.Core.Item
17+
18+
19+--------------------------------------------------------------------------------
20+-- | Compiler form of 'compressCss'
21+compressCssCompiler :: Compiler (Item String)
22+compressCssCompiler = fmap compressCss <$> getResourceString
23+
24+
25+--------------------------------------------------------------------------------
26+-- | Compress CSS to speed up your site.
27+compressCss :: String -> String
28+compressCss = compressSeparators . stripComments . compressWhitespace
29+
30+
31+--------------------------------------------------------------------------------
32+-- | Compresses certain forms of separators.
33+compressSeparators :: String -> String
34+compressSeparators [] = []
35+compressSeparators str
36+ | isConstant = head str : retainConstants compressSeparators (head str) (drop 1 str)
37+ | stripFirst = compressSeparators (drop 1 str)
38+ | stripSecond = compressSeparators (head str : (drop 2 str))
39+ | otherwise = head str : compressSeparators (drop 1 str)
40+ where
41+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
42+ stripFirst = or $ map (isOfPrefix str) [" ", " {", " }", " :", ";;", ";}"]
43+ stripSecond = or $ map (isOfPrefix str) ["{ ", "} ", ": ", "; "]
44+
45+--------------------------------------------------------------------------------
46+-- | Compresses all whitespace.
47+compressWhitespace :: String -> String
48+compressWhitespace [] = []
49+compressWhitespace str
50+ | isConstant = head str : retainConstants compressWhitespace (head str) (drop 1 str)
51+ | replaceOne = compressWhitespace (' ' : (drop 1 str))
52+ | replaceTwo = compressWhitespace (' ' : (drop 2 str))
53+ | otherwise = head str : compressWhitespace (drop 1 str)
54+ where
55+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
56+ replaceOne = or $ map (isOfPrefix str) ["\t", "\n", "\r"]
57+ replaceTwo = or $ map (isOfPrefix str) [" \t", " \n", " \r", " "]
58+
59+--------------------------------------------------------------------------------
60+-- | Function that strips CSS comments away.
61+stripComments :: String -> String
62+stripComments [] = []
63+stripComments str
64+ | isConstant = head str : retainConstants stripComments (head str) (drop 1 str)
65+ | isPrefixOf "/*" str = stripComments $ eatComments $ drop 2 str
66+ | otherwise = head str : stripComments (drop 1 str)
67+ where
68+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
69+ eatComments str'
70+ | null str' = []
71+ | isPrefixOf "*/" str' = drop 2 str'
72+ | otherwise = eatComments $ drop 1 str'
73+
74+--------------------------------------------------------------------------------
75+-- | Helper function to handle string constants correctly.
76+retainConstants :: (String -> String) -> Char -> String -> String
77+retainConstants f delim str
78+ | null str = []
79+ | isPrefixOf [delim] str = head str : f (drop 1 str)
80+ | otherwise = head str : retainConstants f delim (drop 1 str)
81+
82+--------------------------------------------------------------------------------
83+-- | Helper function to determine whether a string is a substring.
84+isOfPrefix :: String -> String -> Bool
85+isOfPrefix = flip isPrefixOf
lib/Hakyll/Web/Feed.hs → src/Hakyll/Web/Feed.hsrenamed+21−59
@@ -1,6 +1,3 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE TemplateHaskell #-}
3−
4--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
5-- | A Module that allows easy rendering of RSS feeds.
2-- | A Module that allows easy rendering of RSS feeds.
6--
3--
@@ -23,40 +20,21 @@ module Hakyll.Web.Feed
23 ( FeedConfiguration (..)
20 ( FeedConfiguration (..)
24 , renderRss
21 , renderRss
25 , renderAtom
22 , renderAtom
26− , renderRssWithTemplates
27− , renderAtomWithTemplates
28 ) where
23 ) where
29
24
30
25
31--------------------------------------------------------------------------------
26--------------------------------------------------------------------------------
32import Hakyll.Core.Compiler
27import Hakyll.Core.Compiler
28+import Hakyll.Core.Compiler.Internal
33import Hakyll.Core.Item
29import Hakyll.Core.Item
34−import Hakyll.Core.Util.String (replaceAll)
30+import Hakyll.Core.Util.String (replaceAll)
35import Hakyll.Web.Template
31import Hakyll.Web.Template
36import Hakyll.Web.Template.Context
32import Hakyll.Web.Template.Context
37import Hakyll.Web.Template.List
33import Hakyll.Web.Template.List
38
34
39
35
40--------------------------------------------------------------------------------
36--------------------------------------------------------------------------------
41−import Data.FileEmbed (makeRelativeToProject)
37+import Paths_hakyll
42−
43−
44−--------------------------------------------------------------------------------
45−rssTemplate :: Template
46−rssTemplate =
47− $(makeRelativeToProject "data/templates/rss.xml" >>= embedTemplate)
48−
49−rssItemTemplate :: Template
50−rssItemTemplate =
51− $(makeRelativeToProject "data/templates/rss-item.xml" >>= embedTemplate)
52−
53−atomTemplate :: Template
54−atomTemplate =
55− $(makeRelativeToProject "data/templates/atom.xml" >>= embedTemplate)
56−
57−atomItemTemplate :: Template
58−atomItemTemplate =
59− $(makeRelativeToProject "data/templates/atom-item.xml" >>= embedTemplate)
60
38
61
39
62--------------------------------------------------------------------------------
40--------------------------------------------------------------------------------
@@ -77,13 +55,16 @@ data FeedConfiguration = FeedConfiguration
77
55
78--------------------------------------------------------------------------------
56--------------------------------------------------------------------------------
79-- | Abstract function to render any feed.
57-- | Abstract function to render any feed.
80−renderFeed :: Template -- ^ Default feed template
58+renderFeed :: FilePath -- ^ Feed template
81− -> Template -- ^ Default item template
59+ -> FilePath -- ^ Item template
82 -> FeedConfiguration -- ^ Feed configuration
60 -> FeedConfiguration -- ^ Feed configuration
83 -> Context String -- ^ Context for the items
61 -> Context String -- ^ Context for the items
84 -> [Item String] -- ^ Input items
62 -> [Item String] -- ^ Input items
85 -> Compiler (Item String) -- ^ Resulting item
63 -> Compiler (Item String) -- ^ Resulting item
86−renderFeed feedTpl itemTpl config itemContext items = do
64+renderFeed feedPath itemPath config itemContext items = do
65+ feedTpl <- loadTemplate feedPath
66+ itemTpl <- loadTemplate itemPath
67+
87 protectedItems <- mapM (applyFilter protectCDATA) items
68 protectedItems <- mapM (applyFilter protectCDATA) items
88 body <- makeItem =<< applyTemplateList itemTpl itemContext' protectedItems
69 body <- makeItem =<< applyTemplateList itemTpl itemContext' protectedItems
89 applyTemplate feedTpl feedContext body
70 applyTemplate feedTpl feedContext body
@@ -92,6 +73,10 @@ renderFeed feedTpl itemTpl config itemContext items = do
92 applyFilter tr str = return $ fmap tr str
73 applyFilter tr str = return $ fmap tr str
93 protectCDATA :: String -> String
74 protectCDATA :: String -> String
94 protectCDATA = replaceAll "]]>" (const "]]&gt;")
75 protectCDATA = replaceAll "]]>" (const "]]&gt;")
76+ -- Auxiliary: load a template from a datafile
77+ loadTemplate path = do
78+ file <- compilerUnsafeIO $ getDataFileName path
79+ unsafeReadTemplateFile file
95
80
96 itemContext' = mconcat
81 itemContext' = mconcat
97 [ itemContext
82 [ itemContext
@@ -117,35 +102,8 @@ renderFeed feedTpl itemTpl config itemContext items = do
117 updatedField = field "updated" $ \_ -> case items of
102 updatedField = field "updated" $ \_ -> case items of
118 [] -> return "Unknown"
103 [] -> return "Unknown"
119 (x : _) -> unContext itemContext' "updated" [] x >>= \cf -> case cf of
104 (x : _) -> unContext itemContext' "updated" [] x >>= \cf -> case cf of
105+ ListField _ _ -> fail "Hakyll.Web.Feed.renderFeed: Internal error"
120 StringField s -> return s
106 StringField s -> return s
121− _ -> fail "Hakyll.Web.Feed.renderFeed: Internal error"
122−
123−--------------------------------------------------------------------------------
124−-- | Render an RSS feed using given templates with a number of items.
125−renderRssWithTemplates ::
126− Template -- ^ Feed template
127− -> Template -- ^ Item template
128− -> FeedConfiguration -- ^ Feed configuration
129− -> Context String -- ^ Item context
130− -> [Item String] -- ^ Feed items
131− -> Compiler (Item String) -- ^ Resulting feed
132−renderRssWithTemplates feedTemplate itemTemplate config context = renderFeed
133− feedTemplate itemTemplate config
134− (makeItemContext "%a, %d %b %Y %H:%M:%S UT" context)
135−
136−
137−--------------------------------------------------------------------------------
138−-- | Render an Atom feed using given templates with a number of items.
139−renderAtomWithTemplates ::
140− Template -- ^ Feed template
141− -> Template -- ^ Item template
142− -> FeedConfiguration -- ^ Feed configuration
143− -> Context String -- ^ Item context
144− -> [Item String] -- ^ Feed items
145− -> Compiler (Item String) -- ^ Resulting feed
146−renderAtomWithTemplates feedTemplate itemTemplate config context = renderFeed
147− feedTemplate itemTemplate config
148− (makeItemContext "%Y-%m-%dT%H:%M:%SZ" context)
149
107
150
108
151--------------------------------------------------------------------------------
109--------------------------------------------------------------------------------
@@ -154,7 +112,9 @@ renderRss :: FeedConfiguration -- ^ Feed configuration
154 -> Context String -- ^ Item context
112 -> Context String -- ^ Item context
155 -> [Item String] -- ^ Feed items
113 -> [Item String] -- ^ Feed items
156 -> Compiler (Item String) -- ^ Resulting feed
114 -> Compiler (Item String) -- ^ Resulting feed
157−renderRss = renderRssWithTemplates rssTemplate rssItemTemplate
115+renderRss config context = renderFeed
116+ "templates/rss.xml" "templates/rss-item.xml" config
117+ (makeItemContext "%a, %d %b %Y %H:%M:%S UT" context)
158
118
159
119
160--------------------------------------------------------------------------------
120--------------------------------------------------------------------------------
@@ -163,11 +123,13 @@ renderAtom :: FeedConfiguration -- ^ Feed configuration
163 -> Context String -- ^ Item context
123 -> Context String -- ^ Item context
164 -> [Item String] -- ^ Feed items
124 -> [Item String] -- ^ Feed items
165 -> Compiler (Item String) -- ^ Resulting feed
125 -> Compiler (Item String) -- ^ Resulting feed
166−renderAtom = renderAtomWithTemplates atomTemplate atomItemTemplate
126+renderAtom config context = renderFeed
127+ "templates/atom.xml" "templates/atom-item.xml" config
128+ (makeItemContext "%Y-%m-%dT%H:%M:%SZ" context)
167
129
168
130
169--------------------------------------------------------------------------------
131--------------------------------------------------------------------------------
170-- | Copies @$updated$@ from @$published$@ if it is not already set.
132-- | Copies @$updated$@ from @$published$@ if it is not already set.
171makeItemContext :: String -> Context a -> Context a
133makeItemContext :: String -> Context a -> Context a
172makeItemContext fmt context = mconcat
134makeItemContext fmt context = mconcat
173− [context, dateField "published" fmt, dateField "updated" fmt]
135+ [dateField "published" fmt, context, dateField "updated" fmt]
lib/Hakyll/Web/Html.hs → src/Hakyll/Web/Html.hsrenamed+2−6
@@ -3,7 +3,6 @@
3module Hakyll.Web.Html
3module Hakyll.Web.Html
4 ( -- * Generic
4 ( -- * Generic
5 withTags
5 withTags
6− , withTagList
7
6
8 -- * Headers
7 -- * Headers
9 , demoteHeaders
8 , demoteHeaders
@@ -37,11 +36,8 @@ import Network.URI (isUnreserved, escapeURIString)
37--------------------------------------------------------------------------------
36--------------------------------------------------------------------------------
38-- | Map over all tags in the document
37-- | Map over all tags in the document
39withTags :: (TS.Tag String -> TS.Tag String) -> String -> String
38withTags :: (TS.Tag String -> TS.Tag String) -> String -> String
40−withTags = withTagList . map
39+withTags f = renderTags' . map f . parseTags'
41
40
42−-- | Map over all tags (as list) in the document
43−withTagList :: ([TS.Tag String] -> [TS.Tag String]) -> String -> String
44−withTagList f = renderTags' . f . parseTags'
45
41
46--------------------------------------------------------------------------------
42--------------------------------------------------------------------------------
47-- | Map every @h1@ to an @h2@, @h2@ to @h3@, etc.
43-- | Map every @h1@ to an @h2@, @h2@ to @h3@, etc.
@@ -59,7 +55,7 @@ demoteHeaders = withTags $ \tag -> case tag of
59
55
60--------------------------------------------------------------------------------
56--------------------------------------------------------------------------------
61isUrlAttribute :: String -> Bool
57isUrlAttribute :: String -> Bool
62−isUrlAttribute = (`elem` ["src", "href", "data", "poster", "srcset"])
58+isUrlAttribute = (`elem` ["src", "href", "data", "poster"])
63
59
64
60
65--------------------------------------------------------------------------------
61--------------------------------------------------------------------------------
lib/Hakyll/Web/Html/RelativizeUrls.hs → src/Hakyll/Web/Html/RelativizeUrls.hsrenamed

The content is the same.

lib/Hakyll/Web/Paginate.hs → src/Hakyll/Web/Paginate.hsrenamed+1−28
@@ -11,8 +11,7 @@ module Hakyll.Web.Paginate
11
11
12
12
13--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
14−import Control.Applicative (empty)
14+import Control.Monad (forM_)
15−import Control.Monad (forM_, forM)
16import qualified Data.Map as M
15import qualified Data.Map as M
17import qualified Data.Set as S
16import qualified Data.Set as S
18
17
@@ -94,18 +93,6 @@ paginatePage pag pageNumber
94-- | A default paginate context which provides the following keys:
93-- | A default paginate context which provides the following keys:
95--
94--
96--
95--
97−-- * @firstPageNum@
98−-- * @firstPageUrl@
99−-- * @previousPageNum@
100−-- * @previousPageUrl@
101−-- * @nextPageNum@
102−-- * @nextPageUrl@
103−-- * @lastPageNum@
104−-- * @lastPageUrl@
105−-- * @currentPageNum@
106−-- * @currentPageUrl@
107−-- * @numPages@
108−-- * @allPages@
109paginateContext :: Paginate -> PageNumber -> Context a
96paginateContext :: Paginate -> PageNumber -> Context a
110paginateContext pag currentPage = mconcat
97paginateContext pag currentPage = mconcat
111 [ field "firstPageNum" $ \_ -> otherPage 1 >>= num
98 [ field "firstPageNum" $ \_ -> otherPage 1 >>= num
@@ -119,20 +106,6 @@ paginateContext pag currentPage = mconcat
119 , field "currentPageNum" $ \i -> thisPage i >>= num
106 , field "currentPageNum" $ \i -> thisPage i >>= num
120 , field "currentPageUrl" $ \i -> thisPage i >>= url
107 , field "currentPageUrl" $ \i -> thisPage i >>= url
121 , constField "numPages" $ show $ paginateNumPages pag
108 , constField "numPages" $ show $ paginateNumPages pag
122− , Context $ \k _ i -> case k of
123− "allPages" -> do
124− let ctx =
125− field "isCurrent" (\n -> if fst (itemBody n) == currentPage then return "true" else empty) `mappend`
126− field "num" (num . itemBody) `mappend`
127− field "url" (url . itemBody)
128−
129− list <- forM [1 .. lastPage] $
130− \n -> if n == currentPage then thisPage i else otherPage n
131− items <- mapM makeItem list
132− return $ ListField ctx items
133− _ -> do
134− empty
135−
136 ]
109 ]
137 where
110 where
138 lastPage = paginateNumPages pag
111 lastPage = paginateNumPages pag
lib/Hakyll/Web/Pandoc.hs → src/Hakyll/Web/Pandoc.hsrenamed+12−13
@@ -22,9 +22,9 @@ module Hakyll.Web.Pandoc
22
22
23
23
24--------------------------------------------------------------------------------
24--------------------------------------------------------------------------------
25−import qualified Data.Text as T
25+import qualified Data.Set as S
26import Text.Pandoc
26import Text.Pandoc
27−import Text.Pandoc.Highlighting (pygments)
27+import Text.Pandoc.Error (PandocError (..))
28
28
29
29
30--------------------------------------------------------------------------------
30--------------------------------------------------------------------------------
@@ -48,10 +48,12 @@ readPandocWith
48 -> Item String -- ^ String to read
48 -> Item String -- ^ String to read
49 -> Compiler (Item Pandoc) -- ^ Resulting document
49 -> Compiler (Item Pandoc) -- ^ Resulting document
50readPandocWith ropt item =
50readPandocWith ropt item =
51− case runPure $ traverse (reader ropt (itemFileType item)) (fmap T.pack item) of
51+ case traverse (reader ropt (itemFileType item)) item of
52− Left err -> fail $
52+ Left (ParseFailure err) -> fail $
53+ "Hakyll.Web.Pandoc.readPandocWith: parse failed: " ++ err
54+ Left (ParsecError _ err) -> fail $
53 "Hakyll.Web.Pandoc.readPandocWith: parse failed: " ++ show err
55 "Hakyll.Web.Pandoc.readPandocWith: parse failed: " ++ show err
54− Right item' -> return item'
56+ Right item' -> return item'
55 where
57 where
56 reader ro t = case t of
58 reader ro t = case t of
57 DocBook -> readDocBook ro
59 DocBook -> readDocBook ro
@@ -67,7 +69,7 @@ readPandocWith ropt item =
67 "Hakyll.Web.readPandocWith: I don't know how to read a file of " ++
69 "Hakyll.Web.readPandocWith: I don't know how to read a file of " ++
68 "the type " ++ show t ++ " for: " ++ show (itemIdentifier item)
70 "the type " ++ show t ++ " for: " ++ show (itemIdentifier item)
69
71
70− addExt ro e = ro {readerExtensions = enableExtension e $ readerExtensions ro}
72+ addExt ro e = ro {readerExtensions = S.insert e $ readerExtensions ro}
71
73
72
74
73--------------------------------------------------------------------------------
75--------------------------------------------------------------------------------
@@ -82,10 +84,7 @@ writePandoc = writePandocWith defaultHakyllWriterOptions
82writePandocWith :: WriterOptions -- ^ Writer options for pandoc
84writePandocWith :: WriterOptions -- ^ Writer options for pandoc
83 -> Item Pandoc -- ^ Document to write
85 -> Item Pandoc -- ^ Document to write
84 -> Item String -- ^ Resulting HTML
86 -> Item String -- ^ Resulting HTML
85−writePandocWith wopt (Item itemi doc) =
87+writePandocWith wopt = fmap $ writeHtmlString wopt
86− case runPure $ writeHtml5String wopt doc of
87− Left err -> error $ "Hakyll.Web.Pandoc.writePandocWith: " ++ show err
88− Right item' -> Item itemi $ T.unpack item'
89
88
90
89
91--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
@@ -148,7 +147,7 @@ defaultHakyllReaderOptions :: ReaderOptions
148defaultHakyllReaderOptions = def
147defaultHakyllReaderOptions = def
149 { -- The following option causes pandoc to read smart typography, a nice
148 { -- The following option causes pandoc to read smart typography, a nice
150 -- and free bonus.
149 -- and free bonus.
151− readerExtensions = enableExtension Ext_smart pandocExtensions
150+ readerSmart = True
152 }
151 }
153
152
154
153
@@ -158,8 +157,8 @@ defaultHakyllWriterOptions :: WriterOptions
158defaultHakyllWriterOptions = def
157defaultHakyllWriterOptions = def
159 { -- This option causes literate haskell to be written using '>' marks in
158 { -- This option causes literate haskell to be written using '>' marks in
160 -- html, which I think is a good default.
159 -- html, which I think is a good default.
161− writerExtensions = enableExtension Ext_smart pandocExtensions
160+ writerExtensions = S.insert Ext_literate_haskell (writerExtensions def)
162 , -- We want to have hightlighting by default, to be compatible with earlier
161 , -- We want to have hightlighting by default, to be compatible with earlier
163 -- Hakyll releases
162 -- Hakyll releases
164− writerHighlightStyle = Just pygments
163+ writerHighlight = True
165 }
164 }
lib/Hakyll/Web/Pandoc/Biblio.hs → src/Hakyll/Web/Pandoc/Biblio.hsrenamed+6−17
@@ -25,19 +25,17 @@ module Hakyll.Web.Pandoc.Biblio
25--------------------------------------------------------------------------------
25--------------------------------------------------------------------------------
26import Control.Monad (liftM, replicateM)
26import Control.Monad (liftM, replicateM)
27import Data.Binary (Binary (..))
27import Data.Binary (Binary (..))
28+import Data.Default (def)
28import Data.Typeable (Typeable)
29import Data.Typeable (Typeable)
29import Hakyll.Core.Compiler
30import Hakyll.Core.Compiler
30−import Hakyll.Core.Compiler.Internal
31import Hakyll.Core.Identifier
31import Hakyll.Core.Identifier
32import Hakyll.Core.Item
32import Hakyll.Core.Item
33−import Hakyll.Core.Provider
34import Hakyll.Core.Writable
33import Hakyll.Core.Writable
35import Hakyll.Web.Pandoc
34import Hakyll.Web.Pandoc
36import Hakyll.Web.Pandoc.Binary ()
35import Hakyll.Web.Pandoc.Binary ()
37import qualified Text.CSL as CSL
36import qualified Text.CSL as CSL
38import Text.CSL.Pandoc (processCites)
37import Text.CSL.Pandoc (processCites)
39−import Text.Pandoc (Pandoc, ReaderOptions (..),
38+import Text.Pandoc (Pandoc, ReaderOptions (..))
40− enableExtension, Extension (..))
41
39
42
40
43--------------------------------------------------------------------------------
41--------------------------------------------------------------------------------
@@ -85,11 +83,8 @@ instance Writable Biblio where
85--------------------------------------------------------------------------------
83--------------------------------------------------------------------------------
86biblioCompiler :: Compiler (Item Biblio)
84biblioCompiler :: Compiler (Item Biblio)
87biblioCompiler = do
85biblioCompiler = do
88− filePath <- getResourceFilePath
86+ filePath <- toFilePath <$> getUnderlying
89− makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile idpred filePath)
87+ makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile filePath)
90− where
91− -- This is a filter on citations. We include all citations.
92− idpred = const True
93
88
94
89
95--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
@@ -100,9 +95,7 @@ readPandocBiblio :: ReaderOptions
100 -> Compiler (Item Pandoc)
95 -> Compiler (Item Pandoc)
101readPandocBiblio ropt csl biblio item = do
96readPandocBiblio ropt csl biblio item = do
102 -- Parse CSL file, if given
97 -- Parse CSL file, if given
103− provider <- compilerProvider <$> compilerAsk
104− style <- unsafeCompiler $
105− CSL.readCSLFile Nothing . (resourceFilePath provider) . itemIdentifier $ csl
98+ style <- unsafeCompiler $ CSL.readCSLFile Nothing . toFilePath . itemIdentifier $ csl
106
99
107 -- We need to know the citation keys, add then *before* actually parsing the
100 -- We need to know the citation keys, add then *before* actually parsing the
108 -- actual page. If we don't do this, pandoc won't even consider them
101 -- actual page. If we don't do this, pandoc won't even consider them
@@ -119,8 +112,4 @@ pandocBiblioCompiler cslFileName bibFileName = do
119 csl <- load $ fromFilePath cslFileName
112 csl <- load $ fromFilePath cslFileName
120 bib <- load $ fromFilePath bibFileName
113 bib <- load $ fromFilePath bibFileName
121 liftM writePandoc
114 liftM writePandoc
122− (getResourceBody >>= readPandocBiblio ropt csl bib)
115+ (getResourceBody >>= readPandocBiblio def csl bib)
123− where ropt = defaultHakyllReaderOptions
124− { -- The following option enables citation rendering
125− readerExtensions = enableExtension Ext_citations $ readerExtensions defaultHakyllReaderOptions
126− }
lib/Hakyll/Web/Pandoc/Binary.hs → src/Hakyll/Web/Pandoc/Binary.hsrenamed+17−19
@@ -1,33 +1,31 @@
1{-# OPTIONS_GHC -fno-warn-orphans #-}
1{-# OPTIONS_GHC -fno-warn-orphans #-}
2−{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE DeriveGeneric #-}
3module Hakyll.Web.Pandoc.Binary where
3module Hakyll.Web.Pandoc.Binary where
4
4
5−import Data.Binary (Binary (..))
5+import Data.Binary (Binary (..))
6
6
7−import qualified Text.CSL as CSL
7+import qualified Text.CSL as CSL
8−import qualified Text.CSL.Reference as REF
8+import qualified Text.CSL.Reference as REF
9−import qualified Text.CSL.Style as STY
9+import qualified Text.CSL.Style as STY
10−import Text.Pandoc
10+import Text.Pandoc
11
11
12--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
13-- orphans
13-- orphans
14
14
15−instance Binary Alignment
16−instance Binary Block
17−instance Binary CSL.Reference
18−instance Binary Citation
19−instance Binary CitationMode
20−instance Binary Format
21−instance Binary Inline
22−instance Binary ListNumberDelim
23−instance Binary ListNumberStyle
24−instance Binary MathType
25−instance Binary QuoteType
26−instance Binary REF.CLabel
27instance Binary REF.CNum
15instance Binary REF.CNum
28instance Binary REF.Literal
16instance Binary REF.Literal
29instance Binary REF.RefDate
17instance Binary REF.RefDate
30instance Binary REF.RefType
18instance Binary REF.RefType
31−instance Binary REF.Season
32instance Binary STY.Agent
19instance Binary STY.Agent
33instance Binary STY.Formatted
20instance Binary STY.Formatted
21+instance Binary Inline
22+instance Binary Block
23+instance Binary Citation
24+instance Binary MathType
25+instance Binary Alignment
26+instance Binary CitationMode
27+instance Binary QuoteType
28+instance Binary Format
29+instance Binary ListNumberDelim
30+instance Binary ListNumberStyle
31+instance Binary CSL.Reference
lib/Hakyll/Web/Pandoc/FileType.hs → src/Hakyll/Web/Pandoc/FileType.hsrenamed

The content is the same.

lib/Hakyll/Web/Redirect.hs → src/Hakyll/Web/Redirect.hsrenamed+1−14
@@ -7,9 +7,8 @@ module Hakyll.Web.Redirect
7 ) where
7 ) where
8
8
9import Control.Applicative ((<$>))
9import Control.Applicative ((<$>))
10−import Control.Monad (forM_, when)
10+import Control.Monad (forM_)
11import Data.Binary (Binary (..))
11import Data.Binary (Binary (..))
12−import Data.List (sort, group)
13import Hakyll.Core.Compiler
12import Hakyll.Core.Compiler
14import Hakyll.Core.Identifier
13import Hakyll.Core.Identifier
15import Hakyll.Core.Routes
14import Hakyll.Core.Routes
@@ -56,17 +55,6 @@ import Hakyll.Core.Writable (Writable (..))
56-- See also <https://groups.google.com/d/msg/hakyll/sWc6zxfh-uM/fUpZPsFNDgAJ>.
55-- See also <https://groups.google.com/d/msg/hakyll/sWc6zxfh-uM/fUpZPsFNDgAJ>.
57createRedirects :: [(Identifier, String)] -> Rules ()
56createRedirects :: [(Identifier, String)] -> Rules ()
58createRedirects redirects =
57createRedirects redirects =
59− do -- redirects are many-to-fewer; keys must be unique, and must point somewhere else:
60− let gkeys = group $ sort $ map fst redirects
61− forM_ gkeys $ \gkey -> case gkey of
62− (k : _ : _) -> fail $
63− "Duplicate 301 redirects; " ++ show k ++ " is ambiguous."
64− _ -> return ()
65−
66− forM_ redirects $ \(r, t) ->
67− when (toFilePath r == t) $ fail $
68− "Self-redirect detected: " ++ show r ++ " points to itself."
69−
70 forM_ redirects $ \(ident, to) ->
58 forM_ redirects $ \(ident, to) ->
71 create [ident] $ do
59 create [ident] $ do
72 route idRoute
60 route idRoute
@@ -93,7 +81,6 @@ instance Writable Redirect where
93redirectToHtml :: Redirect -> String
81redirectToHtml :: Redirect -> String
94redirectToHtml (Redirect working) =
82redirectToHtml (Redirect working) =
95 "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><meta name=\"generator\" content=\"hakyll\"/>" ++
83 "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><meta name=\"generator\" content=\"hakyll\"/>" ++
96− "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">" ++
97 "<meta http-equiv=\"refresh\" content=\"0; url=" ++ working ++
84 "<meta http-equiv=\"refresh\" content=\"0; url=" ++ working ++
98 "\"><link rel=\"canonical\" href=\"" ++ working ++
85 "\"><link rel=\"canonical\" href=\"" ++ working ++
99 "\"><title>Permanent Redirect</title></head><body><p>The page has moved to: <a href=\"" ++ working ++
86 "\"><title>Permanent Redirect</title></head><body><p>The page has moved to: <a href=\"" ++ working ++
lib/Hakyll/Web/Tags.hs → src/Hakyll/Web/Tags.hsrenamed+1−2
@@ -43,7 +43,6 @@
43module Hakyll.Web.Tags
43module Hakyll.Web.Tags
44 ( Tags (..)
44 ( Tags (..)
45 , getTags
45 , getTags
46− , getCategory
47 , buildTagsWith
46 , buildTagsWith
48 , buildTags
47 , buildTags
49 , buildCategories
48 , buildCategories
@@ -113,7 +112,7 @@ getTags identifier = do
113
112
114
113
115--------------------------------------------------------------------------------
114--------------------------------------------------------------------------------
116−-- | Obtain category from a page.
115+-- | Obtain categories from a page.
117getCategory :: MonadMetadata m => Identifier -> m [String]
116getCategory :: MonadMetadata m => Identifier -> m [String]
118getCategory = return . return . takeBaseName . takeDirectory . toFilePath
117getCategory = return . return . takeBaseName . takeDirectory . toFilePath
119
118
lib/Hakyll/Web/Template.hs → src/Hakyll/Web/Template.hsrenamed−24
@@ -138,7 +138,6 @@
138-- > 3...2...1
138-- > 3...2...1
139-- > </p>
139-- > </p>
140--
140--
141−{-# LANGUAGE TemplateHaskell #-}
142module Hakyll.Web.Template
141module Hakyll.Web.Template
143 ( Template
142 ( Template
144 , templateBodyCompiler
143 , templateBodyCompiler
@@ -147,32 +146,9 @@ module Hakyll.Web.Template
147 , loadAndApplyTemplate
146 , loadAndApplyTemplate
148 , applyAsTemplate
147 , applyAsTemplate
149 , readTemplate
148 , readTemplate
150− , compileTemplateItem
151 , unsafeReadTemplateFile
149 , unsafeReadTemplateFile
152− , embedTemplate
153 ) where
150 ) where
154
151
155
152
156--------------------------------------------------------------------------------
153--------------------------------------------------------------------------------
157import Hakyll.Web.Template.Internal
154import Hakyll.Web.Template.Internal
158−
159−
160−--------------------------------------------------------------------------------
161−import Data.FileEmbed (embedFile)
162−import qualified Data.Text as T
163−import qualified Data.Text.Encoding as T
164−import Language.Haskell.TH (Exp, Q)
165−
166−
167−--------------------------------------------------------------------------------
168−-- | Embed template allows you embed a template within the Haskell binary.
169−-- Example:
170−--
171−-- > myTemplate :: Template
172−-- > myTemplate = $(embedTemplate "test.html")
173−embedTemplate :: FilePath -> Q Exp
174−embedTemplate filePath = [|
175− let source = T.unpack $ T.decodeUtf8 $(embedFile filePath) in
176− case parseTemplateElemsFile filePath source of
177− Left err -> error err
178− Right tpl -> template filePath tpl |]
lib/Hakyll/Web/Template/Context.hs → src/Hakyll/Web/Template/Context.hsrenamed+33−135
@@ -1,27 +1,6 @@
1−-- | This module provides 'Context's which are used to expand expressions in
2−-- templates and allow for arbitrary customisation.
3−--
4−-- 'Template's define a small expression DSL which consists of strings,
5−-- identifiers and function application. There is no type system, every value is
6−-- a string and on the top level they get substituted verbatim into the page.
7−--
8−-- For example, you can build a context that contains
9−--
10−-- > … <> functionField "concat" (const . concat) <> …
11−--
12−-- which will allow you to use the @concat@ identifier as a function that takes
13−-- arbitrarily many stings and concatenates them to a new string:
14−--
15−-- > $partial(concat("templates/categories/", category))$
16−--
17−-- This will evaluate the @category@ field in the context, then prepend he path,
18−-- and include the referenced file as a template.
19−
20−
21--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
22{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
23{-# LANGUAGE ExistentialQuantification #-}
3{-# LANGUAGE ExistentialQuantification #-}
24−{-# LANGUAGE RankNTypes #-}
25module Hakyll.Web.Template.Context
4module Hakyll.Web.Template.Context
26 ( ContextField (..)
5 ( ContextField (..)
27 , Context (..)
6 , Context (..)
@@ -49,17 +28,13 @@ module Hakyll.Web.Template.Context
49 , teaserField
28 , teaserField
50 , teaserFieldWithSeparator
29 , teaserFieldWithSeparator
51 , missingField
30 , missingField
52− , bindItem
53 ) where
31 ) where
54
32
55
33
56--------------------------------------------------------------------------------
34--------------------------------------------------------------------------------
57import Control.Applicative (Alternative (..))
35import Control.Applicative (Alternative (..))
58import Control.Monad (msum)
36import Control.Monad (msum)
59−import Data.List (intercalate, tails)
37+import Data.List (intercalate)
60−#if MIN_VERSION_base(4,9,0)
61−import Data.Semigroup (Semigroup (..))
62−#endif
63import Data.Time.Clock (UTCTime (..))
38import Data.Time.Clock (UTCTime (..))
64import Data.Time.Format (formatTime)
39import Data.Time.Format (formatTime)
65import qualified Data.Time.Format as TF
40import qualified Data.Time.Format as TF
@@ -72,16 +47,13 @@ import Hakyll.Core.Metadata
72import Hakyll.Core.Provider
47import Hakyll.Core.Provider
73import Hakyll.Core.Util.String (needlePrefix, splitAll)
48import Hakyll.Core.Util.String (needlePrefix, splitAll)
74import Hakyll.Web.Html
49import Hakyll.Web.Html
75−import Prelude hiding (id)
76−import System.FilePath (dropExtension, splitDirectories,
50+import System.FilePath (splitDirectories, takeBaseName)
77− takeBaseName)
78
51
79
52
80--------------------------------------------------------------------------------
53--------------------------------------------------------------------------------
81-- | Mostly for internal usage
54-- | Mostly for internal usage
82data ContextField
55data ContextField
83− = EmptyField
84− | StringField String
56+ = StringField String
85 | forall a. ListField (Context a) [Item a]
57 | forall a. ListField (Context a) [Item a]
86
58
87
59
@@ -106,123 +78,71 @@ newtype Context a = Context
106
78
107
79
108--------------------------------------------------------------------------------
80--------------------------------------------------------------------------------
109−-- | Tries to find a key in the left context,
110−-- or when that fails in the right context.
111−#if MIN_VERSION_base(4,9,0)
112−instance Semigroup (Context a) where
113− (<>) (Context f) (Context g) = Context $ \k a i -> f k a i <|> g k a i
114−
115−instance Monoid (Context a) where
116− mempty = missingField
117− mappend = (<>)
118−#else
119instance Monoid (Context a) where
81instance Monoid (Context a) where
120 mempty = missingField
82 mempty = missingField
121 mappend (Context f) (Context g) = Context $ \k a i -> f k a i <|> g k a i
83 mappend (Context f) (Context g) = Context $ \k a i -> f k a i <|> g k a i
122−#endif
123
84
124
85
125--------------------------------------------------------------------------------
86--------------------------------------------------------------------------------
126field' :: String -> (Item a -> Compiler ContextField) -> Context a
87field' :: String -> (Item a -> Compiler ContextField) -> Context a
127−field' key value = Context $ \k _ i ->
88+field' key value = Context $ \k _ i -> if k == key then value i else empty
128− if k == key
129− then value i
130− else noResult $ "Tried field " ++ key
131
89
132
90
133--------------------------------------------------------------------------------
91--------------------------------------------------------------------------------
134−-- | Constructs a new field for a 'Context'.
92+-- | Constructs a new field in the 'Context.'
135−-- If the key matches, the compiler is run and its result is substituted in the
136−-- template.
137−--
138−-- If the compiler fails, the field will be considered non-existent
139−-- in an @$if()$@ macro or ultimately break the template application
140−-- (unless the key is found in another context when using '<>').
141−-- Use 'empty' or 'noResult' for intentional failures of fields used in
142−-- @$if()$@, to distinguish them from exceptions thrown with 'fail'.
143field
93field
144 :: String -- ^ Key
94 :: String -- ^ Key
145 -> (Item a -> Compiler String) -- ^ Function that constructs a value based
95 -> (Item a -> Compiler String) -- ^ Function that constructs a value based
146− -- on the item (e.g. accessing metadata)
96+ -- on the item
147 -> Context a
97 -> Context a
148field key value = field' key (fmap StringField . value)
98field key value = field' key (fmap StringField . value)
149
99
150
100
151--------------------------------------------------------------------------------
101--------------------------------------------------------------------------------
152-- | Creates a 'field' to use with the @$if()$@ template macro.
102-- | Creates a 'field' to use with the @$if()$@ template macro.
153−-- Attempting to substitute the field into the template will cause an error.
154boolField
103boolField
155 :: String
104 :: String
156 -> (Item a -> Bool)
105 -> (Item a -> Bool)
157 -> Context a
106 -> Context a
158−boolField name f = field' name (\i -> if f i
107+boolField name f = field name (\i -> if f i
159− then return EmptyField
108+ then pure (error $ unwords ["no string value for bool field:",name])
160− else noResult $ "Field " ++ name ++ " is false")
109+ else empty)
161
110
162
111
163--------------------------------------------------------------------------------
112--------------------------------------------------------------------------------
164−-- | Creates a 'field' that does not depend on the 'Item' but always yields
113+-- | Creates a 'field' that does not depend on the 'Item'
165−-- the same string
166−constField :: String -- ^ Key
114+constField :: String -> String -> Context a
167− -> String -- ^ Value
168− -> Context a
169constField key = field key . const . return
115constField key = field key . const . return
170
116
171
117
172--------------------------------------------------------------------------------
118--------------------------------------------------------------------------------
173−-- | Creates a list field to be consumed by a @$for(…)$@ expression.
174−-- The compiler returns multiple items which are rendered in the loop body
175−-- with the supplied context.
176listField :: String -> Context a -> Compiler [Item a] -> Context b
119listField :: String -> Context a -> Compiler [Item a] -> Context b
177listField key c xs = listFieldWith key c (const xs)
120listField key c xs = listFieldWith key c (const xs)
178
121
179
122
180--------------------------------------------------------------------------------
123--------------------------------------------------------------------------------
181−-- | Produces a new 'Context' which has list field 'key'. All fields from
182−-- 'c' are also accessible from the produced context.
183−-- Be careful when doing @listFieldWith k ca f <> cb@ as any fields in @ca@
184−-- will override fields in @cb@ with the same name.
185−-- Creates a list field like 'listField', but supplies the current page
186−-- to the compiler.
187listFieldWith
124listFieldWith
188 :: String -> Context a -> (Item b -> Compiler [Item a]) -> Context b
125 :: String -> Context a -> (Item b -> Compiler [Item a]) -> Context b
189listFieldWith key c f = field' key $ fmap (ListField c) . f
126listFieldWith key c f = field' key $ fmap (ListField c) . f
190
127
191
128
192--------------------------------------------------------------------------------
129--------------------------------------------------------------------------------
193−-- | Creates a variadic function field.
194−--
195−-- The function will be called with the dynamically evaluated string arguments
196−-- from the template as well as the page that is currently rendered.
197−functionField :: String -- ^ Key
198− -> ([String] -> Item a -> Compiler String) -- ^ Function
130+functionField :: String -> ([String] -> Item a -> Compiler String) -> Context a
199− -> Context a
200functionField name value = Context $ \k args i ->
131functionField name value = Context $ \k args i ->
201 if k == name
132 if k == name
202 then StringField <$> value args i
133 then StringField <$> value args i
203− else noResult $ "Tried function field " ++ name
134+ else empty
204
135
205
136
206--------------------------------------------------------------------------------
137--------------------------------------------------------------------------------
207−-- | Transform the respective string results of all fields in a context.
208−-- For example,
209−--
210−-- > mapContext (++"c") (constField "x" "a" <> constField "y" "b")
211−--
212−-- is equivalent to
213−--
214−-- > constField "x" "ac" <> constField "y" "bc"
215−--
216mapContext :: (String -> String) -> Context a -> Context a
138mapContext :: (String -> String) -> Context a -> Context a
217mapContext f (Context c) = Context $ \k a i -> do
139mapContext f (Context c) = Context $ \k a i -> do
218 fld <- c k a i
140 fld <- c k a i
219 case fld of
141 case fld of
220− EmptyField -> wrongType "boolField"
221 StringField str -> return $ StringField (f str)
142 StringField str -> return $ StringField (f str)
222− _ -> wrongType "ListField"
143+ ListField _ _ -> fail $
223− where
224− wrongType typ = fail $ "Hakyll.Web.Template.Context.mapContext: " ++
144+ "Hakyll.Web.Template.Context.mapContext: " ++
225− "can't map over a " ++ typ ++ "!"
145+ "can't map over a ListField!"
226
146
227--------------------------------------------------------------------------------
147--------------------------------------------------------------------------------
228-- | A context that allows snippet inclusion. In processed file, use as:
148-- | A context that allows snippet inclusion. In processed file, use as:
@@ -231,15 +151,15 @@ mapContext f (Context c) = Context $ \k a i -> do
231-- > $snippet("path/to/snippet/")$
151-- > $snippet("path/to/snippet/")$
232-- > ...
152-- > ...
233--
153--
234−-- The contents of the included file will not be interpolated like @partial@
154+-- The contents of the included file will not be interpolated.
235−-- does it.
236--
155--
237snippetField :: Context String
156snippetField :: Context String
238snippetField = functionField "snippet" f
157snippetField = functionField "snippet" f
239 where
158 where
240 f [contentsPath] _ = loadBody (fromFilePath contentsPath)
159 f [contentsPath] _ = loadBody (fromFilePath contentsPath)
241− f [] _ = fail "No argument to function 'snippet()'"
160+ f _ i = error $
242− f _ _ = fail "Too many arguments to function 'snippet()'"
161+ "Too many arguments to function 'snippet()' in item " ++
162+ show (itemIdentifier i)
243
163
244--------------------------------------------------------------------------------
164--------------------------------------------------------------------------------
245-- | A context that contains (in that order)
165-- | A context that contains (in that order)
@@ -259,7 +179,8 @@ defaultContext =
259 metadataField `mappend`
179 metadataField `mappend`
260 urlField "url" `mappend`
180 urlField "url" `mappend`
261 pathField "path" `mappend`
181 pathField "path" `mappend`
262− titleField "title"
182+ titleField "title" `mappend`
183+ missingField
263
184
264
185
265--------------------------------------------------------------------------------
186--------------------------------------------------------------------------------
@@ -277,20 +198,15 @@ bodyField key = field key $ return . itemBody
277-- | Map any field to its metadata value, if present
198-- | Map any field to its metadata value, if present
278metadataField :: Context a
199metadataField :: Context a
279metadataField = Context $ \k _ i -> do
200metadataField = Context $ \k _ i -> do
280− let id = itemIdentifier i
281− empty' = noResult $ "No '" ++ k ++ "' field in metadata " ++
282− "of item " ++ show id
283− value <- getMetadataField id k
201+ value <- getMetadataField (itemIdentifier i) k
284− maybe empty' (return . StringField) value
202+ maybe empty (return . StringField) value
285
203
286
204
287--------------------------------------------------------------------------------
205--------------------------------------------------------------------------------
288-- | Absolute url to the resulting item
206-- | Absolute url to the resulting item
289urlField :: String -> Context a
207urlField :: String -> Context a
290−urlField key = field key $ \i -> do
208+urlField key = field key $
291− let id = itemIdentifier i
292− empty' = fail $ "No route url found for item " ++ show id
293− fmap (maybe empty' toUrl) $ getRoute id
209+ fmap (maybe empty toUrl) . getRoute . itemIdentifier
294
210
295
211
296--------------------------------------------------------------------------------
212--------------------------------------------------------------------------------
@@ -341,12 +257,6 @@ titleField = mapContext takeBaseName . pathField
341-- that begins with @yyyy-mm-dd@ . For example:
257-- that begins with @yyyy-mm-dd@ . For example:
342-- @folder//yyyy-mm-dd-title//dist//main.extension@ .
258-- @folder//yyyy-mm-dd-title//dist//main.extension@ .
343-- In case of multiple matches, the rightmost one is used.
259-- In case of multiple matches, the rightmost one is used.
344−--
345−-- As another alternative, if none of the above matches, and the file has a
346−-- path which contains nested directories specifying a date, then that date
347−-- will be used. In other words, if the path is of the form
348−-- @**//yyyy//mm//dd//**//main.extension@ .
349−-- As above, in case of multiple matches, the rightmost one is used.
350
260
351dateField :: String -- ^ Key in which the rendered date should be placed
261dateField :: String -- ^ Key in which the rendered date should be placed
352 -> String -- ^ Format to use on the date
262 -> String -- ^ Format to use on the date
@@ -357,7 +267,7 @@ dateField = dateFieldWith defaultTimeLocale
357--------------------------------------------------------------------------------
267--------------------------------------------------------------------------------
358-- | This is an extended version of 'dateField' that allows you to
268-- | This is an extended version of 'dateField' that allows you to
359-- specify a time locale that is used for outputting the date. For more
269-- specify a time locale that is used for outputting the date. For more
360−-- details, see 'dateField' and 'formatTime'.
270+-- details, see 'dateField'.
361dateFieldWith :: TimeLocale -- ^ Output time locale
271dateFieldWith :: TimeLocale -- ^ Output time locale
362 -> String -- ^ Destination key
272 -> String -- ^ Destination key
363 -> String -- ^ Format to use on the date
273 -> String -- ^ Format to use on the date
@@ -378,13 +288,12 @@ getItemUTC :: MonadMetadata m
378getItemUTC locale id' = do
288getItemUTC locale id' = do
379 metadata <- getMetadata id'
289 metadata <- getMetadata id'
380 let tryField k fmt = lookupString k metadata >>= parseTime' fmt
290 let tryField k fmt = lookupString k metadata >>= parseTime' fmt
381− paths = splitDirectories $ (dropExtension . toFilePath) id'
291+ paths = splitDirectories $ toFilePath id'
382
292
383 maybe empty' return $ msum $
293 maybe empty' return $ msum $
384 [tryField "published" fmt | fmt <- formats] ++
294 [tryField "published" fmt | fmt <- formats] ++
385 [tryField "date" fmt | fmt <- formats] ++
295 [tryField "date" fmt | fmt <- formats] ++
386− [parseTime' "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fnCand | fnCand <- reverse paths] ++
296+ [parseTime' "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fnCand | fnCand <- reverse paths]
387− [parseTime' "%Y-%m-%d" $ intercalate "-" $ fnCand | fnCand <- map (take 3) $ reverse . tails $ paths]
388 where
297 where
389 empty' = fail $ "Hakyll.Web.Template.Context.getItemUTC: " ++
298 empty' = fail $ "Hakyll.Web.Template.Context.getItemUTC: " ++
390 "could not parse time for " ++ show id'
299 "could not parse time for " ++ show id'
@@ -412,16 +321,13 @@ getItemModificationTime identifier = do
412
321
413
322
414--------------------------------------------------------------------------------
323--------------------------------------------------------------------------------
415−-- | Creates a field with the last modification date of the underlying item.
416modificationTimeField :: String -- ^ Key
324modificationTimeField :: String -- ^ Key
417 -> String -- ^ Format
325 -> String -- ^ Format
418− -> Context a -- ^ Resulting context
326+ -> Context a -- ^ Resuting context
419modificationTimeField = modificationTimeFieldWith defaultTimeLocale
327modificationTimeField = modificationTimeFieldWith defaultTimeLocale
420
328
421
329
422--------------------------------------------------------------------------------
330--------------------------------------------------------------------------------
423−-- | Creates a field with the last modification date of the underlying item
424−-- in a custom localisation format (see 'formatTime').
425modificationTimeFieldWith :: TimeLocale -- ^ Time output locale
331modificationTimeFieldWith :: TimeLocale -- ^ Time output locale
426 -> String -- ^ Key
332 -> String -- ^ Key
427 -> String -- ^ Format
333 -> String -- ^ Format
@@ -460,11 +366,10 @@ teaserFieldWithSeparator separator key snapshot = field key $ \item -> do
460
366
461
367
462--------------------------------------------------------------------------------
368--------------------------------------------------------------------------------
463−-- | Constantly reports any field as missing. Mostly for internal usage,
464−-- it is the last choice in every context used in a template application.
465missingField :: Context a
369missingField :: Context a
466−missingField = Context $ \k _ _ -> noResult $
370+missingField = Context $ \k _ i -> fail $
467− "Missing field '" ++ k ++ "' in context"
371+ "Missing field $" ++ k ++ "$ in context for item " ++
372+ show (itemIdentifier i)
468
373
469parseTimeM :: Bool -> TimeLocale -> String -> String -> Maybe UTCTime
374parseTimeM :: Bool -> TimeLocale -> String -> String -> Maybe UTCTime
470#if MIN_VERSION_time(1,5,0)
375#if MIN_VERSION_time(1,5,0)
@@ -472,10 +377,3 @@ parseTimeM = TF.parseTimeM
472#else
377#else
473parseTimeM _ = TF.parseTime
378parseTimeM _ = TF.parseTime
474#endif
379#endif
475−
476−--------------------------------------------------------------------------------
477−
478−-- | Binds an 'Item' to a given 'Context', allowing it to be combined with any
479−-- other 'Context' of any type.
480−bindItem :: Context a -> Item a -> forall b. Context b
481−bindItem (Context ctx) ia = Context $ \k args _ -> ctx k args ia
lib/Hakyll/Web/Template/Internal.hs → src/Hakyll/Web/Template/Internal.hsrenamed+45−103
@@ -1,18 +1,15 @@
1−{-# LANGUAGE DeriveAnyClass #-}
2−{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE ScopedTypeVariables #-}
5−
6module Hakyll.Web.Template.Internal
3module Hakyll.Web.Template.Internal
7 ( Template (..)
4 ( Template (..)
8 , template
5 , template
9 , templateBodyCompiler
6 , templateBodyCompiler
10 , templateCompiler
7 , templateCompiler
11 , applyTemplate
8 , applyTemplate
9+ , applyTemplate'
12 , loadAndApplyTemplate
10 , loadAndApplyTemplate
13 , applyAsTemplate
11 , applyAsTemplate
14 , readTemplate
12 , readTemplate
15− , compileTemplateItem
16 , unsafeReadTemplateFile
13 , unsafeReadTemplateFile
17
14
18 , module Hakyll.Web.Template.Internal.Element
15 , module Hakyll.Web.Template.Internal.Element
@@ -21,19 +18,16 @@ module Hakyll.Web.Template.Internal
21
18
22
19
23--------------------------------------------------------------------------------
20--------------------------------------------------------------------------------
24−import Control.Monad (forM)
21+import Control.Monad.Except (MonadError (..))
25−import Control.Monad.Except (MonadError (..), catchError)
26import Data.Binary (Binary)
22import Data.Binary (Binary)
27import Data.List (intercalate)
23import Data.List (intercalate)
28−import qualified Data.List.NonEmpty as NonEmpty
29import Data.Typeable (Typeable)
24import Data.Typeable (Typeable)
30import GHC.Exts (IsString (..))
25import GHC.Exts (IsString (..))
31−import GHC.Generics (Generic)
26+import Prelude hiding (id)
32
27
33
28
34--------------------------------------------------------------------------------
29--------------------------------------------------------------------------------
35import Hakyll.Core.Compiler
30import Hakyll.Core.Compiler
36−import Hakyll.Core.Compiler.Internal
37import Hakyll.Core.Identifier
31import Hakyll.Core.Identifier
38import Hakyll.Core.Item
32import Hakyll.Core.Item
39import Hakyll.Core.Writable
33import Hakyll.Core.Writable
@@ -44,10 +38,9 @@ import Hakyll.Web.Template.Internal.Trim
44
38
45--------------------------------------------------------------------------------
39--------------------------------------------------------------------------------
46-- | Datatype used for template substitutions.
40-- | Datatype used for template substitutions.
47−data Template = Template
41+newtype Template = Template
48− { tplElements :: [TemplateElement]
42+ { unTemplate :: [TemplateElement]
49− , tplOrigin :: FilePath -- Only for error messages.
50− } deriving (Show, Eq, Generic, Binary, Typeable)
43+ } deriving (Show, Eq, Binary, Typeable)
51
44
52
45
53--------------------------------------------------------------------------------
46--------------------------------------------------------------------------------
@@ -63,68 +56,39 @@ instance IsString Template where
63
56
64--------------------------------------------------------------------------------
57--------------------------------------------------------------------------------
65-- | Wrap the constructor to ensure trim is called.
58-- | Wrap the constructor to ensure trim is called.
66−template :: FilePath -> [TemplateElement] -> Template
59+template :: [TemplateElement] -> Template
67−template p = flip Template p . trim
60+template = Template . trim
68
61
69
62
70--------------------------------------------------------------------------------
63--------------------------------------------------------------------------------
71−-- | Parse a string into a template.
72−-- You should prefer 'compileTemplateItem' over this.
73readTemplate :: String -> Template
64readTemplate :: String -> Template
74−readTemplate = either error (template origin) . parseTemplateElemsFile origin
65+readTemplate = Template . trim . readTemplateElems
75− where
76− origin = "{literal}"
77−{-# DEPRECATED readTemplate "Use templateCompiler instead" #-}
78−
79−--------------------------------------------------------------------------------
80−-- | Parse an item body into a template.
81−-- Provides useful error messages in the 'Compiler' monad.
82−compileTemplateItem :: Item String -> Compiler Template
83−compileTemplateItem item = let file = itemIdentifier item
84− in compileTemplateFile file (itemBody item)
85−
86−--------------------------------------------------------------------------------
87−compileTemplateFile :: Identifier -> String -> Compiler Template
88−compileTemplateFile file = either fail (return . template origin)
89− . parseTemplateElemsFile origin
90− where
91− origin = show file
92
66
93--------------------------------------------------------------------------------
67--------------------------------------------------------------------------------
94-- | Read a template, without metadata header
68-- | Read a template, without metadata header
95templateBodyCompiler :: Compiler (Item Template)
69templateBodyCompiler :: Compiler (Item Template)
96templateBodyCompiler = cached "Hakyll.Web.Template.templateBodyCompiler" $ do
70templateBodyCompiler = cached "Hakyll.Web.Template.templateBodyCompiler" $ do
97 item <- getResourceBody
71 item <- getResourceBody
98− file <- getUnderlying
72+ file <- getResourceFilePath
99− withItemBody (compileTemplateFile file) item
73+ return $ fmap (template . readTemplateElemsFile file) item
100
74
101--------------------------------------------------------------------------------
75--------------------------------------------------------------------------------
102-- | Read complete file contents as a template
76-- | Read complete file contents as a template
103templateCompiler :: Compiler (Item Template)
77templateCompiler :: Compiler (Item Template)
104templateCompiler = cached "Hakyll.Web.Template.templateCompiler" $ do
78templateCompiler = cached "Hakyll.Web.Template.templateCompiler" $ do
105 item <- getResourceString
79 item <- getResourceString
106− file <- getUnderlying
80+ file <- getResourceFilePath
107− withItemBody (compileTemplateFile file) item
81+ return $ fmap (template . readTemplateElemsFile file) item
108
82
109
83
110--------------------------------------------------------------------------------
84--------------------------------------------------------------------------------
111−-- | Interpolate template expressions from context values in a page
112applyTemplate :: Template -- ^ Template
85applyTemplate :: Template -- ^ Template
113 -> Context a -- ^ Context
86 -> Context a -- ^ Context
114 -> Item a -- ^ Page
87 -> Item a -- ^ Page
115 -> Compiler (Item String) -- ^ Resulting item
88 -> Compiler (Item String) -- ^ Resulting item
116applyTemplate tpl context item = do
89applyTemplate tpl context item = do
117− body <- applyTemplate' (tplElements tpl) context item `catchError` handler
90+ body <- applyTemplate' (unTemplate tpl) context item
118 return $ itemSetBody body item
91 return $ itemSetBody body item
119− where
120− tplName = tplOrigin tpl
121− itemName = show $ itemIdentifier item
122− handler es = fail $ "Hakyll.Web.Template.applyTemplate: Failed to " ++
123− (if tplName == itemName
124− then "interpolate template in item " ++ itemName
125− else "apply template " ++ tplName ++ " to item " ++ itemName) ++
126− ":\n" ++ intercalate ",\n" es
127−
128
92
129
93
130--------------------------------------------------------------------------------
94--------------------------------------------------------------------------------
@@ -141,6 +105,9 @@ applyTemplate' tes context x = go tes
141
105
142 go = fmap concat . mapM applyElem
106 go = fmap concat . mapM applyElem
143
107
108+ trimError = error $ "Hakyll.Web.Template.applyTemplate: template not " ++
109+ "fully trimmed."
110+
144 ---------------------------------------------------------------------------
111 ---------------------------------------------------------------------------
145
112
146 applyElem :: TemplateElement -> Compiler String
113 applyElem :: TemplateElement -> Compiler String
@@ -151,43 +118,29 @@ applyTemplate' tes context x = go tes
151
118
152 applyElem (Chunk c) = return c
119 applyElem (Chunk c) = return c
153
120
154− applyElem (Expr e) = withErrorMessage evalMsg (applyStringExpr typeMsg e)
121+ applyElem (Expr e) = applyExpr e >>= getString e
155− where
156− evalMsg = "In expr '$" ++ show e ++ "$'"
157− typeMsg = "expr '$" ++ show e ++ "$'"
158
122
159 applyElem Escaped = return "$"
123 applyElem Escaped = return "$"
160
124
161− applyElem (If e t mf) = compilerTry (applyExpr e) >>= handle
125+ applyElem (If e t mf) = (applyExpr e >> go t) `catchError` handler
162 where
126 where
163− f = maybe (return "") go mf
127+ handler _ = case mf of
164− handle (Right _) = go t
128+ Nothing -> return ""
165− handle (Left (CompilationNoResult _)) = f
129+ Just f -> go f
166− handle (Left (CompilationFailure es)) = debug (NonEmpty.toList es) >> f
130+
167− debug = compilerDebugEntries ("Hakyll.Web.Template.applyTemplate: " ++
168− "[ERROR] in 'if' condition on expr '" ++ show e ++ "':")
169−
170− applyElem (For e b s) = withErrorMessage headMsg (applyExpr e) >>= \cf -> case cf of
131+ applyElem (For e b s) = applyExpr e >>= \cf -> case cf of
171− EmptyField -> expected "list" "boolean" typeMsg
132+ StringField _ -> fail $
172− StringField _ -> expected "list" "string" typeMsg
133+ "Hakyll.Web.Template.applyTemplateWith: expected ListField but " ++
134+ "got StringField for expr " ++ show e
173− ListField c xs -> withErrorMessage bodyMsg $ do
135+ ListField c xs -> do
174 sep <- maybe (return "") go s
136 sep <- maybe (return "") go s
175− bs <- forM xs $ applyTemplate' b $ c <> bindItem context x
137+ bs <- mapM (applyTemplate' b c) xs
176 return $ intercalate sep bs
138 return $ intercalate sep bs
177− where
139+
178− headMsg = "In expr '$for(" ++ show e ++ ")$'"
179− typeMsg = "loop expr '" ++ show e ++ "'"
180− bodyMsg = "In loop context of '$for(" ++ show e ++ ")$'"
181−
182− applyElem (Partial e) = withErrorMessage headMsg $
140+ applyElem (Partial e) = do
183− applyStringExpr typeMsg e >>= \p ->
141+ p <- applyExpr e >>= getString e
184− withErrorMessage inclMsg $ do
185− tpl' <- loadBody (fromFilePath p)
142+ Template tpl' <- loadBody (fromFilePath p)
186− itemBody <$> applyTemplate tpl' context x
143+ applyTemplate' tpl' context x
187− where
188− headMsg = "In expr '$partial(" ++ show e ++ ")$'"
189− typeMsg = "partial expr '" ++ show e ++ "'"
190− inclMsg = "In inclusion of '$partial(" ++ show e ++ ")$'"
191
144
192 ---------------------------------------------------------------------------
145 ---------------------------------------------------------------------------
193
146
@@ -196,29 +149,17 @@ applyTemplate' tes context x = go tes
196 applyExpr (Ident (TemplateKey k)) = context' k [] x
149 applyExpr (Ident (TemplateKey k)) = context' k [] x
197
150
198 applyExpr (Call (TemplateKey k) args) = do
151 applyExpr (Call (TemplateKey k) args) = do
199− args' <- mapM (\e -> applyStringExpr (typeMsg e) e) args
152+ args' <- mapM (\e -> applyExpr e >>= getString e) args
200 context' k args' x
153 context' k args' x
201− where
202− typeMsg e = "argument '" ++ show e ++ "'"
203
154
204 applyExpr (StringLiteral s) = return (StringField s)
155 applyExpr (StringLiteral s) = return (StringField s)
205
156
206 ----------------------------------------------------------------------------
157 ----------------------------------------------------------------------------
207
158
208− applyStringExpr :: String -> TemplateExpr -> Compiler String
209− applyStringExpr msg expr =
210− applyExpr expr >>= getString
211− where
212− getString EmptyField = expected "string" "boolean" msg
213− getString (StringField s) = return s
159+ getString _ (StringField s) = return s
214− getString (ListField _ _) = expected "string" "list" msg
160+ getString e (ListField _ _) = fail $
215−
161+ "Hakyll.Web.Template.applyTemplateWith: expected StringField but " ++
216− expected typ act expr = fail $ unwords ["Hakyll.Web.Template.applyTemplate:",
162+ "got ListField for expr " ++ show e
217− "expected", typ, "but got", act, "for", expr]
218−
219− -- expected to never happen with all templates constructed by 'template'
220− trimError = fail $
221− "Hakyll.Web.Template.applyTemplate: template not fully trimmed."
222
163
223
164
224--------------------------------------------------------------------------------
165--------------------------------------------------------------------------------
@@ -248,14 +189,15 @@ loadAndApplyTemplate identifier context item = do
248applyAsTemplate :: Context String -- ^ Context
189applyAsTemplate :: Context String -- ^ Context
249 -> Item String -- ^ Item and template
190 -> Item String -- ^ Item and template
250 -> Compiler (Item String) -- ^ Resulting item
191 -> Compiler (Item String) -- ^ Resulting item
251−applyAsTemplate context item = do
192+applyAsTemplate context item =
252− tpl <- compileTemplateItem item
193+ let tpl = template $ readTemplateElemsFile file (itemBody item)
194+ file = toFilePath $ itemIdentifier item
253− applyTemplate tpl context item
195+ in applyTemplate tpl context item
254
196
255
197
256--------------------------------------------------------------------------------
198--------------------------------------------------------------------------------
257unsafeReadTemplateFile :: FilePath -> Compiler Template
199unsafeReadTemplateFile :: FilePath -> Compiler Template
258unsafeReadTemplateFile file = do
200unsafeReadTemplateFile file = do
259 tpl <- unsafeCompiler $ readFile file
201 tpl <- unsafeCompiler $ readFile file
260− compileTemplateFile (fromFilePath file) tpl
202+ pure $ template $ readTemplateElemsFile file tpl
261−{-# DEPRECATED unsafeReadTemplateFile "Use templateCompiler" #-}
203+
lib/Hakyll/Web/Template/Internal/Element.hs → src/Hakyll/Web/Template/Internal/Element.hsrenamed+14−7
@@ -7,14 +7,14 @@ module Hakyll.Web.Template.Internal.Element
7 , TemplateExpr (..)
7 , TemplateExpr (..)
8 , TemplateElement (..)
8 , TemplateElement (..)
9 , templateElems
9 , templateElems
10− , parseTemplateElemsFile
10+ , readTemplateElems
11+ , readTemplateElemsFile
11 ) where
12 ) where
12
13
13
14
14--------------------------------------------------------------------------------
15--------------------------------------------------------------------------------
15−import Control.Applicative ((<|>), (<*))
16+import Control.Applicative ((<|>))
16import Control.Monad (void)
17import Control.Monad (void)
17−import Control.Arrow (left)
18import Data.Binary (Binary, get, getWord8, put, putWord8)
18import Data.Binary (Binary, get, getWord8, put, putWord8)
19import Data.List (intercalate)
19import Data.List (intercalate)
20import Data.Maybe (isJust)
20import Data.Maybe (isJust)
@@ -107,10 +107,17 @@ instance Binary TemplateExpr where
107 2 -> StringLiteral <$> get
107 2 -> StringLiteral <$> get
108 _ -> error "Hakyll.Web.Template.Internal: Error reading cached template"
108 _ -> error "Hakyll.Web.Template.Internal: Error reading cached template"
109
109
110+
111+--------------------------------------------------------------------------------
112+readTemplateElems :: String -> [TemplateElement]
113+readTemplateElems = readTemplateElemsFile "{literal}"
114+
115+
110--------------------------------------------------------------------------------
116--------------------------------------------------------------------------------
111−parseTemplateElemsFile :: FilePath -> String -> Either String [TemplateElement]
117+readTemplateElemsFile :: FilePath -> String -> [TemplateElement]
118+readTemplateElemsFile file input = case P.parse templateElems file input of
112−parseTemplateElemsFile file = left (\e -> "Cannot parse template " ++ show e)
119+ Left err -> error $ "Cannot parse template: " ++ show err
113− . P.parse (templateElems <* P.eof) file
120+ Right t -> t
114
121
115
122
116--------------------------------------------------------------------------------
123--------------------------------------------------------------------------------
@@ -160,7 +167,7 @@ trimOpen = do
160--------------------------------------------------------------------------------
167--------------------------------------------------------------------------------
161trimClose :: P.Parser Bool
168trimClose :: P.Parser Bool
162trimClose = do
169trimClose = do
163− trimIfR <- P.optionMaybe $ (P.char '-')
170+ trimIfR <- P.optionMaybe $ P.try (P.char '-')
164 void $ P.char '$'
171 void $ P.char '$'
165 pure $ isJust trimIfR
172 pure $ isJust trimIfR
166
173
lib/Hakyll/Web/Template/Internal/Trim.hs → src/Hakyll/Web/Template/Internal/Trim.hsrenamed

The content is the same.

lib/Hakyll/Web/Template/List.hs → src/Hakyll/Web/Template/List.hsrenamed

The content is the same.

stack.yaml+7−27
@@ -1,33 +1,13 @@
1−resolver: lts-13.29
1+resolver: nightly-2016-10-31
2−save-hackage-creds: false
2+extra-package-dbs: []
3+extra-deps:
4+ - 'QuickCheck-2.9.2'
3
5
4flags:
6flags:
5 hakyll:
7 hakyll:
6− previewServer: true
8+ previewServer: True
7− watchServer: true
9+ watchServer: True
8− checkExternal: true
10+ checkExternal: True
9− usePandoc: true
10− buildWebsite: true
11
11
12packages:
12packages:
13 - '.'
13 - '.'
14−
15−nix:
16− enable: false
17− packages:
18− - zlib
19−
20−build:
21− haddock: true
22− haddock-hyperlink-source: true
23− haddock-deps: false
24−
25−extra-deps:
26−- 'cmark-gfm-0.2.0'
27−- 'hslua-module-system-0.2.1'
28−- 'ipynb-0.1'
29−- 'lrucache-1.2.0.1'
30−- 'pandoc-2.7.3'
31−- 'pandoc-citeproc-0.16.2'
32−- 'skylighting-0.8.2'
33−- 'skylighting-core-0.8.2'
test.hsdeleted−30
@@ -1,30 +0,0 @@
1−{-# LANGUAGE BangPatterns #-}
2−import Control.Monad (forM)
3−import qualified Crypto.Hash.SHA256 as SHA256
4−import qualified Data.ByteString.Base16 as Base16
5−import qualified Data.ByteString.Char8 as BS8
6−import qualified Data.ByteString.Lazy as BSL
7−import Data.Map (Map)
8−import qualified Data.Map as Map
9−import Hakyll
10−import System.FilePath ((</>))
11−
12−type FileHashes = Map Identifier String
13−
14−mkFileHashes :: FilePath -> IO FileHashes
15−mkFileHashes dir = do
16− allFiles <- getRecursiveContents (\_ -> return False) dir
17− fmap Map.fromList $ forM allFiles $ \path0 -> do
18− let path1 = dir </> path0
19− !h <- hash path1
20− return (fromFilePath path1, h)
21− where
22− hash :: FilePath -> IO String
23− hash fp = do
24− !h <- SHA256.hashlazy <$> BSL.readFile fp
25− return $! BS8.unpack $! Base16.encode h
26−
27−main :: IO ()
28−main = hakyll $ do
29− fileHashes <- preprocess (mkFileHashes "images")
30− undefined
tests/Hakyll/Core/Identifier/Tests.hs−1
@@ -42,7 +42,6 @@ captureTests = fromAssertions "capture"
42 , Just ["lol", "fun/large"] @=? capture "*cat/**.jpg" "lolcat/fun/large.jpg"
42 , Just ["lol", "fun/large"] @=? capture "*cat/**.jpg" "lolcat/fun/large.jpg"
43 , Just [] @=? capture "\\*.jpg" "*.jpg"
43 , Just [] @=? capture "\\*.jpg" "*.jpg"
44 , Nothing @=? capture "\\*.jpg" "foo.jpg"
44 , Nothing @=? capture "\\*.jpg" "foo.jpg"
45− , Just ["xyz","42"] @=? capture (fromRegex "cat-([a-z]+)/foo([0-9]+).jpg") "cat-xyz/foo42.jpg"
46 ]
45 ]
47
46
48
47
tests/Hakyll/Core/Provider/Tests.hs+2−2
@@ -9,7 +9,7 @@ module Hakyll.Core.Provider.Tests
9import Hakyll.Core.Metadata
9import Hakyll.Core.Metadata
10import Hakyll.Core.Provider
10import Hakyll.Core.Provider
11import Test.Tasty (TestTree, testGroup)
11import Test.Tasty (TestTree, testGroup)
12−import Test.Tasty.HUnit (Assertion, testCase, (@=?))
12+import Test.Tasty.HUnit (Assertion, assert, testCase, (@=?))
13import TestSuite.Util
13import TestSuite.Util
14
14
15
15
@@ -25,7 +25,7 @@ case01 :: Assertion
25case01 = do
25case01 = do
26 store <- newTestStore
26 store <- newTestStore
27 provider <- newTestProvider store
27 provider <- newTestProvider store
28− True @=? resourceExists provider "example.md"
28+ assert $ resourceExists provider "example.md"
29
29
30 metadata <- resourceMetadata provider "example.md"
30 metadata <- resourceMetadata provider "example.md"
31 Just "An example" @=? lookupString "title" metadata
31 Just "An example" @=? lookupString "title" metadata
tests/Hakyll/Core/Rules/Tests.hs+4−3
@@ -17,9 +17,10 @@ import Hakyll.Core.Metadata
17import Hakyll.Core.Routes
17import Hakyll.Core.Routes
18import Hakyll.Core.Rules
18import Hakyll.Core.Rules
19import Hakyll.Core.Rules.Internal
19import Hakyll.Core.Rules.Internal
20+import Hakyll.Web.Pandoc
20import System.FilePath ((</>))
21import System.FilePath ((</>))
21import Test.Tasty (TestTree, testGroup)
22import Test.Tasty (TestTree, testGroup)
22−import Test.Tasty.HUnit (Assertion, (@=?))
23+import Test.Tasty.HUnit (Assertion, assert, (@=?))
23import TestSuite.Util
24import TestSuite.Util
24
25
25
26
@@ -49,7 +50,7 @@ case01 = do
49 checkRoute "example.mv1" (sv "mv1" "example.md")
50 checkRoute "example.mv1" (sv "mv1" "example.md")
50 checkRoute "example.mv2" (sv "mv2" "example.md")
51 checkRoute "example.mv2" (sv "mv2" "example.md")
51 checkRoute "food/example.md" (sv "metadataMatch" "example.md")
52 checkRoute "food/example.md" (sv "metadataMatch" "example.md")
52− readIORef ioref >>= (True @=?)
53+ readIORef ioref >>= assert
53 cleanTestEnv
54 cleanTestEnv
54 where
55 where
55 sv g = setVersion (Just g)
56 sv g = setVersion (Just g)
@@ -74,7 +75,7 @@ rules01 ioref = do
74 -- Compile some posts
75 -- Compile some posts
75 match "*.md" $ do
76 match "*.md" $ do
76 route $ setExtension "html"
77 route $ setExtension "html"
77− compile copyFileCompiler
78+ compile pandocCompiler
78
79
79 -- Yeah. I don't know how else to test this stuff?
80 -- Yeah. I don't know how else to test this stuff?
80 preprocess $ writeIORef ioref True
81 preprocess $ writeIORef ioref True
tests/Hakyll/Core/Runtime/Tests.hs+1−1
@@ -39,7 +39,7 @@ case01 = do
39 compile $ do
39 compile $ do
40 getResourceBody
40 getResourceBody
41 >>= saveSnapshot "raw"
41 >>= saveSnapshot "raw"
42− >>= renderParagraphs
42+ >>= renderPandoc
43
43
44 match (fromList ["partial.html", "partial-helper.html"]) $
44 match (fromList ["partial.html", "partial-helper.html"]) $
45 compile templateCompiler
45 compile templateCompiler
tests/Hakyll/Core/Store/Tests.hs+7−7
@@ -63,11 +63,11 @@ wrongType = do
63 -- Store a string and try to fetch an int
63 -- Store a string and try to fetch an int
64 Store.set store ["foo", "bar"] ("qux" :: String)
64 Store.set store ["foo", "bar"] ("qux" :: String)
65 value <- Store.get store ["foo", "bar"] :: IO (Store.Result Int)
65 value <- Store.get store ["foo", "bar"] :: IO (Store.Result Int)
66− case value of
66+ H.assert $ case value of
67− Store.WrongType e t -> do
67+ Store.WrongType e t ->
68− typeOf (undefined :: Int) H.@=? e
68+ e == typeOf (undefined :: Int) &&
69− typeOf (undefined :: String) H.@=? t
69+ t == typeOf (undefined :: String)
70− _ -> H.assertFailure "Expecting WrongType"
70+ _ -> False
71 cleanTestEnv
71 cleanTestEnv
72
72
73
73
@@ -78,6 +78,6 @@ isMembertest = do
78 Store.set store ["foo", "bar"] ("qux" :: String)
78 Store.set store ["foo", "bar"] ("qux" :: String)
79 good <- Store.isMember store ["foo", "bar"]
79 good <- Store.isMember store ["foo", "bar"]
80 bad <- Store.isMember store ["foo", "baz"]
80 bad <- Store.isMember store ["foo", "baz"]
81− True H.@=? good
81+ H.assert good
82− False H.@=? bad
82+ H.assert (not bad)
83 cleanTestEnv
83 cleanTestEnv
tests/Hakyll/Core/UnixFilter/Tests.hs+12−22
@@ -6,14 +6,15 @@ module Hakyll.Core.UnixFilter.Tests
6
6
7
7
8--------------------------------------------------------------------------------
8--------------------------------------------------------------------------------
9+import Data.List (isInfixOf)
9−import Test.Tasty (TestTree, testGroup)
10+import Test.Tasty (TestTree, testGroup)
10−import Test.Tasty.HUnit (testCase)
11+import Test.Tasty.HUnit (testCase)
11−import qualified Test.Tasty.HUnit as H
12+import qualified Test.Tasty.HUnit as H
12
13
13
14
14--------------------------------------------------------------------------------
15--------------------------------------------------------------------------------
15import Hakyll.Core.Compiler
16import Hakyll.Core.Compiler
16−import Hakyll.Core.Identifier
17+import Hakyll.Core.Compiler.Internal
17import Hakyll.Core.Item
18import Hakyll.Core.Item
18import Hakyll.Core.UnixFilter
19import Hakyll.Core.UnixFilter
19import TestSuite.Util
20import TestSuite.Util
@@ -24,20 +25,17 @@ tests :: TestTree
24tests = testGroup "Hakyll.Core.UnixFilter.Tests"
25tests = testGroup "Hakyll.Core.UnixFilter.Tests"
25 [ testCase "unixFilter rev" unixFilterRev
26 [ testCase "unixFilter rev" unixFilterRev
26 , testCase "unixFilter false" unixFilterFalse
27 , testCase "unixFilter false" unixFilterFalse
27− , testCase "unixFilter error" unixFilterError
28 ]
28 ]
29
29
30−testMarkdown :: Identifier
31−testMarkdown = "russian.md"
32
30
33--------------------------------------------------------------------------------
31--------------------------------------------------------------------------------
34unixFilterRev :: H.Assertion
32unixFilterRev :: H.Assertion
35unixFilterRev = do
33unixFilterRev = do
36 store <- newTestStore
34 store <- newTestStore
37 provider <- newTestProvider store
35 provider <- newTestProvider store
38− output <- testCompilerDone store provider testMarkdown compiler
36+ output <- testCompilerDone store provider "russian.md" compiler
39− expected <- testCompilerDone store provider testMarkdown getResourceString
37+ expected <- testCompilerDone store provider "russian.md" getResourceString
40− rev (itemBody expected) H.@=? lines (itemBody output)
38+ H.assert $ rev (itemBody expected) == lines (itemBody output)
41 cleanTestEnv
39 cleanTestEnv
42 where
40 where
43 compiler = getResourceString >>= withItemBody (unixFilter "rev" [])
41 compiler = getResourceString >>= withItemBody (unixFilter "rev" [])
@@ -49,18 +47,10 @@ unixFilterFalse :: H.Assertion
49unixFilterFalse = do
47unixFilterFalse = do
50 store <- newTestStore
48 store <- newTestStore
51 provider <- newTestProvider store
49 provider <- newTestProvider store
52− testCompilerError store provider testMarkdown compiler "exit code"
50+ result <- testCompiler store provider "russian.md" compiler
51+ H.assert $ case result of
52+ CompilerError es -> any ("exit code" `isInfixOf`) es
53+ _ -> False
53 cleanTestEnv
54 cleanTestEnv
54 where
55 where
55 compiler = getResourceString >>= withItemBody (unixFilter "false" [])
56 compiler = getResourceString >>= withItemBody (unixFilter "false" [])
56−
57−
58−--------------------------------------------------------------------------------
59−unixFilterError :: H.Assertion
60−unixFilterError = do
61− store <- newTestStore
62− provider <- newTestProvider store
63− testCompilerError store provider testMarkdown compiler "option"
64− cleanTestEnv
65− where
66− compiler = getResourceString >>= withItemBody (unixFilter "head" ["-#"])
tests/Hakyll/Web/CompressCss/Tests.hs+13−18
@@ -5,8 +5,9 @@ module Hakyll.Web.CompressCss.Tests
5
5
6
6
7--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
8+import Data.Char (toUpper)
8import Test.Tasty (TestTree, testGroup)
9import Test.Tasty (TestTree, testGroup)
9−import Test.Tasty.HUnit ((@=?))
10+import Test.Tasty.HUnit (assert, (@=?))
10
11
11
12
12--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
@@ -20,9 +21,9 @@ tests = testGroup "Hakyll.Web.CompressCss.Tests" $ concat
20 [ fromAssertions "compressCss"
21 [ fromAssertions "compressCss"
21 [
22 [
22 -- compress whitespace
23 -- compress whitespace
23− "something something" @=?
24+ " something something " @=?
24 compressCss " something \n\t\r something "
25 compressCss " something \n\t\r something "
25− -- do not compress whitespace in string tokens
26+ -- do not compress whitespace in constants
26 , "abc \" \t\n\r \" xyz" @=?
27 , "abc \" \t\n\r \" xyz" @=?
27 compressCss "abc \" \t\n\r \" xyz"
28 compressCss "abc \" \t\n\r \" xyz"
28 , "abc ' \t\n\r ' xyz" @=?
29 , "abc ' \t\n\r ' xyz" @=?
@@ -30,34 +31,28 @@ tests = testGroup "Hakyll.Web.CompressCss.Tests" $ concat
30
31
31 -- strip comments
32 -- strip comments
32 , "before after" @=? compressCss "before /* abc { } ;; \n\t\r */ after"
33 , "before after" @=? compressCss "before /* abc { } ;; \n\t\r */ after"
33− -- don't strip comments inside string tokens
34+ -- don't strip comments inside constants
34 , "before \"/* abc { } ;; \n\t\r */\" after"
35 , "before \"/* abc { } ;; \n\t\r */\" after"
35 @=? compressCss "before \"/* abc { } ;; \n\t\r */\" after"
36 @=? compressCss "before \"/* abc { } ;; \n\t\r */\" after"
36
37
37 -- compress separators
38 -- compress separators
38 , "}" @=? compressCss "; }"
39 , "}" @=? compressCss "; }"
39− , ";{};" @=? compressCss " ; { } ; "
40+ , "{};" @=? compressCss " { } ; "
40− , "text," @=? compressCss "text , "
41− , "a>b" @=? compressCss "a > b"
42− , "a+b" @=? compressCss "a + b"
43− , "a!b" @=? compressCss "a ! b"
44− -- compress calc()
45− , "calc(1px + 100%/(5 + 3) - (3px + 2px)*5)" @=? compressCss "calc( 1px + 100% / ( 5 + 3) - calc( 3px + 2px ) * 5 )"
46 -- compress whitespace even after this curly brace
41 -- compress whitespace even after this curly brace
47 , "}" @=? compressCss "; } "
42 , "}" @=? compressCss "; } "
48− -- but do not compress separators inside string tokens
43+ -- but do not compress separators inside of constants
49− , "\" { } ; , \"" @=? compressCss "\" { } ; , \""
44+ , "\" { } ; \"" @=? compressCss "\" { } ; \""
50− -- don't compress separators at the start or end of string tokens
45+ -- don't compress separators at the start or end of constants
51 , "\" }\"" @=? compressCss "\" }\""
46 , "\" }\"" @=? compressCss "\" }\""
52 , "\"{ \"" @=? compressCss "\"{ \""
47 , "\"{ \"" @=? compressCss "\"{ \""
53− -- don't get irritated by the wrong token delimiter
48+ -- don't get irritated by the wrong constant terminator
54 , "\" ' \"" @=? compressCss "\" ' \""
49 , "\" ' \"" @=? compressCss "\" ' \""
55 , "' \" '" @=? compressCss "' \" '"
50 , "' \" '" @=? compressCss "' \" '"
56− -- don't compress whitespace in the middle of a string
51+ -- don't compress whitespace around separators in constants in the middle of a string
57 , "abc '{ '" @=? compressCss "abc '{ '"
52 , "abc '{ '" @=? compressCss "abc '{ '"
58 , "abc \"{ \"" @=? compressCss "abc \"{ \""
53 , "abc \"{ \"" @=? compressCss "abc \"{ \""
59− -- compress whitespace after colons (but not before)
54+ -- compress whitespace after colons
60− , "abc :xyz" @=? compressCss "abc : xyz"
55+ , "abc:xyz" @=? compressCss "abc : xyz"
61 -- compress multiple semicolons
56 -- compress multiple semicolons
62 , ";" @=? compressCss ";;;;;;;"
57 , ";" @=? compressCss ";;;;;;;"
63 ]
58 ]
tests/Hakyll/Web/Html/Tests.hs+6−6
@@ -7,7 +7,7 @@ module Hakyll.Web.Html.Tests
7--------------------------------------------------------------------------------
7--------------------------------------------------------------------------------
8import Data.Char (toUpper)
8import Data.Char (toUpper)
9import Test.Tasty (TestTree, testGroup)
9import Test.Tasty (TestTree, testGroup)
10−import Test.Tasty.HUnit ((@=?))
10+import Test.Tasty.HUnit (assert, (@=?))
11
11
12
12
13--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
@@ -64,11 +64,11 @@ tests = testGroup "Hakyll.Web.Html.Tests" $ concat
64 ]
64 ]
65
65
66 , fromAssertions "isExternal"
66 , fromAssertions "isExternal"
67− [ True @=? isExternal "http://reddit.com"
67+ [ assert (isExternal "http://reddit.com")
68− , True @=? isExternal "https://mail.google.com"
68+ , assert (isExternal "https://mail.google.com")
69− , True @=? isExternal "//ajax.googleapis.com"
69+ , assert (isExternal "//ajax.googleapis.com")
70− , False @=? isExternal "../header.png"
70+ , assert (not (isExternal "../header.png"))
71− , False @=? isExternal "/foo/index.html"
71+ , assert (not (isExternal "/foo/index.html"))
72 ]
72 ]
73
73
74 , fromAssertions "stripTags"
74 , fromAssertions "stripTags"
tests/Hakyll/Web/Template/Context/Tests.hs+3−40
@@ -13,19 +13,16 @@ import Test.Tasty.HUnit (Assertion, testCase, (@=?))
13--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
14import Hakyll.Core.Compiler
14import Hakyll.Core.Compiler
15import Hakyll.Core.Identifier
15import Hakyll.Core.Identifier
16−import Hakyll.Core.Item
17import Hakyll.Core.Provider
16import Hakyll.Core.Provider
18import Hakyll.Core.Store (Store)
17import Hakyll.Core.Store (Store)
19import Hakyll.Web.Template.Context
18import Hakyll.Web.Template.Context
20−import Hakyll.Web.Template.Internal
21import TestSuite.Util
19import TestSuite.Util
22
20
23
21
24--------------------------------------------------------------------------------
22--------------------------------------------------------------------------------
25tests :: TestTree
23tests :: TestTree
26−tests = testGroup "Hakyll.Web.Template.Context.Tests"
24+tests = testGroup "Hakyll.Core.Template.Context.Tests"
27 [ testCase "testDateField" testDateField
25 [ testCase "testDateField" testDateField
28− , testCase "testOuerLoopContextAccess" testOuerLoopContextAccess
29 ]
26 ]
30
27
31
28
@@ -44,15 +41,6 @@ testDateField = do
44 dateField "date" "%B %e, %Y"
41 dateField "date" "%B %e, %Y"
45 date2 @=? "August 26, 2010"
42 date2 @=? "August 26, 2010"
46
43
47− date3 <- testContextDone store provider
48− "posts/2018-09-26.md" "date" $
49− dateField "date" "%B %e, %Y"
50− date3 @=? "September 26, 2018"
51−
52− date4 <- testContextDone store provider
53− "posts/2019/05/10/tomorrow.md" "date" $
54− dateField "date" "%B %e, %Y"
55− date4 @=? "May 10, 2019"
56 cleanTestEnv
44 cleanTestEnv
57
45
58
46
@@ -65,31 +53,6 @@ testContextDone store provider identifier key context =
65 cf <- unContext context key [] item
53 cf <- unContext context key [] item
66 case cf of
54 case cf of
67 StringField str -> return str
55 StringField str -> return str
68− _ -> error $
56+ ListField _ _ -> error $
69 "Hakyll.Web.Template.Context.Tests.testContextDone: " ++
57 "Hakyll.Web.Template.Context.Tests.testContextDone: " ++
70− "expected StringField"
58+ "Didn't expect ListField"
71−
72−--------------------------------------------------------------------------------
73−
74−testOuerLoopContextAccess :: Assertion
75−testOuerLoopContextAccess = do
76− store <- newTestStore
77− provider <- newTestProvider store
78− test store provider ctx "baz"
79− test store provider (ctx' <> ctx) "not baz"
80− test store provider (ctx <> ctx') "baz"
81−
82− cleanTestEnv
83− where
84− tpl = readTemplate "$for(foo)$$for(bar)$$qux$$endfor$$endfor$"
85− ctx = mconcat [
86− field "qux" $ const $ return "baz"
87− , listField "foo" (listField "bar" mempty $ return [mockItem])
88− $ return [mockItem]
89− ]
90− ctx' = field "qux" $ const $ return "not baz"
91− mockItem = Item "" ()
92− test store provider context str = do
93− str' <- testCompilerDone store provider ""
94− $ applyTemplate tpl context mockItem
95− str @=? itemBody str'
tests/Hakyll/Web/Template/Tests.hs+19−52
@@ -1,6 +1,5 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TemplateHaskell #-}
4module Hakyll.Web.Template.Tests
3module Hakyll.Web.Template.Tests
5 ( tests
4 ( tests
6 ) where
5 ) where
@@ -8,16 +7,16 @@ module Hakyll.Web.Template.Tests
8
7
9--------------------------------------------------------------------------------
8--------------------------------------------------------------------------------
10import Test.Tasty (TestTree, testGroup)
9import Test.Tasty (TestTree, testGroup)
11−import Test.Tasty.HUnit (Assertion, assertBool, testCase,
10+import Test.Tasty.HUnit (Assertion, testCase, (@=?),
12− (@=?), (@?=))
11+ (@?=))
13
12
14−import Data.Either (isLeft)
15
13
16--------------------------------------------------------------------------------
14--------------------------------------------------------------------------------
17import Hakyll.Core.Compiler
15import Hakyll.Core.Compiler
18import Hakyll.Core.Identifier
16import Hakyll.Core.Identifier
19import Hakyll.Core.Item
17import Hakyll.Core.Item
20import Hakyll.Core.Provider
18import Hakyll.Core.Provider
19+import Hakyll.Web.Pandoc
21import Hakyll.Web.Template
20import Hakyll.Web.Template
22import Hakyll.Web.Template.Context
21import Hakyll.Web.Template.Context
23import Hakyll.Web.Template.Internal
22import Hakyll.Web.Template.Internal
@@ -27,20 +26,20 @@ import TestSuite.Util
27
26
28--------------------------------------------------------------------------------
27--------------------------------------------------------------------------------
29tests :: TestTree
28tests :: TestTree
30−tests = testGroup "Hakyll.Web.Template.Tests" $ concat
29+tests = testGroup "Hakyll.Core.Template.Tests" $ concat
31 [ [ testCase "case01" $ test ("template.html.out", "template.html", "example.md")
30 [ [ testCase "case01" $ test ("template.html.out", "template.html", "example.md")
32 , testCase "case02" $ test ("strip.html.out", "strip.html", "example.md")
31 , testCase "case02" $ test ("strip.html.out", "strip.html", "example.md")
33 , testCase "case03" $ test ("just-meta.html.out", "just-meta.html", "example.md")
32 , testCase "case03" $ test ("just-meta.html.out", "just-meta.html", "example.md")
34 , testCase "applyJoinTemplateList" testApplyJoinTemplateList
33 , testCase "applyJoinTemplateList" testApplyJoinTemplateList
35 ]
34 ]
36
35
37− , fromAssertions "parseTemplate"
36+ , fromAssertions "readTemplate"
38− [ Right [Chunk "Hello ", Expr (Call "guest" [])]
37+ [ [Chunk "Hello ", Expr (Call "guest" [])]
39− @=? parse "Hello $guest()$"
38+ @=? readTemplateElems "Hello $guest()$"
40− , Right [If (Call "a" [StringLiteral "bar"]) [Chunk "foo"] Nothing]
39+ , [If (Call "a" [StringLiteral "bar"]) [Chunk "foo"] Nothing]
41− @=? parse "$if(a(\"bar\"))$foo$endif$"
40+ @=? readTemplateElems "$if(a(\"bar\"))$foo$endif$"
42 -- 'If' trim check.
41 -- 'If' trim check.
43− , Right [ TrimL
42+ , [ TrimL
44 , If (Ident (TemplateKey "body"))
43 , If (Ident (TemplateKey "body"))
45 [ TrimR
44 [ TrimR
46 , Chunk "\n"
45 , Chunk "\n"
@@ -56,39 +55,29 @@ tests = testGroup "Hakyll.Web.Template.Tests" $ concat
56 ])
55 ])
57 , TrimR
56 , TrimR
58 ]
57 ]
59− @=? parse "$-if(body)-$\n$body$\n$-else-$\n$body$\n$-endif-$"
58+ @=? readTemplateElems "$-if(body)-$\n$body$\n$-else-$\n$body$\n$-endif-$"
60 -- 'For' trim check.
59 -- 'For' trim check.
61− , Right [ TrimL
60+ , [ TrimL
62 , For (Ident (TemplateKey "authors"))
61 , For (Ident (TemplateKey "authors"))
63 [TrimR, Chunk "\n body \n", TrimL]
62 [TrimR, Chunk "\n body \n", TrimL]
64 Nothing
63 Nothing
65 , TrimR
64 , TrimR
66 ]
65 ]
67− @=? parse "$-for(authors)-$\n body \n$-endfor-$"
66+ @=? readTemplateElems "$-for(authors)-$\n body \n$-endfor-$"
68 -- 'Partial' trim check.
67 -- 'Partial' trim check.
69− , Right [ TrimL
68+ , [ TrimL
70 , Partial (StringLiteral "path")
69 , Partial (StringLiteral "path")
71 , TrimR
70 , TrimR
72 ]
71 ]
73− @=? parse "$-partial(\"path\")-$"
72+ @=? readTemplateElems "$-partial(\"path\")-$"
74 -- 'Expr' trim check.
73 -- 'Expr' trim check.
75− , Right [ TrimL
74+ , [ TrimL
76 , Expr (Ident (TemplateKey "foo"))
75 , Expr (Ident (TemplateKey "foo"))
77 , TrimR
76 , TrimR
78 ]
77 ]
79− @=? parse "$-foo-$"
78+ @=? readTemplateElems "$-foo-$"
80− -- fail on incomplete template.
81− , assertBool "did not yield error" $ isLeft $
82− parse "a$b"
83− -- fail on mismatched template syntax.
84− , assertBool "did not fail to parse" $ isLeft $
85− parse "$for(xs)$\n <p>foo</p>\n$endif$"
86 ]
79 ]
87−
88− , [testCase "embeddedTemplate" testEmbeddedTemplate]
89 ]
80 ]
90− where
91− parse = parseTemplateElemsFile ""
92
81
93
82
94--------------------------------------------------------------------------------
83--------------------------------------------------------------------------------
@@ -100,9 +89,7 @@ test (outf, tplf, itemf) = do
100 out <- resourceString provider outf
89 out <- resourceString provider outf
101 tpl <- testCompilerDone store provider tplf templateBodyCompiler
90 tpl <- testCompilerDone store provider tplf templateBodyCompiler
102 item <- testCompilerDone store provider itemf $
91 item <- testCompilerDone store provider itemf $
103− getResourceBody
104− >>= renderParagraphs
105− >>= applyTemplate (itemBody tpl) testContext
92+ pandocCompiler >>= applyTemplate (itemBody tpl) testContext
106
93
107 out @=? itemBody item
94 out @=? itemBody item
108 cleanTestEnv
95 cleanTestEnv
@@ -125,8 +112,6 @@ testApplyJoinTemplateList :: Assertion
125testApplyJoinTemplateList = do
112testApplyJoinTemplateList = do
126 store <- newTestStore
113 store <- newTestStore
127 provider <- newTestProvider store
114 provider <- newTestProvider store
128− tpl <- testCompilerDone store provider "tpl" $
129− compileTemplateItem (Item "tpl" "<b>$body$</b>")
130 str <- testCompilerDone store provider "item3" $
115 str <- testCompilerDone store provider "item3" $
131 applyJoinTemplateList ", " tpl defaultContext [i1, i2]
116 applyJoinTemplateList ", " tpl defaultContext [i1, i2]
132
117
@@ -135,22 +120,4 @@ testApplyJoinTemplateList = do
135 where
120 where
136 i1 = Item "item1" "Hello"
121 i1 = Item "item1" "Hello"
137 i2 = Item "item2" "World"
122 i2 = Item "item2" "World"
138−
123+ tpl = readTemplate "<b>$body$</b>"
139−
140−--------------------------------------------------------------------------------
141−embeddedTemplate :: Template
142−embeddedTemplate = $(embedTemplate "tests/data/embed.html")
143−
144−--------------------------------------------------------------------------------
145−testEmbeddedTemplate :: Assertion
146−testEmbeddedTemplate = do
147− store <- newTestStore
148− provider <- newTestProvider store
149− str <- testCompilerDone store provider "item3" $
150− applyTemplate embeddedTemplate defaultContext item
151−
152− itemBody str @?= "<p>Hello, world</p>\n"
153− cleanTestEnv
154− where
155− item = Item "item1" "Hello, world"
156−
tests/TestSuite.hs−7
@@ -1,5 +1,4 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2−{-# LANGUAGE CPP #-}
3module Main
2module Main
4 ( main
3 ( main
5 ) where
4 ) where
@@ -23,12 +22,9 @@ import qualified Hakyll.Core.Util.String.Tests
23import qualified Hakyll.Web.CompressCss.Tests
22import qualified Hakyll.Web.CompressCss.Tests
24import qualified Hakyll.Web.Html.RelativizeUrls.Tests
23import qualified Hakyll.Web.Html.RelativizeUrls.Tests
25import qualified Hakyll.Web.Html.Tests
24import qualified Hakyll.Web.Html.Tests
26−#ifdef USE_PANDOC
27import qualified Hakyll.Web.Pandoc.FileType.Tests
25import qualified Hakyll.Web.Pandoc.FileType.Tests
28−#endif
29import qualified Hakyll.Web.Template.Context.Tests
26import qualified Hakyll.Web.Template.Context.Tests
30import qualified Hakyll.Web.Template.Tests
27import qualified Hakyll.Web.Template.Tests
31−import qualified Hakyll.Web.Tags.Tests
32
28
33
29
34--------------------------------------------------------------------------------
30--------------------------------------------------------------------------------
@@ -47,10 +43,7 @@ main = defaultMain $ testGroup "Hakyll"
47 , Hakyll.Web.CompressCss.Tests.tests
43 , Hakyll.Web.CompressCss.Tests.tests
48 , Hakyll.Web.Html.RelativizeUrls.Tests.tests
44 , Hakyll.Web.Html.RelativizeUrls.Tests.tests
49 , Hakyll.Web.Html.Tests.tests
45 , Hakyll.Web.Html.Tests.tests
50−#ifdef USE_PANDOC
51 , Hakyll.Web.Pandoc.FileType.Tests.tests
46 , Hakyll.Web.Pandoc.FileType.Tests.tests
52−#endif
53− , Hakyll.Web.Tags.Tests.tests
54 , Hakyll.Web.Template.Context.Tests.tests
47 , Hakyll.Web.Template.Context.Tests.tests
55 , Hakyll.Web.Template.Tests.tests
48 , Hakyll.Web.Template.Tests.tests
56 ]
49 ]
tests/TestSuite/Util.hs+5−27
@@ -6,15 +6,13 @@ module TestSuite.Util
6 , newTestProvider
6 , newTestProvider
7 , testCompiler
7 , testCompiler
8 , testCompilerDone
8 , testCompilerDone
9− , testCompilerError
10 , testConfiguration
9 , testConfiguration
11 , cleanTestEnv
10 , cleanTestEnv
12− , renderParagraphs
13 ) where
11 ) where
14
12
15
13
16--------------------------------------------------------------------------------
14--------------------------------------------------------------------------------
17−import Data.List (intercalate, isInfixOf)
15+import Data.List (intercalate)
18import Data.Monoid (mempty)
16import Data.Monoid (mempty)
19import qualified Data.Set as S
17import qualified Data.Set as S
20import Test.Tasty
18import Test.Tasty
@@ -31,7 +29,6 @@ import Hakyll.Core.Provider
31import Hakyll.Core.Store (Store)
29import Hakyll.Core.Store (Store)
32import qualified Hakyll.Core.Store as Store
30import qualified Hakyll.Core.Store as Store
33import Hakyll.Core.Util.File
31import Hakyll.Core.Util.File
34−import Hakyll.Core.Item
35
32
36
33
37--------------------------------------------------------------------------------
34--------------------------------------------------------------------------------
@@ -79,23 +76,14 @@ testCompilerDone store provider underlying compiler = do
79 result <- testCompiler store provider underlying compiler
76 result <- testCompiler store provider underlying compiler
80 case result of
77 case result of
81 CompilerDone x _ -> return x
78 CompilerDone x _ -> return x
82− CompilerError e -> fail $
79+ CompilerError e -> error $
83 "TestSuite.Util.testCompilerDone: compiler " ++ show underlying ++
80 "TestSuite.Util.testCompilerDone: compiler " ++ show underlying ++
84− " threw: " ++ intercalate "; " (compilerErrorMessages e)
81+ " threw: " ++ intercalate "; " e
85− CompilerRequire i _ -> fail $
82+ CompilerRequire i _ -> error $
86 "TestSuite.Util.testCompilerDone: compiler " ++ show underlying ++
83 "TestSuite.Util.testCompilerDone: compiler " ++ show underlying ++
87 " requires: " ++ show i
84 " requires: " ++ show i
88− CompilerSnapshot _ _ -> fail
89− "TestSuite.Util.testCompilerDone: unexpected CompilerSnapshot"
90
85
91−testCompilerError :: Store -> Provider -> Identifier -> Compiler a -> String -> IO ()
86+
92−testCompilerError store provider underlying compiler expectedMessage = do
93− result <- testCompiler store provider underlying compiler
94− case result of
95− CompilerError e ->
96− any (expectedMessage `isInfixOf`) (compilerErrorMessages e) @?
97− "Expecting '" ++ expectedMessage ++ "' error"
98− _ -> assertFailure "Expecting CompilerError"
99
87
100--------------------------------------------------------------------------------
88--------------------------------------------------------------------------------
101testConfiguration :: Configuration
89testConfiguration :: Configuration
@@ -113,13 +101,3 @@ cleanTestEnv = do
113 removeDirectory $ destinationDirectory testConfiguration
101 removeDirectory $ destinationDirectory testConfiguration
114 removeDirectory $ storeDirectory testConfiguration
102 removeDirectory $ storeDirectory testConfiguration
115 removeDirectory $ tmpDirectory testConfiguration
103 removeDirectory $ tmpDirectory testConfiguration
116−
117−
118−--------------------------------------------------------------------------------
119−-- | like 'Hakyll.Web.Pandoc.renderPandoc'
120−-- | but allowing to test without the @usePandoc@ flag
121−renderParagraphs :: Item String -> Compiler (Item String)
122−renderParagraphs = withItemBody (return
123− . intercalate "\n" -- no trailing line
124− . map (("<p>"++) . (++"</p>"))
125− . lines)
tests/data/embed.htmldeleted−1
@@ -1 +0,0 @@
1−<p>$body$</p>
tests/data/posts/2018-09-26.mddeleted−1
@@ -1 +0,0 @@
1−Something happened today.
tests/data/posts/2019/05/10/tomorrow.mddeleted−1
@@ -1 +0,0 @@
1−This day hasn't happened yet (as of writing this).
web/css/syntax.css+18−61
@@ -1,61 +1,18 @@
1−a.sourceLine { display: inline-block; line-height: 1.25; }
1+/* Generated by pandoc. */
2−a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
2+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre
3−a.sourceLine:empty { height: 1.2em; }
3+ { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }
4−.sourceCode { overflow: visible; }
4+td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
5−code.sourceCode { white-space: pre; position: relative; }
5+td.sourceCode { padding-left: 5px; }
6−div.sourceCode { margin: 1em 0; }
7−pre.sourceCode { margin: 0; }
8−@media screen {
9−div.sourceCode { overflow: auto; }
10−}
11−@media print {
12−code.sourceCode { white-space: pre-wrap; }
13−a.sourceLine { text-indent: -1em; padding-left: 1em; }
14−}
15−pre.numberSource a.sourceLine
16− { position: relative; left: -4em; }
17−pre.numberSource a.sourceLine::before
18− { content: attr(title);
19− position: relative; left: -1em; text-align: right; vertical-align: baseline;
20− border: none; pointer-events: all; display: inline-block;
21− -webkit-touch-callout: none; -webkit-user-select: none;
22− -khtml-user-select: none; -moz-user-select: none;
23− -ms-user-select: none; user-select: none;
24− padding: 0 4px; width: 4em;
25− color: #aaaaaa;
26− }
27−pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
28−div.sourceCode
29− { }
30−@media screen {
31−a.sourceLine::before { text-decoration: underline; }
32−}
33−code span.al { color: #ff0000; font-weight: bold; } /* Alert */
34−code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
35−code span.at { color: #7d9029; } /* Attribute */
36−code span.bn { color: #40a070; } /* BaseN */
37−code span.bu { } /* BuiltIn */
38−code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
6+.sourceCode span.kw { color: #007020; font-weight: bold; }
39−code span.ch { color: #4070a0; } /* Char */
40−code span.cn { color: #880000; } /* Constant */
41−code span.co { color: #60a0b0; font-style: italic; } /* Comment */
42−code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
43−code span.do { color: #ba2121; font-style: italic; } /* Documentation */
44−code span.dt { color: #902000; } /* DataType */
7+.sourceCode span.dt { color: #902000; }
45−code span.dv { color: #40a070; } /* DecVal */
8+.sourceCode span.dv { color: #40a070; }
46−code span.er { color: #ff0000; font-weight: bold; } /* Error */
9+.sourceCode span.bn { color: #40a070; }
47−code span.ex { } /* Extension */
48−code span.fl { color: #40a070; } /* Float */
10+.sourceCode span.fl { color: #40a070; }
11+.sourceCode span.ch { color: #4070a0; }
12+.sourceCode span.st { color: #4070a0; }
13+.sourceCode span.co { color: #60a0b0; font-style: italic; }
14+.sourceCode span.ot { color: #007020; }
15+.sourceCode span.al { color: red; font-weight: bold; }
49−code span.fu { color: #06287e; } /* Function */
16+.sourceCode span.fu { color: #06287e; }
50−code span.im { } /* Import */
17+.sourceCode span.re { }
51−code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
18+.sourceCode span.er { color: red; font-weight: bold; }
52−code span.kw { color: #007020; font-weight: bold; } /* Keyword */
53−code span.op { color: #666666; } /* Operator */
54−code span.ot { color: #007020; } /* Other */
55−code span.pp { color: #bc7a00; } /* Preprocessor */
56−code span.sc { color: #4070a0; } /* SpecialChar */
57−code span.ss { color: #bb6688; } /* SpecialString */
58−code span.st { color: #4070a0; } /* String */
59−code span.va { color: #19177c; } /* Variable */
60−code span.vs { color: #4070a0; } /* VerbatimString */
61−code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
web/examples.markdown+29−45
@@ -20,8 +20,6 @@ directly with the default Hakyll site.
20 [source](https://github.com/jaspervdj/jaspervdj)
20 [source](https://github.com/jaspervdj/jaspervdj)
21- <http://www.imagination-land.org/>,
21- <http://www.imagination-land.org/>,
22 [source](https://github.com/Keruspe/blog/)
22 [source](https://github.com/Keruspe/blog/)
23−- <https://bananasandlenses.net/>,
24− [source](https://github.com/denisshevchenko/bananasandlenses)
25- <http://blog.clement.delafargue.name/>,
23- <http://blog.clement.delafargue.name/>,
26 [source](https://github.com/divarvel/blog)
24 [source](https://github.com/divarvel/blog)
27- <http://bneijt.nl>,
25- <http://bneijt.nl>,
@@ -36,6 +34,8 @@ directly with the default Hakyll site.
36 [source](https://github.com/dannysu/hakyll-blog)
34 [source](https://github.com/dannysu/hakyll-blog)
37- <http://meta.plasm.us/>,
35- <http://meta.plasm.us/>,
38 [source](https://github.com/travisbrown/metaplasm)
36 [source](https://github.com/travisbrown/metaplasm)
37+- <http://www.web2day-nantes.org/>,
38+ [source](https://github.com/CompanyCampus/web2day2013)
39- <http://workforpizza.com/>,
39- <http://workforpizza.com/>,
40 [source](https://github.com/irneh/workforpizza)
40 [source](https://github.com/irneh/workforpizza)
41- <http://poleiro.info/>,
41- <http://poleiro.info/>,
@@ -45,7 +45,9 @@ directly with the default Hakyll site.
45- <http://www.regisfoucault.com/>,
45- <http://www.regisfoucault.com/>,
46 [source](https://github.com/regisfoucault/blog)
46 [source](https://github.com/regisfoucault/blog)
47- <http://www.chaoxuprime.com/>,
47- <http://www.chaoxuprime.com/>,
48− [source](https://github.com/chaoxu/chaoxu.github.io/tree/develop)
48+ [source](https://github.com/Mgccl/blog)
49+- <https://benjeffrey.com/>,
50+ [source](https://github.com/jeffbr13/benjeffrey.com)
49- <http://www.skybluetrades.net/>,
51- <http://www.skybluetrades.net/>,
50 [source](https://github.com/ian-ross/blog)
52 [source](https://github.com/ian-ross/blog)
51- <http://chromaticleaves.com/>,
53- <http://chromaticleaves.com/>,
@@ -56,6 +58,8 @@ directly with the default Hakyll site.
56 [source](https://github.com/blaenk/blaenk.github.io)
58 [source](https://github.com/blaenk/blaenk.github.io)
57- <https://xinitrc.de/>,
59- <https://xinitrc.de/>,
58 [source](https://github.com/xinitrc/xinitrc.de)
60 [source](https://github.com/xinitrc/xinitrc.de)
61+- <http://blog.darkfox.id.au/>,
62+ [source](http://hub.darcs.net/DarkFox/DarkFox-blog)
59- <http://nickcharlton.net/>,
63- <http://nickcharlton.net/>,
60 [source](https://github.com/nickcharlton/nickcharlton.net)
64 [source](https://github.com/nickcharlton/nickcharlton.net)
61- <http://scr.stunts.hu/>,
65- <http://scr.stunts.hu/>,
@@ -68,10 +72,16 @@ directly with the default Hakyll site.
68 [source](https://github.com/walkie/WebPage)
72 [source](https://github.com/walkie/WebPage)
69- <http://techblog.rosedu.org/>,
73- <http://techblog.rosedu.org/>,
70 [source](https://github.com/rosedu/techblog)
74 [source](https://github.com/rosedu/techblog)
75+- <http://abizern.org>,
76+ [source](https://github.com/Abizern/hblog)
71- <http://freizl.github.io>,
77- <http://freizl.github.io>,
72 [source](https://github.com/freizl/freizl.github.com/tree/master/build)
78 [source](https://github.com/freizl/freizl.github.com/tree/master/build)
79+- <http://covariant.me>,
80+ [source](http://hub.darcs.net/co-dan/website)
73- <http://www.gwern.net/>,
81- <http://www.gwern.net/>,
74 [source](https://github.com/gwern/gwern.net)
82 [source](https://github.com/gwern/gwern.net)
83+- <http://www.rohanjain.in/>,
84+ [source](https://github.com/crodjer/rohanjain.in)
75- <http://www.corentindupont.info/>,
85- <http://www.corentindupont.info/>,
76 [source](https://github.com/cdupont/CorentinDupont-WebPage)
86 [source](https://github.com/cdupont/CorentinDupont-WebPage)
77- <http://jelv.is>,
87- <http://jelv.is>,
@@ -80,8 +90,8 @@ directly with the default Hakyll site.
80 [source](https://github.com/plaimi/www)
90 [source](https://github.com/plaimi/www)
81- <http://duplode.github.io/>,
91- <http://duplode.github.io/>,
82 [source](https://github.com/duplode/duplode.github.io/tree/sources)
92 [source](https://github.com/duplode/duplode.github.io/tree/sources)
83−- <http://tzemanovic.github.io/>,
93+- <http://maseek.codes>,
84− [source](https://github.com/tzemanovic/tzemanovic)
94+ [source](https://github.com/maseek/maseek-codes)
85- <http://listx.github.io>,
95- <http://listx.github.io>,
86 [source](https://github.com/listx/listx_blog)
96 [source](https://github.com/listx/listx_blog)
87- <http://kyle.marek-spartz.org>,
97- <http://kyle.marek-spartz.org>,
@@ -92,20 +102,26 @@ directly with the default Hakyll site.
92 [source](https://github.com/rbros/reichertbrothers.com)
102 [source](https://github.com/rbros/reichertbrothers.com)
93- <http://alemedeiros.sdf.org>,
103- <http://alemedeiros.sdf.org>,
94 [source](https://github.com/alemedeiros/homepage)
104 [source](https://github.com/alemedeiros/homepage)
105+- <https://ruudvanasseldonk.com/>,
106+ [source](https://github.com/ruud-v-a/ruudvanasseldonk.com)
95- <http://www.haskell.mn>,
107- <http://www.haskell.mn>,
96 [source](https://github.com/HaskellMN/www.haskell.mn)
108 [source](https://github.com/HaskellMN/www.haskell.mn)
97- <https://axiomatic.neophilus.net/>,
109- <https://axiomatic.neophilus.net/>,
98 [source](https://github.com/Libbum/AxiomaticSemantics)
110 [source](https://github.com/Libbum/AxiomaticSemantics)
99−- [https://tesser.org/](http://web.archive.org/web/20161022221713/https://tesser.org/),
111+- <https://tesser.org/>,
100 [source](https://github.com/fractalcat/tesser.org)
112 [source](https://github.com/fractalcat/tesser.org)
101−- <https://weien.io/>,
113+- <https://wei2912.github.io/>,
102−  [source](https://github.com/wei2912/blog-src)
114+ [source](https://github.com/wei2912/blog_src)
103- <http://www.metasepi.org/>,
115- <http://www.metasepi.org/>,
104 [source](https://github.com/metasepi/metasepi-website)
116 [source](https://github.com/metasepi/metasepi-website)
105- <http://gisli.hamstur.is/>,
117- <http://gisli.hamstur.is/>,
106 [source](https://github.com/gislik/gisli.hamstur.is)
118 [source](https://github.com/gislik/gisli.hamstur.is)
107- <http://blog.ssanj.net/>,
119- <http://blog.ssanj.net/>,
108 [source](https://github.com/ssanj/babyloncandle)
120 [source](https://github.com/ssanj/babyloncandle)
121+- <https://rockymadden.com/>,
122+ [source](https://github.com/rockymadden/rockymadden-web)
123+- <http://blog.dshevchenko.biz/>,
124+ [source](https://github.com/denisshevchenko/blog)
109- <http://ruhaskell.org/>,
125- <http://ruhaskell.org/>,
110 [source](https://github.com/ruHaskell/ruhaskell)
126 [source](https://github.com/ruHaskell/ruhaskell)
111- <http://www.haskell.od.ua/>,
127- <http://www.haskell.od.ua/>,
@@ -126,6 +142,8 @@ directly with the default Hakyll site.
126 [source](https://github.com/ismailmustafa/ismailmustafa.github.io/tree/hakyll)
142 [source](https://github.com/ismailmustafa/ismailmustafa.github.io/tree/hakyll)
127- <http://lettier.github.io/>,
143- <http://lettier.github.io/>,
128 [source](https://github.com/lettier/lettier.github.io)
144 [source](https://github.com/lettier/lettier.github.io)
145+- <http://jozefg.bitbucket.org/>,
146+ [source](https://github.com/jozefg/blog)
129- <http://raindev.io>,
147- <http://raindev.io>,
130 [source](https://github.com/raindev/raindev.github.io)
148 [source](https://github.com/raindev/raindev.github.io)
131- <http://hal2016.haskell.org/>,
149- <http://hal2016.haskell.org/>,
@@ -144,46 +162,10 @@ directly with the default Hakyll site.
144 [source](https://github.com/jjduhamel/blog)
162 [source](https://github.com/jjduhamel/blog)
145- <http://alexanderlobov.ru/>,
163- <http://alexanderlobov.ru/>,
146 [source](https://github.com/alexanderlobov/homepage)
164 [source](https://github.com/alexanderlobov/homepage)
147−- <http://www.rosanbo.com/>,
148− [source](https://github.com/polo2ro/blog)
149−- <http://limansky.me/>,
150− [source](https://github.com/limansky/limansky_me)
151- <http://rahul.nu/>,
165- <http://rahul.nu/>,
152 [source](https://github.com/rp/rp.github.io/tree/dev)
166 [source](https://github.com/rp/rp.github.io/tree/dev)
153- <http://haskanything.com/>,
167- <http://haskanything.com/>,
154− [source](https://github.com/beerendlauwers/HaskAnything)
168+[source](https://github.com/beerendlauwers/HaskAnything)
155−- <https://anler.me/>,
156− [source](https://github.com/anler/anler.me)
157−- <http://argumatronic.com/>,
158− [source](https://gitlab.com/GinBaby/argumatronic/tree/master)
159−- <http://sillybytes.net/>,
160− [source](https://github.com/sillybytes/sillybytes)
161−- <https://falconpilot.github.io/>,
162− [source](https://github.com/FalconPilot/falconpilot.github.io)
163−- <http://spyhop.cafe/>,
164− [source](https://github.com/thunky-monk/spyhop-cafe)
165−- <https://bendo.github.io/>,
166− [source](https://github.com/bendo/bendo.github.io)
167−- <http://adarsh.cc/>,
168− [source](https://github.com/adarshp/adarsh.cc)
169−- <http://0a.io>,
170− [source](https://github.com/arrchyy/0a.io)
171−- <https://nasy.moe/>,
172− [source](https://github.com/nasyxx/NasyMoe)
173−- <http://uniprocess.org/>,
174− [source](https://gitlab.com/uniprocess/uniprocess.org)
175−- <https://regularflolloping.com/>,
176− [source](https://github.com/techieAgnostic/rf)
177−- <http://enter-haken.github.io/>,
178− [source](https://github.com/enter-haken/blog)
179−- <https://modular.blind.guru/>,
180− [source](https://github.com/mlang/eurorack-metadata)
181−- <http://www.jonashietala.se/>,
182− [source](https://github.com/treeman/jonashietala)
183−- <https://abhinavsarkar.net/>,
184− [source](https://github.com/abhin4v/abhin4v.github.io)
185−- <https://dailyreadingnotes.com/>,
186− [source](https://github.com/hackeryarn/daily-reading-notes)
187
169
188## Hakyll 3.X
170## Hakyll 3.X
189
171
@@ -211,5 +193,7 @@ directly with the default Hakyll site.
211 [source](http://gitorious.org/shakthimaan-blog)
193 [source](http://gitorious.org/shakthimaan-blog)
212- <http://www.alfredodinapoli.com/>,
194- <http://www.alfredodinapoli.com/>,
213 [source](https://github.com/CharlesStain/alfredodinapoli.com)
195 [source](https://github.com/CharlesStain/alfredodinapoli.com)
196+- <http://datahackermd.com>,
197+ [source](http://github.com/akshayjshah/datahackermd)
214- <http://michaelxavier.net>,
198- <http://michaelxavier.net>,
215 [source](https://github.com/michaelxavier/michaelxavier.net)
199 [source](https://github.com/michaelxavier/michaelxavier.net)
web/libraries.markdown−1
@@ -18,4 +18,3 @@ Here is a list of the ones I know of (I would be happy to hear about others).
18 a conversion tool from other blog engines to Hakyll.
18 a conversion tool from other blog engines to Hakyll.
19- [hakyll-elm](https://hackage.haskell.org/package/hakyll-elm),
19- [hakyll-elm](https://hackage.haskell.org/package/hakyll-elm),
20 Hakyll wrapper for the Elm compiler.
20 Hakyll wrapper for the Elm compiler.
21−- [hakyll-sass](http://hackage.haskell.org/package/hakyll-sass), a compiler for SASS templates.
web/site.hs+32−14
@@ -1,7 +1,8 @@
1--------------------------------------------------------------------------------
1--------------------------------------------------------------------------------
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3import Control.Arrow (second)
3import Control.Arrow (second)
4−import Control.Monad (filterM, forM_)
4+import Control.Monad (forM_)
5+import Data.Char (isDigit)
5import Data.List (isPrefixOf, sortBy)
6import Data.List (isPrefixOf, sortBy)
6import Data.Monoid ((<>))
7import Data.Monoid ((<>))
7import Data.Ord (comparing)
8import Data.Ord (comparing)
@@ -56,11 +57,17 @@ main = hakyllWith config $ do
56 create ["tutorials.html"] $ do
57 create ["tutorials.html"] $ do
57 route idRoute
58 route idRoute
58 compile $ do
59 compile $ do
59− ctx <- tutorialsCtx <$>
60+ tuts <-
60 sortBy (comparing itemIdentifier) <$> loadAll "tutorials/*"
61 sortBy (comparing itemIdentifier) <$> loadAll "tutorials/*"
62+
63+ let tutorialsCtx =
64+ constField "title" "Tutorials" `mappend`
65+ listField "tutorials" tutorialCtx (return tuts) `mappend`
66+ defaultContext
67+
61 makeItem ""
68 makeItem ""
62− >>= loadAndApplyTemplate "templates/tutorials.html" ctx
69+ >>= loadAndApplyTemplate "templates/tutorials.html" tutorialsCtx
63− >>= loadAndApplyTemplate "templates/default.html" ctx
70+ >>= loadAndApplyTemplate "templates/default.html" tutorialsCtx
64 >>= relativizeUrls
71 >>= relativizeUrls
65
72
66 -- Templates
73 -- Templates
@@ -101,17 +108,28 @@ hackage url
101 reverse $ splitPath url
108 reverse $ splitPath url
102
109
103
110
111+--------------------------------------------------------------------------------
112+data TutorialType = SeriesTutorial | ArticlesTutorial | ExternalTutorial
113+ deriving (Eq)
114+
115+
104--------------------------------------------------------------------------------
116--------------------------------------------------------------------------------
105-- | Partition tutorials into tutorial series, other articles, external articles
117-- | Partition tutorials into tutorial series, other articles, external articles
106−tutorialsCtx :: [Item String] -> Context String
118+tutorialCtx :: Context String
107−tutorialsCtx tuts =
119+tutorialCtx =
108− constField "title" "Tutorials" <>
120+ field "isSeries" (isTutorialType SeriesTutorial) <>
109− listField "main" defaultContext (ofType "main") <>
121+ field "isArticle" (isTutorialType ArticlesTutorial) <>
110− listField "articles" defaultContext (ofType "article") <>
122+ field "isExternal" (isTutorialType ExternalTutorial) <>
111− listField "externals" defaultContext (ofType "external") <>
112− listField "robertwpearce" defaultContext (ofType "robertwpearce") <>
113 defaultContext
123 defaultContext
114 where
124 where
115− ofType ty = filterM (\item -> do
125+ getTutorialType item = do
116− mbType <- getMetadataField (itemIdentifier item) "type"
126+ mbExternal <- getMetadataField (itemIdentifier item) "external"
117− return $ Just ty == mbType) tuts
127+ return $ case mbExternal of
128+ Just _ -> ExternalTutorial
129+ _ -> case splitPath (toFilePath $ itemIdentifier item) of
130+ [_, (x : _)] -> if isDigit x then SeriesTutorial else ArticlesTutorial
131+ _ -> ArticlesTutorial
132+
133+ isTutorialType ty0 item = do
134+ ty1 <- getTutorialType item
135+ if ty0 == ty1 then return "yes" else fail "no"
web/templates/default.html+6−1
@@ -35,7 +35,12 @@
35 <a href="/tutorials/faq.html">faq</a>
35 <a href="/tutorials/faq.html">faq</a>
36 <a href="/examples.html">examples</a>
36 <a href="/examples.html">examples</a>
37 <a href="/releases.html">releases</a>
37 <a href="/releases.html">releases</a>
38+
39+ <!-- Flattr button -->
40+ <h1>Donate</h1>
38− <a href="https://jaspervdj.be/contact.html#donate" target="_blank">donate</a>
41+ <a href="https://flattr.com/thing/291889/Hakyll" target="_blank">
42+ <img src="https://api.flattr.com/button/flattr-badge-large.png"
43+ alt="Flattr this" title="Flattr this" border="0" /></a>
39 </div>
44 </div>
40
45
41 <div id="content">
46 <div id="content">
web/templates/tutorials.html+18−24
@@ -1,19 +1,23 @@
1<h1>Tutorials about Hakyll</h1>
1<h1>Tutorials about Hakyll</h1>
2<h2 id="series">Tutorial series</h2>
2<h2 id="series">Tutorial series</h2>
3<ul>
3<ul>
4− $for(main)$
4+ $for(tutorials)$
5+ $if(isSeries)$
5− <li>
6+ <li>
6− <a href="$url$">$title$</a>
7+ <a href="$url$">$title$</a>
7− </li>
8+ </li>
9+ $endif$
8 $endfor$
10 $endfor$
9</ul>
11</ul>
10<h2 id="articles">Other articles</h2>
12<h2 id="articles">Other articles</h2>
11<p>In no particular order:</p>
13<p>In no particular order:</p>
12<ul>
14<ul>
13− $for(articles)$
15+ $for(tutorials)$
16+ $if(isArticle)$
14− <li>
17+ <li>
15− <a href="$url$">$title$</a> by <em>$author$</em>
18+ <a href="$url$">$title$</a> by <em>$author$</em>
16− </li>
19+ </li>
20+ $endif$
17 $endfor$
21 $endfor$
18</ul>
22</ul>
19<h2 id="external-articles">External articles</h2>
23<h2 id="external-articles">External articles</h2>
@@ -24,22 +28,12 @@
24</p>
28</p>
25<p>In no particular order:</p>
29<p>In no particular order:</p>
26<ul>
30<ul>
27− $for(externals)$
31+ $for(tutorials)$
32+ $if(isExternal)$
28− <li>
33+ <li>
29− <a href="$url$">$title$</a> by <em>$author$</em>
34+ <a href="$url$">$title$</a> by <em>$author$</em>
30− </li>
35+ </li>
31− $endfor$
36+ $endif$
32−</ul>
33−<h2 id="robertwpearce">Robert Pearce's series</h2>
34−<p>
35− <a href="https://robertwpearce.com/">Robert Pearce</a> has been writing an
36− excellent tutorial-style series on Hakyll as well. You can find those here:
37−</p>
38−<ul>
39− $for(robertwpearce)$
40− <li>
41− <a href="$url$">$title$</a>
42− </li>
43 $endfor$
37 $endfor$
44</ul>
38</ul>
45<p>
39<p>
web/tutorials/01-installation.markdown+1−4
@@ -1,7 +1,6 @@
1---
1---
2title: Installation
2title: Installation
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Installation
6Installation
@@ -18,8 +17,6 @@ different distributions. For installation from source (i.e. via Hackage),
18Linux distro packages:
17Linux distro packages:
19
18
20- [Debian unstable](http://packages.debian.org/source/sid/haskell-hakyll)
19- [Debian unstable](http://packages.debian.org/source/sid/haskell-hakyll)
21−- [Fedora](https://apps.fedoraproject.org/packages/ghc-hakyll)
22−- [Nix](https://nixos.org/nixos/packages.html#hakyll): `$ nix-env -i hakyll`
23
20
24Building the example site
21Building the example site
25-------------------------
22-------------------------
@@ -28,7 +25,7 @@ Apart from the main Hakyll library, the cabal package also provides you with an
28executable `hakyll-init` to create an example site. This is an easy way to get
25executable `hakyll-init` to create an example site. This is an easy way to get
29started:
26started:
30
27
31− $ stack exec hakyll-init my-site
28+ $ hakyll-init my-site
32
29
33This creates a folder `my-site` in the current directory, with some example
30This creates a folder `my-site` in the current directory, with some example
34content and a generic configuration.
31content and a generic configuration.
web/tutorials/02-basics.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: The basics
2title: The basics
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Building and cleaning
6Building and cleaning
web/tutorials/03-rules-routes-compilers.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Rules, routes and compilers
2title: Rules, routes and compilers
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Basic rules
6Basic rules
web/tutorials/04-compilers.markdown+3−4
@@ -1,7 +1,6 @@
1---
1---
2title: 'More on compilers: load, and templates'
2title: 'More on compilers: load, and templates'
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Loading items
6Loading items
@@ -93,7 +92,7 @@ And `$title$` like this:
93titleContext :: Context a
92titleContext :: Context a
94titleContext = field "title" $ \item -> do
93titleContext = field "title" $ \item -> do
95 metadata <- getMetadata (itemIdentifier item)
94 metadata <- getMetadata (itemIdentifier item)
96− return $ fromMaybe "No title" $ lookupString "title" metadata
95+ return $ fromMaybe "No title" $ M.lookup "title" metadata
97```
96```
98
97
99And compose them using the `Monoid` instance:
98And compose them using the `Monoid` instance:
@@ -131,7 +130,7 @@ postCtx =
131### Loading and applying templates
130### Loading and applying templates
132
131
133Now we know about templates, context and how to load arbitrary items. This gives
132Now we know about templates, context and how to load arbitrary items. This gives
134−us enough background information in order to understand how you can apply a
133+us enough background information in order to understand you can apply a
135template:
134template:
136
135
137```haskell
136```haskell
@@ -152,7 +151,7 @@ Control flow in templates
152-------------------------
151-------------------------
153
152
154Sometimes string interpolation does not suffice, and you want a little more
153Sometimes string interpolation does not suffice, and you want a little more
155−control over how your templates are laid out. Hakyll provides a few control
154+control over how your templates are layed out. Hakyll provides a few control
156structures for this. The syntax for these structures was based on the syntax
155structures for this. The syntax for these structures was based on the syntax
157used in pandoc templates, since Hakyll already has tight integration with
156used in pandoc templates, since Hakyll already has tight integration with
158pandoc.
157pandoc.
web/tutorials/05-snapshots-feeds.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Snapshots, and how to produce an RSS/Atom feed
2title: Snapshots, and how to produce an RSS/Atom feed
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Basic feed configuration
6Basic feed configuration
web/tutorials/06-versions.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Producing multiple versions of a single file
2title: Producing multiple versions of a single file
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: main
5---
4---
6
5
7Basics
6Basics
web/tutorials/a-guide-to-the-hakyll-module-zoo.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: A Guide to the Hakyll Module Zoo
2title: A Guide to the Hakyll Module Zoo
3author: Brent Yorgey
3author: Brent Yorgey
4−type: article
5---
4---
6
5
7The hakyll package [contains a bewildering array](/reference/) of modules, and
6The hakyll package [contains a bewildering array](/reference/) of modules, and
web/tutorials/external-add-tags-to-your-hakyll-blog.md+1−1
@@ -2,5 +2,5 @@
2title: Add tags to your Hakyll blog
2title: Add tags to your Hakyll blog
3author: Javran Cheng
3author: Javran Cheng
4url: https://javran.github.io/posts/2014-03-01-add-tags-to-your-hakyll-blog.html
4url: https://javran.github.io/posts/2014-03-01-add-tags-to-your-hakyll-blog.html
5−type: external
5+external: true
6---
6---
web/tutorials/external-blogger-port.mddeleted−6
@@ -1,6 +0,0 @@
1−---
2−title: Port an existing Blogger blog to Hakyll
3−author: Daniel Campoverde
4−url: 'http://www.sillybytes.net/posts/from_blogger_to_hakyll.html'
5−type: external
6−---
web/tutorials/external-cassius-template.mddeleted−6
@@ -1,6 +0,0 @@
1−---
2−title: Using Cassius templating with Hakyll
3−author: Daniel Campoverde
4−url: 'http://www.sillybytes.net/posts/using_hakyll_with_cassius.html'
5−type: external
6−---
web/tutorials/external-clean-urls-with-hakyll.md+1−1
@@ -2,5 +2,5 @@
2title: Clean URLs with Hakyll
2title: Clean URLs with Hakyll
3author: Rohan Jain
3author: Rohan Jain
4url: http://www.rohanjain.in/hakyll-clean-urls/
4url: http://www.rohanjain.in/hakyll-clean-urls/
5−type: external
5+external: true
6---
6---
web/tutorials/external-deploying-with-widely.md+1−1
@@ -2,5 +2,5 @@
2title: Deploying with Widely
2title: Deploying with Widely
3author: Kyle Marek-Spartz
3author: Kyle Marek-Spartz
4url: http://kyle.marek-spartz.org/posts/2013-12-09-widely-and-hakyll.html
4url: http://kyle.marek-spartz.org/posts/2013-12-09-widely-and-hakyll.html
5−type: external
5+external: true
6---
6---
web/tutorials/external-external-code-inclusion.mddeleted−6
@@ -1,6 +0,0 @@
1−---
2−title: 'External code inclusion with Hakyll'
3−author: 'Tobias Pleyer'
4−url: 'http://blog.tpleyer.de/posts/2019-04-21-external-code-inclusion-with-hakyll.html'
5−type: external
6−---
web/tutorials/external-functionfield.md+1−1
@@ -2,5 +2,5 @@
2title: Hakyll's functionField
2title: Hakyll's functionField
3author: Beerend Lauwers
3author: Beerend Lauwers
4url: http://beerendlauwers.be/posts/2015-09-21-hakylls-functionfield.html
4url: http://beerendlauwers.be/posts/2015-09-21-hakylls-functionfield.html
5−type: external
5+external: true
6---
6---
web/tutorials/external-github-pages-circle-ci.md+1−1
@@ -2,5 +2,5 @@
2title: Create a GitHub page with Hakyll and CircleCI
2title: Create a GitHub page with Hakyll and CircleCI
3author: Juan Pedro Villa
3author: Juan Pedro Villa
4url: https://www.stackbuilders.com/news/dr-hakyll-create-a-github-page-with-hakyll-and-circleci
4url: https://www.stackbuilders.com/news/dr-hakyll-create-a-github-page-with-hakyll-and-circleci
5−type: external
5+external: true
6---
6---
web/tutorials/external-inlining-and-compressing-css.md+1−1
@@ -2,5 +2,5 @@
2title: Inlining and compressing CSS
2title: Inlining and compressing CSS
3author: Kyle Marek-Spartz
3author: Kyle Marek-Spartz
4url: http://kyle.marek-spartz.org/posts/2014-12-09-hakyll-css-template-compiler.html
4url: http://kyle.marek-spartz.org/posts/2014-12-09-hakyll-css-template-compiler.html
5−type: external
5+external: true
6---
6---
web/tutorials/external-live-reload.mdnew file+6
@@ -0,0 +1,6 @@
1+---
2+title: Live Reloading with Hakyll
3+author: Ben Kolera
4+url: 'http://benkolera.com/posts/2015-09-14-hakyll_livereload.html'
5+external: true
6+---
web/tutorials/faq.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: FAQ
2title: FAQ
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: article
5---
4---
6
5
7## "hGetContents: invalid argument" or "commitBuffer: invalid argument"
6## "hGetContents: invalid argument" or "commitBuffer: invalid argument"
web/tutorials/github-pages-tutorial.md−1
@@ -1,7 +1,6 @@
1---
1---
2title: Using Hakyll with GitHub Pages
2title: Using Hakyll with GitHub Pages
3author: Erik Stevenson
3author: Erik Stevenson
4−type: article
5---
4---
6
5
7## Introduction
6## Introduction
web/tutorials/hakyll-3-to-hakyll4-migration-guide.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Hakyll 3 to Hakyll 4 migration guide
2title: Hakyll 3 to Hakyll 4 migration guide
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: article
5---
4---
6
5
7Introduction
6Introduction
web/tutorials/robertwpearce-01-setup-and-initial-customization.htmldeleted−5
@@ -1,5 +0,0 @@
1−---
2−title: 'Pt. 1: Setup & Initial Customization'
3−url: 'https://robertwpearce.com/hakyll-pt-1-setup-and-initial-customization.html'
4−type: robertwpearce
5−---
web/tutorials/robertwpearce-02-generating-a-sitemap-xml-file.htmldeleted−5
@@ -1,5 +0,0 @@
1−---
2−title: 'Pt. 2: Generating a Sitemap XML File'
3−url: 'https://robertwpearce.com/hakyll-pt-2-generating-a-sitemap-xml-file.html'
4−type: robertwpearce
5−---
web/tutorials/robertwpearce-03-generating-rss-and-atom-xml-feeds.htmldeleted−5
@@ -1,5 +0,0 @@
1−---
2−title: 'Pt. 3: Generating RSS and Atom XML Feeds'
3−url: 'https://robertwpearce.com/hakyll-pt-3-generating-rss-and-atom-xml-feeds.html'
4−type: robertwpearce
5−---
web/tutorials/robertwpearce-04-copying-static-files-for-your-build.htmldeleted−5
@@ -1,5 +0,0 @@
1−---
2−title: 'Pt. 4: Copying Static Files For Your Build'
3−url: 'https://robertwpearce.com/hakyll-pt-4-copying-static-files-for-your-build.html'
4−type: robertwpearce
5−---
web/tutorials/robertwpearce-05-generating-custom-post-filenames-from-a-title-slug.htmldeleted−5
@@ -1,5 +0,0 @@
1−---
2−title: 'Pt. 5 – Generating Custom Post Filenames From a Title Slug'
3−url: 'https://robertwpearce.com/hakyll-pt-5-generating-custom-post-filenames-from-a-title-slug.html'
4−type: robertwpearce
5−---
web/tutorials/using-clay-with-hakyll.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Using Clay with Hakyll
2title: Using Clay with Hakyll
3author: Jasper Van der Jeugt
3author: Jasper Van der Jeugt
4−type: article
5---
4---
6
5
7[Clay](http://sebastiaanvisser.github.com/clay/) is a nice CSS preprocesser
6[Clay](http://sebastiaanvisser.github.com/clay/) is a nice CSS preprocesser
web/tutorials/using-teasers-in-hakyll.markdown−1
@@ -1,7 +1,6 @@
1---
1---
2title: Using teasers in Hakyll
2title: Using teasers in Hakyll
3author: Ivan Veselov
3author: Ivan Veselov
4−type: article
5---
4---
6
5
7## Introduction
6## Introduction