Scheme:CHICKEN:Hydeを改造する
Scheme lisp で書かれた静的サイトジェネレーターを使いたくて、CHICKEN Hydeを改造した。
目次
CHICKEN Hyde のインストールについては、Scheme:CHICKEN:Hydeを使ってみるを参照。
Hydeには、すごく基本的な機能しかついてこないので、がしがし自分で書く必要がある。
追加機能
- 目次
- 関連記事
- 記事一覧
- タグ
- タグクラウド
- タグごとの記事一覧
- "/blog/{year}/{month}/{day}/{filename}.html"のような、pretty url
- ファイル名から記事の日付を拾う
- 検索機能
- サイトマップ
- RSS
成果物
ここには一部しか載せてないので、詳しくは github.com/kobapan/scheme-chicken-hyde で。
実例は kobapan.com で運用中。
以下概略
toc ( 目次 ) の表示
layouts/blogpost.sxml
()
`((div (@ (class "article-meta"))
(h2 (@ (class "title")) ,($ 'title))
(div (@ (class "tags"))
" Tagged as: "
,(fold (lambda (t tags)
(append tags
`(,(and (pair? tags) ", ")
(span (a (@ (href ,(base-uri)"/tags/#",t)
(class "tag")) ,t)))))
'()
(or ($ 'tags) '())))
(div (@ (class "date"))
"written on " ,($ 'date)))
(div (@ (class "article-content"))
(inject ,(toc contents))))
目次の必要な記事の page-vars に(toc . #t)
((title . "これこそ実験")
(tags "作る" "自然農")
(toc . #t))
関連記事の表示
layouts/related-article.sxml
()
`(inject ,contents)
(if ($ 'tags)
`(div
(h2 "関連記事")
,(tag-posts-links (car ($ 'tags)) 3))
"")
hyde.scm
(default-page-vars `(((: bos "blog/" (+ any) ".md" eos)
(layouts "related-article.sxml" "blogpost.sxml" "default.sxml"))))
layout ファイルを書く順番は大事。右を左が包む。
タグと件数を指定した記事一覧の表示
src/index.sxml
()
`(div (@ (id "home"))
(div (img (@ (class "img__center")
(src http://kobapan.com/assets/img/top-txt.png))))
,(digest "sizen-nou/index.md" "...つづき" "sizen-nou/")
(span "「自然農」最新記事")
,(tag-posts-links '自然農 3))
タグクラウド表示と、タグごとの記事一覧を全タグ分表示
src/tags/index.sxml
((title . "#タグ"))
; タグクラウド
(let ((tag-groups (tag-groups (all-posts))))
`((div (@ (id "tagcloud"))
,(map (lambda (t)
`((a (@ (href ,(base-uri)"/tags/#",(car t))
(class ,(tag-class t)" onetag"))
"#",(car t))))
tag-groups))
; タグごとの記事一覧
(div ,(map (lambda (tag-group)
`((h2 (@ (class "tag-group") (id ,(car tag-group)))
,(car tag-group))
,(map (lambda (post)
`("「" (a (@ (href ,(cdr post))) ,(car post)) "」 "))
(cdr tag-group))))
tag-groups))))
「pretty url」「ファイル名からの date 取得」
pretty url とは?
記事のファイル名は
src/blog/2020-10-02-test.md
ブラウザで表示する際は
/blog/2020/10/02/test.html
ファイル名からの date 取得 とは?
改造前の post's page-vars はこんなの(↓)、jekyll から移行することを考えてたので、date はここに書くんでなくて、ファイル名から拾いたい。
((title . "これこそ実験")
(date . "2020-10-20")
(tags "作る" "自然農"))
改造後の post's page-vars すっきりした
((title . "これこそ実験")
(tags "作る" "自然農"))
hyde の egg本体を修正
「pretty url」「ファイル名からの date 取得」、に対応するために hydeのソースファイルをいじってコンパイル&インストールし直す。
ソースファイルをダウンロード
$ chicken-install -r hyde
$ cd hyde
ソースファイル内のhyde.scm を編集
$ $ diff -Ebt -U 0 hyde.scm.orig hyde.scm
--- hyde.scm.orig 2020-10-21 22:57:56.795903959 +0900
+++ hyde.scm 2020-10-24 22:21:50.086603256 +0900
@@ -358 +358,2 @@ END
- (let ((output-file (make-pathname (output-dir) (pathname-relative-from (source-dir) path))))
+ (let* ((output-file (make-pathname (output-dir) (pathname-relative-from (source-dir) path)))
+ (output-file (irregex-replace "(.*)/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.*)" output-file 1 "/" 2 "/" 3 "/" 4 "/" 5)))
@@ -417,0 +419,4 @@ END
+(define (default-page-vars-for-date page)
+ (let ((m (irregex-search "([0-9]{4}-[0-9]{2}-[0-9]{2})-.+\\.md$" (page-source-path page))))
+ (if m `((date . ,(irregex-match-substring m 1))) `())))
+
@@ -437 +442,2 @@ END
- (page (update-page page vars: (append local-page-vars
+ (page (update-page page vars: (append (default-page-vars-for-date page)
+ local-page-vars
@@ -446 +452,4 @@ END
- (with-output-to-file (make-output-path path page)
+ (let ((rel-path (make-output-path path page)))
+ (create-directory (string-append (current-directory) "/" (pathname-directory rel-path))
+ #t)
+ (with-output-to-file rel-path
@@ -451 +460 @@ END
- (lambda () (wrap-with-layouts (reader)))))))))))
+ (lambda () (wrap-with-layouts (reader))))))))))))
コンパイル&インストール
ソースファイルのトップディレクトリで chicken-install を引数なし実行。Installing_extensions eggs
改造する際の、はまりどころ
inject が何をするのか
$ cat layouts/default.sxml
() `((xhtml-1.0-strict) (html (head (title ,($ 'title))) (body (h1 ,($ 'title)) (inject ,contents))))inject transformation rule which allows injection of **unescaped** HTML into the document. Hyde - The CHICKEN Scheme wiki
contents の中身は traslation 後の html文字列。しかし injectルールで囲わないと、このhtml文字列内のhtmlタグは最終的に文字実体参照として表現される。injectルールで囲えばHTMLタグとして表現される。
pages の中身
src-dir 配下のディレクトリとファイルの全部が連想配列になってる。
((edible-forest-garden/index.md . #<page>)
(edible-forest-garden . #<page>)
(blog/2015-10-07-lorena-rocket.md . #<page>) ...)
オブジェクト #<page>には、($ page-var #!optional page)でアクセスできる。
参考
Hyde 公式ガイド
Hyde のソースコード
Hyde 利用例1
Hyde 利用例2
Hyde 利用例3
- kdltr/blog: Sources of the www.upyum.com website
- libbro/libbro.github.io: My personal blog created in Hyde