From 303a12092413c157272d78657d7c4d4c3f6b27b0 Mon Sep 17 00:00:00 2001
From: Ricardo Wurmus <rekado@elephly.net>
Date: Tue, 13 Apr 2021 23:30:55 +0200
Subject: software: Generate project list with member details.

* software.md: Replace this file...
* software.sxml: ...with this new file.
* haunt.scm (read-markdown-page): Rename this procedure...
(read-page): ...to this procedure and add optional READER argument.
(static-pages): Add local definition of SXML-PAGE and use it for software.sxml.
---
 haunt.scm           |  18 +++--
 software.md         |  40 ----------
 software.sxml       | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 static/css/main.css |  38 +++++++++
 4 files changed, 276 insertions(+), 46 deletions(-)
 delete mode 100644 software.md
 create mode 100644 software.sxml

diff --git a/haunt.scm b/haunt.scm
index d3b5a73..27594b3 100644
--- a/haunt.scm
+++ b/haunt.scm
@@ -127,10 +127,10 @@
 (define read-markdown
   (reader-proc commonmark-reader))
 
-(define (read-markdown-page file posts site)
+(define* (read-page file posts site #:optional (reader read-markdown))
   "Read the CommonMark page from FILE.  Return its final SXML
 representation."
-  (let ((meta body (read-markdown (string-append %cwd "/" file))))
+  (let ((meta body (reader (string-append %cwd "/" file))))
     (base-layout `(div (@ (class "post"))
                        (div (@ (class "post-body"))
                             ,body))
@@ -144,13 +144,19 @@ representation."
   "Return the list of static web pages."
   (define (markdown-page html md)
     (lambda (site posts)
-      (make-page html (read-markdown-page md posts site)
+      (make-page html (read-page md posts site)
+                 sxml->html)))
+  (define (sxml-page html sxml)
+    (lambda (site posts)
+      (make-page html (read-page sxml posts site (reader-proc sxml-reader))
                  sxml->html)))
 
   (list (markdown-page "index.html" "index.md")
 
-        (markdown-page "/en/software/index.html"
-                       "software.md")
+        (sxml-page "/en/software/index.html"
+                   "software.sxml")
+        (markdown-page "/en/documents/index.html"
+                       "documents.md")
         (markdown-page "/en/contribute/index.html"
                        "contribute.md")
         (markdown-page "/en/documents/index.html"
@@ -240,7 +246,7 @@ representation."
       #:default-metadata
       '((author . "The GNU Assembly")
         (email  . "assembly@lists.gnu.tools"))
-      #:readers (list commonmark-reader)
+      #:readers (list commonmark-reader sxml-reader)
       #:builders (append (list (static-directory "static"))
                          (static-pages)
 
diff --git a/software.md b/software.md
deleted file mode 100644
index b53416b..0000000
--- a/software.md
+++ /dev/null
@@ -1,40 +0,0 @@
-title: Software
-author: The GNU Assembly
-menu: software
----
-
-# Software
-
-Maintainers of the following projects participate in the GNU Assembly:
-
-- GCC
-- GNU 8sync
-- GNU Archimedes
-- GNU Classpath
-- GNU Dominion
-- GNU Gneural Network
-- GNU Guile
-- GNU Guile-Debbugs
-- GNU Guile-RPC
-- GNU Guix
-- GNU Guix Workflow Language
-- GNU Hurd
-- GNU Indent
-- GNU Libgcrypt
-- GNU Libtasn1
-- GNU LilyPond
-- GNU MCSim
-- GNU MediaGoblin
-- GNU Mes
-- GNU Nano-Archimedes
-- GNU Scientific Library
-- GNU Shepherd
-- GNU Source Highlight
-- GNU adns
-- GNU libc
-- GNU userv
-- GnuCOBOL
-- GnuPG
-- Guile-GNOME
-- Guile-OpenGL
-- Liquid War 6
diff --git a/software.sxml b/software.sxml
new file mode 100644
index 0000000..8ef1002
--- /dev/null
+++ b/software.sxml
@@ -0,0 +1,226 @@
+(use-modules (ice-9 match)
+             (srfi srfi-9)
+             (srfi srfi-69)
+             (haunt utils))
+
+(define-record-type <project>
+  (project id name url members)
+  project?
+  (id      project-id)
+  (name    project-name)
+  (url     project-url)
+  (members project-members set-project-members!))
+
+(define-record-type <person>
+  (make-person name url avatar)
+  person?
+  (name    person-name)
+  (url     person-url)
+  (avatar  person-avatar))
+
+(define* (person name #:optional url avatar)
+  (make-person name url avatar))
+
+(define %projects
+  (let ((table (make-hash-table)))
+    (for-each
+     (match-lambda
+       ((id name url)
+        (hash-table-set! table id (project id name url (list)))))
+     '((8sync
+        "8sync"
+        "https://www.gnu.org/software/8sync/")
+       (adns
+        "GNU adns"
+        "https://www.gnu.org/software/adns/")
+       (archimedes
+        "GNU Archimedes"
+        "https://www.gnu.org/software/archimedes/")
+       (binutils
+        "binutils"
+        "https://www.gnu.org/software/binutils/")
+       (classpath
+        "GNU Classpath"
+        "https://www.gnu.org/software/classpath/")
+       (dominion
+        "GNU Dominion"
+        "https://savannah.gnu.org/projects/dominion")
+       (gcc
+        "GNU Compiler Collection (GCC)"
+        "https://gcc.gnu.org")
+       (gdb
+        "GDB" "https://www.gnu.org/software/gdb/")
+       (glibc
+        "GNU C Library"
+        "https://www.gnu.org/software/libc/")
+       (gneural
+        "GNU Gneural Network"
+        "https://www.gnu.org/software/gneuralnetwork/")
+       (gnucobol
+        "GnuCOBOL"
+        "https://gnucobol.sourceforge.io/")
+       (gnupg
+        "GnuPG"
+        "https://gnupg.org")
+       (gsl
+        "GNU Scientific Library"
+        "https://www.gnu.org/software/gsl/")
+       (guile
+        "GNU Guile"
+        "https://www.gnu.org/software/guile/")
+       (guile-debbugs
+        "Guile-Debbugs"
+        "https://savannah.gnu.org/projects/guile-debbugs/")
+       (guile-gnome
+        "Guile-GNOME"
+        "https://www.gnu.org/software/guile-gnome/")
+       (guile-opengl
+        "Guile-OpenGL"
+        "https://www.gnu.org/software/guile-opengl/")
+       (guile-rpc
+        "GNU Guile-RPC"
+        "https://www.gnu.org/software/guile-rpc/")
+       (guix
+        "GNU Guix"
+        "https://guix.gnu.org")
+       (gwl
+        "Guix Workflow Language"
+        "https://guixwl.org")
+       (hurd
+        "GNU Hurd"
+        "https://hurd.gnu.org")
+       (indent
+        "GNU indent"
+        "https://www.gnu.org/software/indent/")
+       (libgcrypt
+        "GNU Libgcrypt"
+        "https://gnupg.org/related_software/libgcrypt/")
+       (libtasn1
+        "GNU Libtasn1"
+        "https://www.gnu.org/software/libtasn1/")
+       (lilypond
+        "GNU LilyPond"
+        "https://lilypond.org/")
+       (liquid-war-6
+        "Liquid War 6"
+        "https://www.gnu.org/software/liquidwar6/")
+       (mcsim
+        "GNU MCSim"
+        "https://www.gnu.org/software/mcsim/")
+       (mediagoblin
+        "GNU MediaGoblin"
+        "https://mediagoblin.org/")
+       (mes
+        "GNU Mes"
+        "https://www.gnu.org/software/mes/")
+       (mpc
+        "GNU MPC"
+        "http://www.multiprecision.org/mpc/")
+       (nano-archimedes
+        "GNU Nano-Archimedes"
+        "https://www.gnu.org/software/archimedes/")
+       (shepherd
+        "GNU Shepherd"
+        "https://www.gnu.org/software/shepherd/")
+       (source-highlight
+        "GNU Source Highlight"
+        "https://www.gnu.org/software/src-highlite/")
+       (userv
+        "GNU userv"
+        "https://www.gnu.org/software/userv/")))
+    table))
+
+(define-syntax-rule (define-member person projects ...)
+  (for-each (lambda (project-id)
+              (let ((project
+                     (hash-table-ref %projects project-id
+                                     (lambda ()
+                                       (error (format #false
+                                                      "Unknown project ~a for ~a~%"
+                                                      project-id name))))))
+                (set-project-members!
+                 project (cons person (project-members project)))))
+            (quote (projects ...))))
+
+(define-member (person "Carlos O'Donell")
+  glibc gdb gcc binutils)
+(define-member (person "Mark J. Wielaard"
+                       "https://gnu.wildebeest.org/blog/mjw/")
+  classpath gcc glibc gdb)
+(define-member (person "Andy Wingo"
+                       "https://wingolog.org")
+  guile guile-gnome guile-opengl)
+(define-member (person "Ludovic Courtès"
+                       "https://people.bordeaux.inria.fr/lcourtes/")
+  guix guile shepherd guile-rpc)
+(define-member (person "Frederic Y. Bois")
+  mcsim)
+(define-member (person "Andrej Shadura")
+  indent)
+(define-member (person "Werner Koch")
+  gnupg libgcrypt)
+(define-member (person "Mark Galassi")
+  gsl dominion)
+(define-member (person "Jean Michel Sellier")
+  archimedes nano-archimedes gneural)
+(define-member (person "Christopher Webber"
+                       "https://dustycloud.org")
+  8sync mediagoblin)
+(define-member (person "Ian Jackson")
+  adns userv)
+(define-member (person "Samuel Thibault")
+  hurd)
+(define-member (person "Jan Nieuwenhuizen")
+  mes lilypond)
+(define-member (person "Christian Mauduit")
+  liquid-war-6)
+(define-member (person "Nikos Mavrogiannopoulos")
+  libtasn1)
+(define-member (person "Andreas Enge")
+  mpc)
+(define-member (person "Han-Wen Nienhuys")
+  lilypond)
+(define-member (person "Tobias Geerinckx-Rice")
+  guix)
+(define-member (person "Bernard Giroud")
+  gnucobol)
+(define-member (person "Tom Tromey")
+  source-highlight)
+(define-member (person "Jeff Law")
+  gcc)
+(define-member (person "David Malcolm")
+  gcc)
+(define-member (person "Ricardo Wurmus"
+                       "https://elephly.net")
+  guix gwl guile-debbugs)
+
+
+`((title . "Software")
+  (author . "The GNU Assembly")
+  (date . ,(string->date* "2021-04-13 23:00"))
+  (menu . "software")
+  (content
+   ((h2 "Software")
+    (p "Maintainers of the following projects participate in the GNU Assembly:")
+    (ul (@ (class "projects"))
+     ,@(hash-table-fold %projects
+                        (lambda (key project acc)
+                          (cons `(li (span
+                                      (a (@ (class "project-url")
+                                            (href ,(project-url project)))
+                                         ,(project-name project))
+                                      ,(let ((members (project-members project)))
+                                         `(details
+                                           (summary ,(format #false "members (~a)"
+                                                             (length members)))
+                                           (ul (@ (class "members"))
+                                               ,(map (lambda (person)
+                                                       `(li (@ (class "person"))
+                                                            ,(let ((home-page (person-url person)))
+                                                               (if home-page
+                                                                   `(a (@ (href ,home-page))
+                                                                       ,(person-name person))
+                                                                   (person-name person)))))
+                                                     members))))))
+                                acc))
+                        '())))))
diff --git a/static/css/main.css b/static/css/main.css
index 73c2c7f..a1eddf6 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -353,5 +353,43 @@ article ul li::before {
     font-weight: bold;
 }
 
+article ul.projects {
+    position: relative;
+}
+article ul.projects details ul.members li {
+    display: inline-block;
+    list-style-type: none;
+}
+li.person::before {
+    content: '';
+}
+
+details summary {
+    cursor: pointer;
+    color: #4D4D4D;
+    font-size: smaller;
+}
+
+details summary > * {
+    display: inline;
+}
+
+details[open] summary ~ * {
+    animation: sweep .5s ease-in-out;
+}
+@keyframes sweep {
+    0%    {opacity: 0; margin-top: -10px}
+    100%  {opacity: 1; margin-top: 0px}
+}
+
+details ul.members {
+    padding: 0;
+    margin-top: 0;
+    display: inline-block;
+}
+ul.members li.person + li.person {
+    margin-left: 1em;
+}
+
 #footer-box a { color: #333333; }
 #footer-box a:visited { color: #333333; }
-- 
cgit v1.2.1