emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/hyperbole 5d5e2aa: Add kexport:display to instantly dis


From: ELPA Syncer
Subject: [elpa] externals/hyperbole 5d5e2aa: Add kexport:display to instantly display collapsible HTML koutlines
Date: Sat, 22 May 2021 15:57:10 -0400 (EDT)

branch: externals/hyperbole
commit 5d5e2aab08df4979046115b0c9c5ccbad288a7c6
Author: Bob Weiner <rsw@gnu.org>
Commit: Bob Weiner <rsw@gnu.org>

    Add kexport:display to instantly display collapsible HTML koutlines
---
 ChangeLog       |   7 ++
 kotl/kexport.el | 282 +++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 213 insertions(+), 76 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c2e7cb6..5b607b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,13 @@
     item, match to the first capitalized char in each item.
 
 * kotl/kexport.el (kexport:font-awesome-css-url,
+                   kexport:font-awesome-css-include,
+                   kexport:font-awesome-collapsible-javascript,
+                   kexport:buffer,
+                   kexport:display,
+                   kexport:html): Add/update to support collapsible
+   parent cells in HTML exported Koutlines.
+
 2021-05-19  Bob Weiner  <rsw@gnu.org>
 
 * Makefile (kotl/kotl-autoloads.el): Revert commit that removed
diff --git a/kotl/kexport.el b/kotl/kexport.el
index ab2124f..cbbd1e0 100644
--- a/kotl/kexport.el
+++ b/kotl/kexport.el
@@ -4,12 +4,17 @@
 ;;
 ;; Orig-Date:    26-Feb-98
 ;;
-;; Copyright (C) 1998-2017  Free Software Foundation, Inc.
+;; Copyright (C) 1998-2021  Free Software Foundation, Inc.
 ;; See the "../HY-COPY" file for license information.
 ;;
 ;; This file is part of GNU Hyperbole.
 
 ;;; Commentary:
+;; Use "https://validator.w3.org/"; to validate the HTML that this generates.
+;;
+;; Within JavaScript-enabled web browsers, koutline parent cells exported to
+;; HTML may be expanded and collapsed interactively.  This feature utilizes
+;; a small 20-line JavaScript snippet is included in each exported koutline.
 
 ;;; Code:
 ;;; ************************************************************************
