remove some env vars; make output land in html/

CLONE-URL, TITLE, and H1 are no longer processed. instead, the user
should modify the templates/default.html to their liking.

the output used to be structured like this:

target-html-directory/
+-- index.html
+-- files.html
+-- README.md.html
+-- (all the other files)

the output is now structured like this:

target-html-directory/
+-- index.html
+-- html/
    +-- files.html
    +-- README.md.html
    +-- (all the other files...)

this makes it so people who are hosting bare repos for cloning on static
webservers will have only two new directory entries (index.html and
html) in the bare repo directory, reducing the risk of clobbering
something.

finally, i tried something hacky with gitattributes to get an automatic
version idenifier to show up. but it turns out this is not the git hash
of the commit, but instead the hash of the blob for main.scm, which
could remain the same across releases. doesn't hurt, so i'll look for a
better approach in the future.
This commit is contained in:
pho4cexa 2022-12-18 09:59:59 -08:00
parent bd18246b08
commit 917788e29f
3 changed files with 73 additions and 46 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
main.scm ident

100
main.scm
View file

@ -21,13 +21,9 @@
utf8 utf8
) )
(define CLONE-URL (or (get-environment-variable "REPO2HTML_CLONE_URL") "git://git.example.com"))
(define TITLE (or (get-environment-variable "REPO2HTML_TITLE") "git.example.com"))
(define DESCRIPTION (or (get-environment-variable "REPO2HTML_DESCRIPTION") "my git repositories"))
(define H1 (or (get-environment-variable "REPO2HTML_H1") "git.example.com"))
;; small utilities --------------------------------- ;; small utilities ---------------------------------
;; (bail [message [exit-status]]) ;; (bail [message [exit-status]])
;; end the program immediately. ;; end the program immediately.
;; if a message is provided, print it to the screen. ;; if a message is provided, print it to the screen.
@ -166,12 +162,12 @@
(plaintext) (plaintext)
(binary)))))) (binary))))))
(define (filelist->sxml source-files-list) (define (filelist->sxml source-files-list relative-root)
`((h1 "Files") `((h1 "Files")
((ul ((ul
,(map ,(map
(lambda (source-file) (lambda (source-file)
`(li (a (@ href ,source-file ".html") ,source-file))) `(li (a (@ href ,(make-pathname relative-root source-file ".html")) ,source-file)))
source-files-list))))) source-files-list)))))
(define (commits->sxml) (define (commits->sxml)
@ -241,32 +237,51 @@
;; main program ------------------------------------------------------------------------------ ;; main program ------------------------------------------------------------------------------
(define (generate-html-files html-repo-path templates-directory) (define (generate-html-files html-repo-path templates-directory)
(let* ((source-files-list (git-repository->paths-list)) (let* ((version-ident "$Id$")
(repository-name (pathname-strip-directory (string-chomp html-repo-path "/"))) (source-files-list (git-repository->paths-list))
(template-alist `(;; variables provided to template at all times (template-alist
(source_files_list . ,source-files-list) `(;; variables provided to template at all times. beware: ersatz
(clone_url_prefix . ,CLONE-URL) ;; templates break if you attempt to use a variable with a hyphen.
(forge_title . ,TITLE)
(h1 . ,H1) ;; the list of all files in the git repo
(repository_description . ,DESCRIPTION) (source_files_list . ,source-files-list)
(repository_name . ,repository-name) ;; the description of the repo, taken from env, falling back to
(readme_file ;; description file
. ,(find (lambda (x) (member x source-files-list)) (repository_description
'("README" "README.md" "README.txt"))) . ,(or (get-environment-variable "REPO2HTML_DESCRIPTION")
(license_file (if-let (f (file-exists? "description"))
. ,(find (lambda (x) (member x source-files-list)) (with-input-from-file f read-lines)
'("LICENSE" "LICENSE.md" "LICENSE.txt"))) #f)
(issues_file ""))
. ,(and (find (lambda (x) (string-prefix? "ISSUES/" x)) source-files-list) "ISSUES")) ;; the repository name, which we detect from the output directory
)) ;; name. TODO: more heuristics if this doesn't work well
(repository_name
. ,(pathname-strip-directory (string-chomp html-repo-path "/")))
;; the first README file found, if any.
(readme_file
. ,(find (lambda (x) (member x source-files-list))
'("README" "README.md" "README.txt")))
;; the first LICENSE file found, if any.
(license_file
. ,(find (lambda (x) (member x source-files-list))
'("LICENSE" "LICENSE.md" "LICENSE.txt")))
;; the string "ISSUES" if any files exist in ISSUES/
(issues_file
. ,(and (find (lambda (x) (string-prefix? "ISSUES/" x)) source-files-list) "ISSUES"))
(repo2html_version
. ,(if (equal? version-ident (list->string '(#\$ #\I #\d #\$)))
""
(substring* version-ident 5 12)))
))
(write-with-template (write-with-template
(make-template-writer-ersatz templates-directory template-alist))) (make-template-writer-ersatz templates-directory template-alist)))
(define html-path (make-pathname html-repo-path "html"))
(create-directory html-repo-path #t) (create-directory html-repo-path #t)
;; special files ;; special files
(write-with-template (make-pathname html-repo-path "files" "html") (filelist->sxml source-files-list)) (write-with-template (make-pathname html-path "files" "html") (filelist->sxml source-files-list ""))
(write-with-template (make-pathname html-repo-path "contributors" "html") (contributors->sxml)) (write-with-template (make-pathname html-path "contributors" "html") (contributors->sxml))
(write-with-template (make-pathname html-repo-path "commits" "html") (commits->sxml)) (write-with-template (make-pathname html-path "commits" "html") (commits->sxml))
;; htmlified repo contents ;; htmlified repo contents
(for-each (for-each
(lambda (source-file) (lambda (source-file)
@ -274,7 +289,7 @@
(pathparts) (pathparts)
(define-values (root elements basename extension relative-root))) (define-values (root elements basename extension relative-root)))
(write-with-template (write-with-template
(make-pathname html-repo-path source-file "html") (make-pathname html-path source-file "html")
(source->sxml source-file) (source->sxml source-file)
`(;; additional per-page variables provided to template `(;; additional per-page variables provided to template
(source_file . ,source-file) (source_file . ,source-file)
@ -284,24 +299,29 @@
(extension . ,extension) (extension . ,extension)
(relative_root . ,relative-root) (relative_root . ,relative-root)
)) ))
;; if it's an image also copy it verbatim to output directory ;; if it's an image, also write it verbatim to output directory
(case (string->symbol (or (pathname-extension source-file) "")) (case (string->symbol (or (pathname-extension source-file) ""))
((jpg jpeg png gif webp webm svg apng avif svgz ico) ((jpg jpeg png gif webp webm svg apng avif svgz ico)
(system (format "git show HEAD:~a > ~a" (system (format "git show HEAD:~a > ~a"
source-file source-file
(make-pathname html-repo-path source-file)))))) (make-pathname html-path source-file))))))
source-files-list) source-files-list)
;; if (the output version of) README.md, README, or README.txt exists, copy ;; if README.md, README, or README.txt exists, regenerate it as index.html.
;; that to index.html. otherwise copy files.html to index.html. ;; otherwise regenerate files.html as index.html.
(->> (write-with-template
'("README.md" "README" "README.txt" "files") (make-pathname html-repo-path "index" "html")
(map (lambda (x) (make-pathname html-repo-path x "html"))) (if-let (readme-file
(find file-exists?) (alist-ref 'readme_file template-alist))
((lambda (x) (copy-file x (make-pathname html-repo-path "index" "html") #t)))) (source->sxml readme-file)
(filelist->sxml source-files-list "html"))
;; TODO: do we need the full set of template variables defined here?
;; if so maybe this and the set above should be lifted out somewhere
`((relative_root . "html/")))
;; if the ISSUES directory got created, write out an index file for the ;; if the ISSUES directory got created, write out an index file for the
;; stuff in there. ;; stuff in there.
(when (file-exists? (make-pathname html-repo-path "ISSUES")) (when (file-exists? (make-pathname html-path "ISSUES"))
(write-with-template (make-pathname html-repo-path "ISSUES" "html") (issueslist->sxml source-files-list))))) (write-with-template (make-pathname html-path "ISSUES" "html") (issueslist->sxml source-files-list)))))
(define (main #!optional html-repo-path templates-directory) (define (main #!optional html-repo-path templates-directory)

View file

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>{{ forge_title }} - {{ repository_name }}</title> <title>git.example.com - {{ repository_name }}</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale-1.0, user-scalable=yes" /> <meta name="viewport" content="width=device-width, initial-scale-1.0, user-scalable=yes" />
<link rel="icon" href="data:," /> <link rel="icon" href="data:," />
@ -18,15 +18,15 @@
</style> </style>
</head> </head>
<body> <body>
<h1>{{ h1 }}</h1> <h1>git.example.com</h1>
<h2>{{ repository_name }}</h2> <h2>{{ repository_name }}</h2>
<p>clone url:{{ clone_url_prefix }}/{{ repository_name }}</p> <p>clone url: git://git.example.com/{{ repository_name }}</p>
<nav> <nav>
{% if readme_file %} {% if readme_file %}
<a href="{{ relative_root }}index.html">about</a> <a href="{{ relative_root }}{{ readme_file }}.html">about</a>
<a href="{{ relative_root }}files.html">files</a> <a href="{{ relative_root }}files.html">files</a>
{% else %} {% else %}
<a href="{{ relative_root }}index.html">files</a> <a href="{{ relative_root }}files.html">files</a>
{% endif %} {% endif %}
{% if license_file %} {% if license_file %}
<a href="{{ relative_root }}{{ license_file }}.html">license</a> <a href="{{ relative_root }}{{ license_file }}.html">license</a>
@ -41,4 +41,10 @@
{{ content|safe }} {{ content|safe }}
<hr /> <hr />
<footer> <footer>
<p>Generated by <a href="https://git.m455.casa/repo2html/">repo2html</a> using ersatz templates</p></footer></html> <p>Generated by
<a href="https://git.m455.casa/repo2html/"
title="the repo2html git repo static renderer by m455 and pho4cexa">repo2html</a>
{{ repo2html_version }} using
<a href="http://wiki.call-cc.org/eggref/5/ersatz"
title="the ersatz Jinja2-like templating library by Ivan Raikov"
>ersatz</a> templates</p></footer></html>