1
2
Fork
You've already forked gemoire
0
yet another static gemlog generator + converter https://hackage.haskell.org/package/gemoire
  • Haskell 93.3%
  • Nix 4%
  • HTML 1.7%
  • Just 1%
Sena 5dc77eedf0
All checks were successful
ci/woodpecker/push/test/3 Pipeline was successful
ci/woodpecker/push/test/1 Pipeline was successful
ci/woodpecker/push/test/2 Pipeline was successful
docs(Gemoire.Converter): fix regex hyperlink
2025年02月02日 13:02:54 +03:00
.woodpecker ci: update ghcs 2025年01月19日 18:30:51 +03:00
example fix(Gemoire.Converter): escape stuff 2025年02月01日 23:07:29 +03:00
src docs(Gemoire.Converter): fix regex hyperlink 2025年02月02日 13:02:54 +03:00
test test: test for feed escaping 2025年02月02日 00:38:31 +03:00
.editorconfig feat(Gemoire.Gemlog.Post): init 2024年08月18日 02:53:26 +03:00
.envrc init 2024年08月03日 02:32:18 +03:00
.gitattributes feat(Gemoire.Gemlog.Post): init 2024年08月18日 02:53:26 +03:00
.gitignore docs(Gemoire.Template): document properly 2025年01月24日 17:21:11 +03:00
cabal.project init 2024年08月03日 02:32:18 +03:00
ChangeLog.md fix(Gemoire.Converter): make recursive generations work 2025年02月02日 01:04:01 +03:00
flake.lock ci: update ghcs 2025年01月19日 18:30:51 +03:00
flake.nix docs(Gemoire.Converter*): add documentation 2025年02月01日 17:33:55 +03:00
fourmolu.yaml init 2024年08月03日 02:32:18 +03:00
gemoire.cabal fix(Gemoire.Converter): make recursive generations work 2025年02月02日 01:04:01 +03:00
justfile docs(example): update 2025年01月25日 18:59:08 +03:00
LICENSE chore!: clean up 2024年08月07日 01:41:51 +03:00
README.md docs: update readme.md 2025年02月01日 17:59:11 +03:00
Setup.lhs chore!: clean up 2024年08月07日 01:41:51 +03:00
stack.yaml ci: update ghcs 2025年01月19日 18:30:51 +03:00
stack.yaml.lock ci: update ghcs 2025年01月19日 18:30:51 +03:00
treefmt.toml chore!: clean up 2024年08月07日 01:41:51 +03:00

gemoire - yet another static gemlog generator + converter

gemoire is just a basic flexible gemini blog generator, that can:

  • be configured using Haskell code,
  • use custom templates written in an authentic syntax,
  • set additional and overriding variables for formatting,
  • generate Atom and Gemini feeds.
  • and convert capsules to various formats, such as HTML and Markdown by default.

See the example directory in the repository to see how it looks like in "production".

Getting Started

Intended way for using gemoire is through Cabal scripts. To get started, you should organize your gemlog sources like so:

gemlog
├── content
│ ├── post1.gmi
│ └── post2.gmi
└── gemlog.hs

The contents directory can be as deep as you want, all posts will end up in a flat directory in the end. After setting up your files, you can start configuring your gemlog.hs, here is a simple template for you using the defaults:

#!/usr/bin/env cabal
{- cabal:
build-depends: base
 , gemoire
-}
{-# LANGUAGE OverloadedStrings #-}
import Gemoire
main :: IO ()
main = do
 let gemlog =
 Gemlog
 { title = "my gemlog"
 , author = "me"
 , sourceDir = "content"
 , baseURL = "gemini://my.website.com/path/to/gemlog"
 , postTemplate = defPost
 , gemfeedTemplates =
 ( defGemfeed
 , defGemfeedEntry
 )
 , atomTemplates =
 ( defAtom
 , defAtomEntry
 )
 , overrides = vempty
 }
 generatePosts gemlog "~/public_gemini/path/to/gemlog"
 generateGemfeed gemlog "~/public_gemini/path/to/gemlog/index.gmi"
 generateAtom gemlog "~/public_gemini/path/to/gemlog/atom.xml"

After setting up your configuration, you can just cd into the gemlog directory and run the generator:

$ cabal run gemlog.hs

If Cabal is causing problems, you can just install the library and use runghc instead, like so:

$ cabal install --lib gemoire
$ runghc gemlog.hs

Customizing

You can then customize your gemlog to your liking. To do that, you might want to start with changing the templates, like so:

#!/usr/bin/env cabal
{- cabal:
build-depends: base
 , text
 , gemoire
-}
{-# LANGUAGE OverloadedStrings #-}
-- gemoire uses Data.Text under the hood.
import Data.Text (unlines)
import Prelude hiding (unlines)
import Gemoire
-- The line endings will be taken care of by gemoire.
-- ...
 , postTemplate = template . unlines $
 [ "By {$author$}."
 , ""
 , "{$post$}"
 ]
-- ...

There are various variables and different useful compounds you can use in the templates. A detailed list can be found in the documentation of Gemoire.Template. Also check the default templates in the source for some inspiration!

Different special variables are available to the formatters for feeds and posts. You can see a list of those and how you can set overrides per post in the page for Gemoire.Gemlog.

Additionally, you can set overriding variables globally using the overrides variable, like so:

-- ...
 , overrides = vlist
 [ ("variable", "new value")
 , ("another", "overridden")
 ]
-- ...

Converting

After generating a Gemini capsule, you might want to convert your art into different formats, e.g. to publish on the web as well. To do so, you can use something like the following:

#!/usr/bin/env cabal
{- cabal:
build-depends: base
 , gemoire
-}
import Gemoire
main :: IO ()
main = do
 let web = defWebConversion
 convertCapsule web "~/public_gemini" "~/public_html"

You can also somewhat customize this behaviour, like so:

#!/usr/bin/env cabal
{- cabal:
build-depends: base
 , gemoire
-}
{-# LANGUAGE OverloadedStrings #-}
import Gemoire
main :: IO ()
main = do
 let web = defWebConversion
 { textTemplate = template "<p class=\"something\">{$text$}</p>"
 , rewriteRules =
 [ -- Rewrite .gmi links in the domain example.com as .html.
 ( ".*\\.gmi" -- input files in which the rewriting will occur
 , "((https*)|(gemini))://example.com/(.*)\\.gmi" -- the RegEx to match
 , "https://example.com/\\4.html" -- the replacement text
 , True -- multiline
 , True -- case senstive
 )
 ]
 , conversionOverrides = vlist [("title", "every title is this now")]
 }
 convertCapsule web "~/public_gemini" "~/public_html"

You can also define your own conversion rules using the Conversion struct. See the documentation of Gemoire.Converter for more on what else you can do and the template variables.

See also