@@ -18,7 +23,7 @@
 
 (require 'hypb)
 (require 'hpath)
-(require 'hibtypes)
+(require 'hibtypes) ;; loads hsys-www where www-url actype is defined
 (require 'klink)
 (require 'kview)
 (require 'kotl-mode)
@@ -111,11 +116,107 @@ pattern may be:
   as (match-beginning 1) since the regexp has just been matched against
   the target string when it is called.")
 
+
+(defconst kexport:font-awesome-css-url
+  "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css";
+  "Url that provides font-awesome expand/collapse glyphicons.
+Font Awesome Free is free and GPL friendly.")
+
+(defconst kexport:font-awesome-css-include
+  "<style>
+
+button {
+ display: inline;
+}
+
+span.nobreak {
+  white-space: nowrap;
+}
+
+div {
+ display: inline;
+}
+
+li {
+ list-style-type: none;
+}
+
+.collapsible {
+  all: unset;
+  background-color: inherit;
+  cursor: pointer;
+  display: block;
+  outline: inherit;
+}
+
+.collapsible:hover {
+  background-color: #FAFAD2;
+}
+
+.content {
+  display: block;
+}
+</style>\n"
+  "CSS that styles collapsible HTML-exported Koutline parent cells")
+
+(defconst kexport:font-awesome-collapsible-javascript
+  "<script>
+var coll = document.getElementsByClassName('collapsible');
+var i;
+
+function childElt(elt, tag)
+{
+    return elt.getElementsByTagName(tag)[0];
+}
+
+for (i = 0; i < coll.length; i++) {
+  coll[i].addEventListener('click', function() {
+    var icon = childElt(this, 'span');
+    var content = this.nextElementSibling;
+    if (content.style.display === 'none') {
+      content.style.display = 'block';
+      icon.classList.add('fas', 'fa-chevron-down');
+      icon.classList.remove('fa-chevron-right');
+    } else {
+      content.style.display = 'none';
+      icon.classList.add('fas', 'fa-chevron-right');
+      icon.classList.remove('fa-chevron-down');
+    }
+  });
+}
+</script>\n"
+  "JavaScript which expands/collapses HTML-exported Koutline parent cells")
+
 ;;; ************************************************************************
 ;;; Public functions
 ;;; ************************************************************************
 
 ;;;###autoload
+(defun kexport:buffer (&optional soft-newlines-flag)
+  "Export the current buffer's koutline to the same named file with a 
\".html\" suffix.
+Return the pathname of the html file created.
+
+By default, this retains newlines within cells as they are.  With optional 
prefix arg, SOFT-NEWLINES-FLAG,
+hard newlines are not used.  Also converts Urls and Klinks into Html 
hyperlinks."
+  (interactive "P")
+  (let ((export-from buffer-file-name)
+       (output-to (concat (file-name-sans-extension buffer-file-name) 
".html")))
+    (kexport:html export-from output-to soft-newlines-flag)
+    output-to))
+
+;;;###autoload
+(defun kexport:display (&optional soft-newlines-flag)
+  "Export the current buffer's koutline to the same named file with a 
\".html\" suffix and display it in a web browser.
+Return the pathname of the html file created.
+
+By default, this retains newlines within cells as they are.  With optional 
prefix arg, SOFT-NEWLINES-FLAG,
+hard newlines are not used.  Also converts Urls and Klinks into Html 
hyperlinks."
+  (interactive "P")
+  (let ((html-file (kexport:buffer soft-newlines-flag)))
+    (hact 'www-url (concat "file://" html-file))
+    html-file))
+
+;;;###autoload
 (defun kexport:html (export-from output-to &optional soft-newlines-flag)
   "Export a koutline buffer or file in EXPORT-FROM to html format in OUTPUT-TO.
 By default, this retains newlines within cells as they are.  With optional 
prefix arg, SOFT-NEWLINES-FLAG,
@@ -153,80 +254,109 @@ STILL TODO:
         (standard-output (get-buffer output-to-buf-name))
         title)
 
-    (set-buffer standard-output)
-    (setq buffer-read-only nil
-         kexport:output-filename buffer-file-name)
-    (erase-buffer)
-    (set-buffer export-buf-name)
-    (setq kexport:input-filename buffer-file-name)
-
-    ;; Use the first line of the first cell as the default HTML document title.
-    (setq title (save-excursion
-                 (kotl-mode:beginning-of-buffer)
-                 (kcell-view:contents)))
-    (if (string-match "\n" title)
-       (setq title (substring title 0 (match-beginning 0))))
-
-    ;; If called interactively, prompt user for the title to use.
-    (if (called-interactively-p 'interactive)
-       (setq title (read-string (format "Title for %s: " output-to-buf-name)
-                                title)))
-
-    (princ "<html><head>\n\n")
-    (princ "<a id=\"top\"></a><a id=\"k0\"></a>\n")
-    (princ (format "<title>%s</title>\n" title))
-    (if kexport:html-description
-       (princ (format "<meta id=\"description\" content=\"%s\">\n"
-                      kexport:html-description)))
-    (if kexport:html-keywords
-       (princ (format "<meta id=\"keywords\" content=\"%s\">\n"
-                      kexport:html-keywords)))
-    (princ "</head>\n\n")
-    (princ (format "<body %s>\n\n" kexport:html-body-attributes))
-    (princ (format "<center><h1>%s</h1></center>\n\n" title))
-    (let* ((separator
-           (hypb:replace-match-string
-            ">" (hypb:replace-match-string
-                 "<" (kview:label-separator kview) "&lt;")
-            "&gt;"))
-          i level label contents)
-      (kview:map-tree
-       (lambda (kview)
-        (setq level (kcell-view:level)
-              i level)
-        (while (> i 1)
-          (princ "<ul>")
-          (setq i (1- i)))
-        (princ "<table><tr>\n")
-        (setq label (kcell-view:label))
-        (princ (format "<a id=\"k%s\"></a>" label))
-        (princ (format "<a id=\"k%s\"></a>\n" (kcell-view:idstamp)))
-        (princ "<td width=2% valign=top><pre>\n")
-        (princ (format
-                "<font %s>%s%s</font></pre></td>\n"
-                kexport:label-html-font-attributes
-                label separator))
-        (princ "<td>")
-        (setq contents (kcell-view:contents))
-        (if (string-match "\\`\\([-_$%#@~^&*=+|/A-Za-z0-9 ]+\\):.*\\S-"
-                          contents)
-            (princ (format "<a id=\"%s\"></a>"
-                           (substring contents 0 (match-end 1)))))
-        (setq contents (kexport:html-markup contents))
-        (if soft-newlines-flag
-            (princ contents)
-          (princ "<pre>") (princ contents) (princ "</pre>"))
-        (princ "</td>\n")
-        (princ "</tr></table>")
-        (setq i level)
-        (while (> i 1)
-          (princ "</ul>")
-          (setq i (1- i)))
-        (terpri) (terpri))
-       kview t t))
-    (princ "</body></html>\n")
-    (set-buffer standard-output)
-    (save-buffer)))
+    (with-current-buffer standard-output
+      (setq buffer-read-only nil
+           kexport:output-filename buffer-file-name)
+      (erase-buffer))
+    (with-current-buffer export-buf-name
+      (save-excursion
+       (kotl-mode:beginning-of-buffer)
+       (setq kexport:input-filename buffer-file-name)
+
+       ;; Use the first line of the first cell as the default HTML document 
title.
+       (setq title (save-excursion
+                     (kotl-mode:beginning-of-buffer)
+                     (kcell-view:contents)))
+       (if (string-match "\n" title)
+           (setq title (substring title 0 (match-beginning 0))))
+
+       ;; If called interactively, prompt user for the title to use.
+       (if (called-interactively-p 'interactive)
+           (setq title (read-string (format "Title for %s: " 
output-to-buf-name)
+                                    title)))
+
+       (princ "<html><head>\n\n")
+       (princ "<a id=\"top\"></a><a id=\"k0\"></a>\n")
+       (princ (format "<title>%s</title>\n" title))
+       (if kexport:html-description
+           (princ (format "<meta id=\"description\" content=\"%s\">\n"
+                          kexport:html-description)))
+       (if kexport:html-keywords
+           (princ (format "<meta id=\"keywords\" content=\"%s\">\n"
+                          kexport:html-keywords)))
+       (princ "<meta name=\"viewport\" content=\"width=device-width, 
initial-scale=1\">")
+       ;; CSS
+       (princ (format "<link rel=\"stylesheet\" href=\"%s\">\n" 
kexport:font-awesome-css-url))
+       (princ kexport:font-awesome-css-include)
+       ;; HTML
+       (princ "</head>\n\n")
+       (princ (format "<body %s>\n\n" kexport:html-body-attributes))
+       (princ (format "<center><h1>%s</h1></center>\n\n" title))
+       (let* ((separator
+               (hypb:replace-match-string
+                ">" (hypb:replace-match-string
+                     "<" (kview:label-separator kview) "&lt;")
+                "&gt;"))
+              i is-parent is-last-sibling no-sibling-stack level label 
contents)
+         (kview:map-tree
+          (lambda (kview)
+            (setq level (kcell-view:level)
+                  i level
+                  is-parent (kcell-view:child-p)
+                  is-last-sibling (not (kcell-view:sibling-p)))
+            (when is-parent
+              (push is-last-sibling no-sibling-stack)
+              (princ "<button type=\"button\" class=\"collapsible\">\n"))
+            (while (> i 1)
+              (princ "<ul>")
+              (setq i (1- i)))
+            (princ "<li list-style-type=none><table><tr>\n")
+            (princ "<td width=1% valign=top>")
+            (princ (format "<span class=\"fas fa-chevron-down 
fa-fw\"%s></span>"
+                           (if is-parent
+                               ""
+                             ;; Fill same space for alignment but don't
+                             ;; show collapsible chevron when not a parent
+                             " style=\"visibility:hidden\"")))
+            (princ "</td>\n")
+            (princ "<td width=2% valign=top>\n")
+            (setq label (kcell-view:label))
+            (princ (format "<a id=\"k%s\"></a>" label))
+            (princ (format "<a id=\"k%s\"></a>\n" (kcell-view:idstamp)))
+            (princ (format
+                    "<pre><font %s>%s%s</font></pre>\n"
+                    kexport:label-html-font-attributes
+                    label separator))
+            (princ "</td>\n<td>\n")
+            (setq contents (kcell-view:contents))
+            (if (string-match "\\`\\([-_$%#@~^&*=+|/A-Za-z0-9 ]+\\):.*\\S-"
+                              contents)
+                (princ (format "<a id=\"%s\"></a>"
+                               (substring contents 0 (match-end 1)))))
+            (setq contents (kexport:html-markup contents))
+            (if soft-newlines-flag
+                (princ contents)
+              (princ "<pre>") (princ contents) (princ "</pre>"))
+            (princ "</td>\n")
+            (princ "</tr></table></li>")
+            (setq i level)
+            (while (> i 1)
+              (princ "</ul>")
+              (setq i (1- i)))
+            (cond (is-parent
+                   (princ "\n</button>\n<div class=\"content\">\n"))
+                  ((and (/= level 1) is-last-sibling)
+                   (princ "\n</div>")
+                   (while (pop no-sibling-stack)
+                     (princ "</div>"))))
+            (when (not is-parent)
+              (terpri) (terpri)))
+          kview t))
+       ;; JavaScript
+       (princ kexport:font-awesome-collapsible-javascript)
+       (princ "</body></html>\n")))
+    (with-current-buffer standard-output
+      (save-buffer))))
 
 ;;; ************************************************************************
 ;;; Private functions



reply via email to

[Prev in Thread] Current Thread [Next in Thread]