on master help sign in
Add redirect module to Hakyll
commit718c9a407caddfdaeff56d1148f02fb09a088044 authorJasper Van der Jeugt <m@jaspervdj.be> dateSat 7 Jan 2017, 17:27 (10 years ago) parent5bfff2b
3 files changed+86−1
hakyll.cabal+1 src/Hakyll.hs+3−1 src/Hakyll/Web/Redirect.hs+82
hakyll.cabal+1
@@ -121,6 +121,7 @@ Library
121121 Hakyll.Web.Pandoc
122122 Hakyll.Web.Pandoc.Biblio
123123 Hakyll.Web.Pandoc.FileType
124+ Hakyll.Web.Redirect
124125 Hakyll.Web.Tags
125126 Hakyll.Web.Paginate
126127 Hakyll.Web.Template
src/Hakyll.hs+3−1
@@ -21,10 +21,11 @@ module Hakyll
2121 , module Hakyll.Web.Html
2222 , module Hakyll.Web.Html.RelativizeUrls
2323 , module Hakyll.Web.Pandoc
24+ , module Hakyll.Web.Paginate
2425 , module Hakyll.Web.Pandoc.Biblio
2526 , module Hakyll.Web.Pandoc.FileType
27+ , module Hakyll.Web.Redirect
2628 , module Hakyll.Web.Tags
27− , module Hakyll.Web.Paginate
2829 , module Hakyll.Web.Template
2930 , module Hakyll.Web.Template.Context
3031 , module Hakyll.Web.Template.List
@@ -54,6 +55,7 @@ import Hakyll.Web.Paginate
5455import Hakyll.Web.Pandoc
5556import Hakyll.Web.Pandoc.Biblio
5657import Hakyll.Web.Pandoc.FileType
58+import Hakyll.Web.Redirect
5759import Hakyll.Web.Tags
5860import Hakyll.Web.Template
5961import Hakyll.Web.Template.Context
src/Hakyll/Web/Redirect.hsnew file+82
@@ -0,0 +1,82 @@
1+-- | Module used for generating HTML redirect pages. This allows renaming pages
2+-- to avoid breaking existing links without requiring server-side support for
3+-- formal 301 Redirect error codes
4+module Hakyll.Web.Redirect
5+ ( Redirect (..)
6+ , createRedirects
7+ ) where
8+
9+import Control.Applicative ((<$>))
10+import Control.Monad (forM_)
11+import Data.Binary (Binary (..))
12+import Hakyll.Core.Compiler
13+import Hakyll.Core.Identifier
14+import Hakyll.Core.Routes
15+import Hakyll.Core.Rules
16+import Hakyll.Core.Writable (Writable (..))
17+
18+-- | This function exposes a higher-level interface compared to using the
19+-- 'Redirect' type manually.
20+--
21+-- This creates, using a database mapping broken URLs to working ones, HTML
22+-- files which will do HTML META tag redirect pages (since, as a static site, we
23+-- can't use web-server-level 301 redirects, and using JS is gross).
24+--
25+-- This is useful for sending people using old URLs to renamed versions, dealing
26+-- with common typos etc, and will increase site traffic. Such broken URLs can
27+-- be found by looking at server logs or by using Google Webmaster Tools.
28+-- Broken URLs must be valid Haskell strings, non-URL-escaped valid POSIX
29+-- filenames, and relative links, since they will be defined in a @hakyll.hs@
30+-- and during generation, written to disk with the filename corresponding to the
31+-- broken URLs. (Target URLs can be absolute or relative, but should be
32+-- URL-escaped.) So broken incoming links like <http://www.gwern.net/foo/> which
33+-- should be <http://www.gwern.net/foobar> cannot be fixed (since you cannot
34+-- create a HTML file named @"foo/"@ on disk, as that would be a directory).
35+--
36+-- An example of a valid association list would be:
37+--
38+-- > brokenLinks = [("/Black-market archive", "/Black-market%20archives")]
39+--
40+-- In which case the functionality can then be used in `main` with a line like:
41+--
42+-- > createRedirects brokenLinks
43+--
44+-- The on-disk files can then be uploaded with HTML mimetypes
45+-- (either explicitly by generating and uploading them separately, by
46+-- auto-detection of the filetype, or an upload tool defaulting to HTML
47+-- mimetype, such as calling @s3cmd@ with @--default-mime-type=text/html@) and
48+-- will redirect browsers and search engines going to the old/broken URLs.
49+--
50+-- See also <https://groups.google.com/d/msg/hakyll/sWc6zxfh-uM/fUpZPsFNDgAJ>.
51+createRedirects :: [(Identifier, String)] -> Rules ()
52+createRedirects redirects =
53+ forM_ redirects $ \(ident, to) ->
54+ create [ident] $ do
55+ route idRoute
56+ compile $ makeItem $! Redirect to
57+
58+-- | This datatype can be used directly if you want a lower-level interface to
59+-- generate redirects. For example, if you want to redirect @foo.html@ to
60+-- @bar.jpg@, you can use:
61+--
62+-- > create ["foo.html"] $ do
63+-- > route idRoute
64+-- > compile $ makeItem $ Redirect "bar.jpg"
65+data Redirect = Redirect
66+ { redirectTo :: String
67+ } deriving (Eq, Ord, Show)
68+
69+instance Binary Redirect where
70+ put (Redirect to) = put to
71+ get = Redirect <$> get
72+
73+instance Writable Redirect where
74+ write path = write path . fmap redirectToHtml
75+
76+redirectToHtml :: Redirect -> String
77+redirectToHtml (Redirect working) =
78+ "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><meta name=\"generator\" content=\"hakyll\"/>" ++
79+ "<meta http-equiv=\"refresh\" content=\"0; url=" ++ working ++
80+ "\"><link rel=\"canonical\" href=\"" ++ working ++
81+ "\"><title>Permanent Redirect</title></head><body><p>The page has moved to: <a href=\"" ++ working ++
82+ "\">this page</a></p></body></html>"