summary refs log tree commit diff
path: root/doc
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2022-01-18 22:20:12 +0100
committerLudovic Courtès <ludo@gnu.org>2022-01-18 22:51:08 +0100
commit7eb883b7c284c78cc17093bfc4ef2d70e0acad83 (patch)
treed6cb9d8b7879da6af715b03e5185584965e795d9 /doc
parentee16e4e8dac9fd14340cd96731e867134cd843fe (diff)
downloadguix-7eb883b7c284c78cc17093bfc4ef2d70e0acad83.tar.gz
doc: Add a language menu in the HTML manual.
* doc/build.scm (stylized-html): New procedure.
(html-manual): Use it.
Diffstat (limited to 'doc')
-rw-r--r--doc/build.scm156
1 files changed, 153 insertions, 3 deletions
diff --git a/doc/build.scm b/doc/build.scm
index 1057336c65..44c185e5f9 100644
--- a/doc/build.scm
+++ b/doc/build.scm
@@ -600,6 +600,154 @@ its <pre class=\"lisp\"> blocks (as produced by 'makeinfo --html')."
 
   (computed-file name build))
 
+(define* (stylized-html source input
+                        #:key
+                        (languages %languages)
+                        (manual %manual)
+                        (manual-css-url "/static/base/css/manual.css"))
+  "Process all the HTML files in INPUT; add them MANUAL-CSS-URL as a <style>
+link, and add a menu to choose among LANGUAGES.  Use the Guix PO files found
+in SOURCE."
+  (define build
+    (with-extensions (list guile-lib)
+      (with-imported-modules `((guix build utils)
+                               ((localization)
+                                => ,(localization-helper-module
+                                     source languages)))
+        #~(begin
+            (use-modules (htmlprag)
+                         (localization)
+                         (guix build utils)
+                         (srfi srfi-1)
+                         (ice-9 match)
+                         (ice-9 threads))
+
+            (define* (menu-dropdown #:key (label "Item") (url "#") (items '()))
+              ;; Return an SHTML <li> element representing a dropdown for the
+              ;; navbar.  LABEL is the text of the dropdown menu, and ITEMS is
+              ;; the list of items in this menu.
+              (define id "visible-dropdown")
+
+              `(li
+                (@ (class "navbar-menu-item dropdown dropdown-btn"))
+                (input (@ (class "navbar-menu-hidden-input")
+                          (type "radio")
+                          (name "dropdown")
+                          (id ,id)))
+                (label (@ (for ,id)) ,label)
+                (label (@ (for "all-dropdowns-hidden")) ,label)
+                (div
+                 (@ (class "navbar-submenu")
+                    (id "navbar-submenu"))
+                 (div (@ (class "navbar-submenu-triangle"))
+                      " ")
+                 (ul ,@items))))
+
+            (define (menu-item label url)
+              ;; Return an SHTML <li> element for a menu item with the given
+              ;; LABEL and URL.
+              `(li (a (@ (class "navbar-menu-item")
+	                 (href ,url))
+                      ,label)))
+
+            (define* (base-language-url code manual
+                                        #:key split-node?)
+              ;; Return the base URL of MANUAL for language CODE.
+              (if split-node?
+                  (string-append "../../" code "/html_node")
+                  (string-append "../" code "/" manual
+                                 (if (string=? code "en")
+                                     ""
+                                     (string-append "." code))
+                                 ".html")))
+
+            (define (language-menu-items file)
+              ;; Return the language menu items to be inserted in FILE.
+              (define split-node?
+                (string-contains file "/html_node/"))
+
+              (append
+                  (map (lambda (code)
+                         (menu-item (language-code->native-name code)
+                                    (base-language-url code #$manual
+                                                       #:split-node?
+                                                       split-node?)))
+                       '#$%languages)
+                  (list
+                   (menu-item "⊕"
+                              (if (string=? #$manual "guix-cookbook")
+                                  "https://translate.fedoraproject.org/projects/guix/documentation-cookbook/"
+                                  "https://translate.fedoraproject.org/projects/guix/documentation-manual/")))))
+
+            (define (stylized-html sxml file)
+              ;; Return SXML, which was read from FILE, with additional
+              ;; styling.
+              (let loop ((sxml sxml))
+                (match sxml
+                  (('*TOP* decl body ...)
+                   `(*TOP* ,decl ,@(map loop body)))
+                  (('head elements ...)
+                   ;; Add reference to our own manual CSS, which provides
+                   ;; support for the language menu.
+                   `(head ,@elements
+                          (link (@ (rel "stylesheet")
+                                   (type "text/css")
+                                   (href #$manual-css-url)))))
+                  (('body ('@ attributes ...) elements ...)
+                   `(body (@ ,@attributes)
+                          (nav (@ (class "navbar-menu"))
+                               (ul
+                                ;; TODO: Add "Contribute" menu, to report
+                                ;; errors, etc.
+                                ,(menu-dropdown #:label
+                                                `(img (@ (alt "Language")
+                                                         (src "/static/base/img/language-picker.svg")))
+                                                #:items
+                                                (language-menu-items file))))
+                          ,@elements))
+                  ((tag ('@ attributes ...) body ...)
+                   `(,tag (@ ,@attributes) ,@(map loop body)))
+                  ((tag body ...)
+                   `(,tag ,@(map loop body)))
+                  ((? string? str)
+                   str))))
+
+            (define (process-html file)
+              ;; Parse FILE and add links to translations.  Install the result
+              ;; to #$output.
+              (format (current-error-port) "processing ~a...~%" file)
+              (let* ((shtml        (parameterize ((%strict-tokenizer? #t))
+                                     (call-with-input-file file html->shtml)))
+                     (processed    (stylized-html shtml file))
+                     (base         (string-drop file (string-length #$input)))
+                     (target       (string-append #$output base)))
+                (mkdir-p (dirname target))
+                (call-with-output-file target
+                  (lambda (port)
+                    (write-shtml-as-html processed port)))))
+
+            ;; Install a UTF-8 locale so we can process UTF-8 files.
+            (setenv "GUIX_LOCPATH"
+                    #+(file-append glibc-utf8-locales "/lib/locale"))
+            (setlocale LC_ALL "en_US.utf8")
+            (setenv "LC_ALL" "en_US.utf8")
+            (setvbuf (current-error-port) 'line)
+
+            (n-par-for-each (parallel-job-count)
+                            (lambda (file)
+                              (if (string-suffix? ".html" file)
+                                  (process-html file)
+                                  ;; Copy FILE as is to #$output.
+                                  (let* ((base   (string-drop file (string-length #$input)))
+                                         (target (string-append #$output base)))
+                                    (mkdir-p (dirname target))
+                                    (if (eq? 'symlink (stat:type (lstat file)))
+                                        (symlink (readlink file) target)
+                                        (copy-file file target)))))
+                            (find-files #$input))))))
+
+  (computed-file "stylized-html-manual" build))
+
 (define* (html-manual source #:key (languages %languages)
                       (version "0.0")
                       (manual %manual)
@@ -690,9 +838,11 @@ makeinfo OPTIONS."
                     (filter (compose file-exists? language->texi-file-name)
                             '#$languages)))))
 
-  (let* ((name   (string-append manual "-html-manual"))
-         (manual (computed-file name build #:local-build? #f)))
-    (syntax-highlighted-html manual
+  (let* ((name    (string-append manual "-html-manual"))
+         (manual* (computed-file name build #:local-build? #f)))
+    (syntax-highlighted-html (stylized-html source manual*
+                                            #:languages languages
+                                            #:manual manual)
                              #:mono-node-indexes mono-node-indexes
                              #:split-node-indexes split-node-indexes
                              #:name (string-append name "-highlighted"))))