Add support for rendering furigana

main
Oystein Kristoffer Tveit 2022-03-19 00:59:36 +01:00
parent 9854cfd60f
commit 1030977dfd
11 changed files with 189 additions and 59 deletions

View File

@ -36,7 +36,7 @@
packages = p: [ p.ssg ];
buildInputs = with pkgs.myHaskellPackages; [
ssg
# ssg
# Helpful tools for `nix develop` shells
ghcid # https://github.com/ndmitchell/ghcid

View File

@ -1,13 +1,13 @@
---
desc: "This is me saying hello to the world"
desc: "Nani.wtf homepage"
image: "./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg"
lang: "en"
stylesheet: "default"
title: "Hello, world!"
title: "Nani"
---
<header class="header">
<h1>Hello, world!</h1>
<h1>Welcome to nani.wtf</h1>
<img
alt="A woman sitting on a bench amongst trees at the end of a boardwalk leading to a pond with mountains in the background"
src="./images/robert-pearce-UwHN0jU_YqQ-unsplash-800w.jpg"
@ -16,14 +16,27 @@ title: "Hello, world!"
</header>
<main>
<section class="content">
<h2>Blog Posts</h2>
<ul>
$for(posts)$
<li>
<div><a href=".$url$">$title$</a></div>
<small>$date$</small>
</li>
$endfor$
</ul>
<div class="pure-g">
<div class="pure-u-1-2 pure-u-md-1-2">
<h2>Posts</h2>
<ul>
$for(posts)$
<li>
<div><a href=".$url$">$title$</a></div>
<small>$date$</small>
</li>
$endfor$
</ul>
</div>
<div class="pure-u-1-2 pure-u-md-1-2">
<h2>成り立ち</h2>
<ul>
$for(naritachi)$
<li>
<div><a href=".$url$">$title$</a></div>
</li>
$endfor$
</ul>
</div>
</section>
</main>

9
src/naritachi/suru.md Normal file
View File

@ -0,0 +1,9 @@
---
desc: "I announce myself to the world"
keywords: "japanese, naritachi, grammar"
lang: "en"
updated: "2020-09-22T12:00:00Z"
title: "[為](す)る"
---
suru

View File

@ -6,42 +6,48 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="$desc$">
$if(author)$
<meta name="author" content="$author$">
<meta name="author" content="$author$">
$endif$
$if(keywords)$
<meta name="keywords" content="$keywords$">
<meta name="keywords" content="$keywords$">
$endif$
<meta property="og:site_name" content="$siteName$">
<meta property="og:title" content="$title$">
<meta property="og:url" content="$root$$url$">
<meta property="og:description" content="$desc$">
$if(image)$
<meta property="og:image" content="$root$$image$">
<meta property="og:image" content="$root$$image$">
$endif$
$if(type)$
<meta property="og:type" content="$type$">
<meta property="og:type" content="$type$">
$else$
<meta property="og:type" content="website">
<meta property="og:type" content="website">
$endif$
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:site" content="$siteName$">
<meta property="twitter:title" content="$title$">
<meta property="twitter:description" content="$desc$">
$if(image)$
<meta property="twitter:image" content="$root$$image$">
$endif$
$if(authorTwitter)$
<meta property="twitter:creator" content="$authorTwitter$">
<meta property="twitter:image" content="$root$$image$">
$endif$
<link rel="shortcut icon" href="/favicon.ico">
<!-- $if(authorTwitter)$ -->
<!-- <meta property="twitter:creator" content="$authorTwitter$"> -->
<!-- $endif$ -->
<link rel="shortcut icon" href="$root$favicon.ico">
<link rel="canonical" href="$root$$url$">
<link rel="stylesheet" href="./css/default.css" />
<link rel="stylesheet" href="./css/styles.css" />
<link rel="stylesheet" href="./css/code.css" />
<link rel="stylesheet" href="$root$css/default.css" />
<link rel="stylesheet" href="$root$css/styles.css" />
<link rel="stylesheet" href="$root$css/code.css" />
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.6/build/pure-min.css" integrity="sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5" crossorigin="anonymous">
</head>
<body>
@ -56,14 +62,16 @@
<a class="pure-menu-heading" href="$root$">$siteName$</a>
<ul class="pure-menu-list">
<li class="pure-menu-item"><a href="#home" class="pure-menu-link">Home</a></li>
<li class="pure-menu-item"><a href="#about" class="pure-menu-link">About</a></li>
<li class="pure-menu-item menu-item-divided pure-menu-selected">
<a href="#" class="pure-menu-link">Services</a>
</li>
<li class="pure-menu-item"><a href="$root$" class="pure-menu-link">Posts</a></li>
<li class="pure-menu-item"><a href="$root$" class="pure-menu-link">成り立ち</a></li>
<!-- <li class="pure-menu-item menu-item-divided pure-menu-selected"> -->
<!-- <a href="#" class="pure-menu-link">Services</a> -->
<!-- </li> -->
<li class="pure-menu-item"><a href="#contact" class="pure-menu-link">Contact</a></li>
<li class="pure-menu-item menu-item-divided"><a href="https://git.nani.wtf" class="pure-menu-link">Git</a></li>
<li class="pure-menu-item"><a href="https://git.nani.wtf/h7x4/nani.wtf" class="pure-menu-link">Site source</a></li>
</ul>
</div>
</div>
@ -81,7 +89,9 @@
<!-- </p> -->
</div>
</div>
$body$
$body$
<script async src="./js/script.js"></script>
<script src="./js/ui.js"></script>
</body>

View File

@ -0,0 +1,20 @@
<main>
<article>
<header class="header">
<h1>$titleHtml$</h1>
<div>
$if(updated)$
<small>(updated: $updated$)</small>
$endif$
</div>
$if(alternative_writings)$
<div>
$alternative_writings$
</div>
$endif$
</header>
<section class="content">
$body$
</section>
</article>
</main>

View File

@ -1,17 +1,15 @@
<main>
<article>
<header>
<h1>
<a href=".$url$">$title$</a>
</h1>
<header class="header">
<h1>$title$</h1>
<div>
<small>$date$</small>
$if(updated)$
<small>(updated: $updated$)</small>
<small>(updated: $updated$)</small>
$endif$
</div>
</header>
<section>
<section class="content">
$body$
</section>
</article>

View File

@ -0,0 +1,51 @@
{-# LANGUAGE QuasiQuotes, FlexibleContexts #-}
module Formats.Naritachi (
convertFuriganaTitle,
convertFuriganaTitleHtml
) where
import Hakyll (Item, Metadata, Compiler, itemIdentifier, getMetadata, lookupString)
import Debug.Trace (traceId)
import Data.Maybe (fromMaybe)
import Text.Regex.PCRE.Heavy
--------------------------------------------------------------------------------
-- FURIGANA CONVERSION
type FuriganaTemplate = String
convertTitle = updateFieldWith "title" "???"
convertFuriganaTitle :: Item a -> Compiler String
convertFuriganaTitle = convertTitle replaceFuriganaWithKanji
convertFuriganaTitleHtml :: Item a -> Compiler String
convertFuriganaTitleHtml = convertTitle replaceFuriganaWithHtml
updateFieldWith :: String -> String -> (String -> String) -> Item a -> Compiler String
updateFieldWith field defaultPreviousValue f =
fmap updateField . getMetadata . itemIdentifier
where
updateField :: Metadata -> String
updateField = traceId . f . fromMaybe defaultPreviousValue . lookupString field
replaceFuriganaWithKanji :: FuriganaTemplate -> String
replaceFuriganaWithKanji = gsub [re|\[(.*?)\]\((.*?)\)|] (\(kanji:kana:_) -> kanji :: String)
replaceFuriganaWithHtml :: FuriganaTemplate -> String
replaceFuriganaWithHtml = between "<ruby>" "</ruby>" . gsub [re|\[(.*?)\]\((.*?)\)|] (\(kanji:kana:_) -> "<rb>" ++ kanji ++"</rb> <rp>(</rp><rt> " ++ kana ++ "</rt><rp>)</rp>" :: String)
where
between x y s = x ++ s ++ y
-- toHtml :: FuriganaTemplate -> String
-- toHtml input =
-- "<ruby>"
-- <> subRegex (mkRegex "[(.*?)]\\((.*?)\\)") input "<rb>\1</rb> <rp>(</rp><rt>\2</rt><rp>)</rp>"
-- <> "</ruby>"
-- <!-- <ruby> -->
-- <!-- <rb>す</rb> <rp>(</rp><rt>為</rt><rp>)</rp> -->
-- <!-- <rb>る</rb> -->
-- <!-- </ruby> -->
-- <!-- " -->

1
ssg/src/Formats/Posts.hs Normal file
View File

@ -0,0 +1 @@
module Formats.Posts where

View File

@ -3,7 +3,6 @@
import Control.Monad (forM_)
import Data.Maybe (fromMaybe)
import Hakyll
import Debug.Trace (trace)
import qualified Data.Text as T
import qualified Data.Text.Slugger as Slugger
import Text.Pandoc
@ -18,6 +17,11 @@ import Text.Pandoc
)
import Text.Pandoc.Highlighting (Style, breezeDark, styleToCss)
-- ---------
import Formats.Naritachi
import Util.Routes
--------------------------------------------------------------------------------
-- CONFIG
@ -76,13 +80,31 @@ main = hakyllWith config $ do
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" ctx
match "naritachi/*" $ do
let ctx =
constField "type" "article"
<> field "title" convertFuriganaTitle
<> field "titleHtml" convertFuriganaTitleHtml
<> postCtx
route $ setExtension ".html"
compile $ do
pandocCompilerCustom
>>= loadAndApplyTemplate "templates/naritachi.html" ctx
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" ctx
match "index.html" $ do
route idRoute
compile $ do
-- posts :: Compiler
posts <- recentFirst =<< loadAll "posts/*"
naritachi <- loadAll "naritachi/*"
let indexCtx =
listField "posts" postCtx (return posts)
listField "posts" postCtx (return posts)
<> listField "naritachi" postCtx (return naritachi)
<> constField "root" root
<> constField "siteName" siteName
<> defaultContext
@ -225,21 +247,3 @@ feedConfiguration =
, feedAuthorEmail = "h7x4@protonmail.com"
, feedRoot = root
}
--------------------------------------------------------------------------------
-- CUSTOM ROUTE
getTitleFromMeta :: Metadata -> String
getTitleFromMeta =
fromMaybe "no title" . lookupString "title"
fileNameFromTitle :: Metadata -> FilePath
fileNameFromTitle =
T.unpack . (`T.append` ".html") . Slugger.toSlug . T.pack . getTitleFromMeta
titleRoute :: Metadata -> Routes
titleRoute =
constRoute . fileNameFromTitle
prefixRoute :: FilePath -> Routes
prefixRoute p = customRoute $ \id -> p ++ (toFilePath id)

23
ssg/src/Util/Routes.hs Normal file
View File

@ -0,0 +1,23 @@
{-# LANGUAGE OverloadedStrings #-}
module Util.Routes where
import Hakyll
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import qualified Data.Text.Slugger as Slugger
prefixRoute :: FilePath -> Routes
prefixRoute p = customRoute $ \id' -> p ++ (toFilePath id')
titleRoute :: Metadata -> Routes
titleRoute = constRoute . fileNameFromTitle
where
getTitleFromMeta :: Metadata -> String
getTitleFromMeta =
fromMaybe "no title" . lookupString "title"
fileNameFromTitle :: Metadata -> FilePath
fileNameFromTitle =
T.unpack . (`T.append` ".html") . Slugger.toSlug . T.pack . getTitleFromMeta

View File

@ -14,5 +14,6 @@ executable hakyll-site
, pandoc == 2.14.*
, slugger >= 0.1.0.1
, text >= 1.2
, pcre-heavy >= 1.0.0.2
ghc-options: -Wall -threaded
default-language: Haskell2010