kobapan@wiLiki
Login
Scheme:CHICKEN

Scheme:CHICKEN:Hydeを改造する

Scheme lisp で書かれた静的サイトジェネレーターを使いたくて、CHICKEN Hydeを改造した。

目次

CHICKEN Hyde のインストールについては、Scheme:CHICKEN:Hydeを使ってみるを参照。

Hydeには、すごく基本的な機能しかついてこないので、がしがし自分で書く必要がある。

追加機能

  1. 目次
  2. 関連記事
  3. 記事一覧
  4. タグ
    1. タグクラウド
    2. タグごとの記事一覧
  5. "/blog/{year}/{month}/{day}/{filename}.html"のような、pretty url
  6. ファイル名から記事の日付を拾う
  7. 検索機能
  8. サイトマップ
  9. 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

markdown

Debian
Emacs
Firefox
Gauche
JavaScript
Linux
Scheme
org-mode/latex

More ...