# -*- eval: (my/execute-startup-blocks) -*-
# The .el files are the source of truth; this file is the manual.  Its Lisp blocks are
# no longer tangled, lest they overwrite the .el files with stale code.
#+property: header-args:emacs-lisp :tangle no :exports code
#+property: header-args :eval never-export
#+macro: blurb Forty-six custom blocks and fifty-seven link types for Emacs' Org-mode ^_^
# On alhassy.com, each public top-level heading is its own article; see AlBasmala.org §“A REDIRECT to a container”.
#+article_style: multiple

# Render diagram: (progn (use-package ob-latex-as-png :ensure t)
#                        (add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images))
#+begin_src latex-as-png :file org-special-block-extras-overview.png :resolution "720" :results raw value replace :exports results
\usepackage{smartdiagram}
\usepackage{graphicx}
\vspace{1.5em}
\centering{One Org source $\rightarrow$ rich HTML \emph{and} \LaTeX\ export}

\vspace{1em}
\smartdiagramset{
  planet color=black!75,
  planet size=3.5cm,
  planet font=\normalfont\bfseries\normalsize,
  satellite size=3.6cm,
  satellite font=\normalfont\small,
  satellite text width=3.5cm,
  distance planet-satellite=5.7cm,
  connection color=gray!60,
  connection line width=0.06cm,
  text color=black,
  font=\small\sffamily
}
\resizebox{1.0\textwidth}{!}{%
\smartdiagram[constellation diagram]{%
  {\color{white}\LARGE\texttt{org-special-block-extras}\\[0.5em]\normalsize define blocks \& links},
  \texttt{org-defblock}\\[0.5em]{\footnotesize custom Org blocks},
  \texttt{details}\ \texttt{parallel}\\[0.5em]\texttt{proof}\ \texttt{margin}\\[0.5em]{\footnotesize 30+ block types},
  \texttt{org-deflink}\\[0.5em]{\footnotesize custom Org links},
  \texttt{doc:}\ \texttt{kbd:}\\[0.5em]\texttt{badge:}\ \texttt{fortune:}\\[0.5em]{\footnotesize 34+ link types},
  HTML \& \LaTeX\\[0.5em]{\footnotesize single Org source},
  \texttt{spoiler}\ \texttt{tree}\\[0.5em]\texttt{demo}\ \texttt{solution}\\[0.5em]{\footnotesize interactive export}
}} % end \resizebox + \smartdiagram
\\{\color{white} Bye!}
#+end_src

* COMMENT Random notes
# TODO: Final version should not have the following incantation active.
html-export-style:solarized_light

#+begin_src emacs-lisp
(setq org-export-with-broken-links nil)
(setq org-export-with-broken-links t)
(add-to-list 'load-path (expand-file-name "./lisp"))
(require 'org-special-block-extras)
(require 'org-graph-block)

(load-file "./tests/examples/README.el") ;; The osbe-example:NAME link

(org-html-export-to-html)

;; TODO Add a hook to run tests whenever I produce an export!
#+end_src


#+RESULTS:
: index.html

#+name: startup-code
#+begin_src emacs-lisp :exports none :tangle no :exports none
(org-docs-load-libraries (list "~/org-special-block-extras/documentation.org"))
#+end_src

# TODO: Do I have local unpushed branches on my other machine?

# TODO: The main difference between “doc” and “margin” is that the latter admits a block form,
# whereas the former only admits a link form. We can merge the two into a single type.

# TODO: Tersely explain how this pkg works, at the top of the README; e.g.:
# org-defblock registers blocks (in org-supported-blocks),
# then, just before export we replace blocks with the (verbatim) result of their definitions.

# TODO: Write unit tests against org-osbe-html-export-preserving-whitespace,
# rename it to `org-export-string-as-html-preserving-whitespace`
# so that the new name looks similar to the built-in `org-export-string-as`
# thereby increasing discoverability. Unit tests can mimic ‘margin’ block usage.
# After the unit tests characterize this
# method, then refactor it. The current implementation could be prettier:
# Perhaps the implementation can be replace “ ” with “ ”, and “\n” with “@@html: <br>@@”,
# then invoke built-in `org-export-string-as`?
# 
# orange:Going orange:forward, it would be nice to get full code colouring of
# source blocks in the HTML tooltips ---which can be done using
# doc:org-export-string-as, just need the time.

# TODO: The main difference between “doc” and “margin” is that the latter admits a block form,
# whereas the former only admits a link form. We can merge the two into a single type.
# For example, “doc: !Here's more explanatory prose” ≈ “[[margin: Here's more explanatory prose]]”; i.e.,
# doc links that start with ‘!’ are considered to be inline literals and not addresses to look-up information.
  
# TODO: Introduce org-defblock-alias which alises org-block/X, org-link/X, registers the new name in org-supported-blocks, and registers the new name as an org-link.


# TODO: Add tests involving header-args
# Set the width onces-and-for-all using header-args:
#
#   (setq org-babel-default-header-args:margin '((:width . "4cm")))

# TODO: Make org-defblock looks almost the same as cl-defun, namely argslist has args being either pairs or singletons!

# TODO: Since the implementation is a find-replace, nested blocks do not honor enclosing blocks.
# For example, try placing a `rename` block within an `example` block and see that it is expanded!

# TODO: Add :noexport support to [all?] blocks?
# TODO: Could generalize this to be a hook that's run before processing blocks, and :noexport support amounts to a hook that returns "" for the block.

# TODO: Favour plists over HTML tags:
#
#   ;; dom.el has multiple methods to maniuplate HTML DOM plist values.
#   (shr-dom-to-xml '(name ((key₀ . value₀) (key₁ . value₁)) "contents"))
# ⇒ "<name key₀=\"value₀\" key₁=\"value₁\">contents</name>"


#  1. osbe-example:doc
#  2. osbe-example:rename

** See changes for current buffer only
C-c M-g will pop up a menu just for that fie and you can hit d there to get a diff, then stage as you like!



** COMMENT Run all /unit/ tests

# TODO C-c C-c  ⇒ Run all tests, and see them printed with their descriptions nicely.
#+begin_src emacs-lisp :exports none :tangle no
;; Press ‘q’ to kill the resulting buffer and window.
;;
;; i.e., insist on displaying in a dedicated buffer
(let ((max-mini-window-height 0))
  (ignore-errors (kill-buffer "ERT: tests.el"))
  (message "Tangling source & tests...") (org-babel-tangle)
  (message "Running tests...")
  (display-message-or-buffer (shell-command-to-string "emacs -batch -l ert -l tests.el -f ert-run-tests-batch-and-exit"))
  (switch-to-buffer-other-window "*Message*")
  (rename-buffer (format "ERT: tests.el"))
  ;; Make · look like a space
  (font-lock-mode -1) (font-lock-add-keywords nil '(("·" 0 '(face default display " ") t))) (font-lock-mode +1)
  (highlight-regexp "failed" 'hi-red-b)
  (highlight-regexp "failures" 'hi-red-b)
  (highlight-regexp "passed" 'hi-green-b)
  (highlight-regexp "deprecated" 'hi-blue-b)
  (or (re-search-forward "failed" nil t) (message "Yay, everything passes!"))
  (read-only-mode)
  (local-set-key "q" #'kill-buffer-and-window) ;; (message "Read-only; “q” to kill buffer and window.")
  )
#+end_src

* HTML & LaTeX Setup                                                 :ignore:
  :PROPERTIES:
  :CUSTOM_ID: HTML-LaTeX-Setup
  :END:

#+macro: newline @@latex: \newline@@

# (add-to-list 'org-src-lang-modes '("org" . c))
#+BEGIN_export html
<style>
/* Using source blocks “C” as alias for Org */
pre.src-C:before { content: 'Org-mode Example!'; }
/* Execute this for alias: (add-to-list 'org-src-lang-modes '("org" . C)) */
</style>
#+END_export

#+latex_header: \usepackage{newunicodechar}



#+latex_header: \newunicodechar{𝒳}{\ensuremath{\mathcal{X}}}
#+latex_header: \newunicodechar{ℒ}{\ensuremath{\mathcal{L}}}
#+LATEX_HEADER: \usepackage[hmargin=15mm,top=15mm,bottom=15mm]{geometry}

#+latex_header: \usepackage{tcolorbox}

#+latex_header: \newunicodechar{τ}{\ensuremath{\tau}}
#+latex_header: \newunicodechar{⟨}{\ensuremath{\langle}}
#+latex_header: \newunicodechar{⟩}{\ensuremath{\rangle}}
#+latex_header: \newunicodechar{→}{\ensuremath{\to}}
#+latex_header: \newunicodechar{⊕}{\ensuremath{\oplus}}
#+latex_header: \newunicodechar{₀}{\ensuremath{_0}}
#+latex_header: \newunicodechar{₁}{\ensuremath{_1}}
#+latex_header: \newunicodechar{₂}{\ensuremath{_2}}
#+latex_header: \newunicodechar{ₙ}{\ensuremath{_n}}
#+latex_header: \newunicodechar{ₖ}{\ensuremath{_k}}
#+latex_header: \newunicodechar{ᵢ}{\ensuremath{_i}}
#+latex_header: \newunicodechar{′}{'}
#+latex_header: \newunicodechar{⇒}{\ensuremath{\Rightarrow}}
#+latex_header: \newunicodechar{𝒞}{\ensuremath{\mathcal{C}}}
#+latex_header: \newunicodechar{∈}{\ensuremath{\in}}



#  (•̀ᴗ•́)و
#+latex_header: \newunicodechar{و}{\ensuremath{;}}
#+latex_header: \newunicodechar{•}{\ensuremath{\bullet}}
#+latex_header: \newunicodechar{ᴗ}{\ensuremath{\smile}}
#+latex_header: \newunicodechar{́}{\ensuremath{}}
#+latex_header: \newunicodechar{̀}{\ensuremath{}}
#+latex_header: \newunicodechar{‿}{\ensuremath{\smile}}

#+latex_header: \newunicodechar{⌣}{\ensuremath{\smile}}
#+latex_header: \newunicodechar{̈}{\ensuremath{{}^{..}}}

#+LATEX_HEADER: \usepackage{minted}
# +LATEX_HEADER: \usepackage{tcolorbox}
# +LATEX_HEADER: \usepackage{etoolbox}
# +LATEX_HEADER: \def\mytitle{??? Program Code ???}
# +LATEX_HEADER: \BeforeBeginEnvironment{minted}{\begin{tcolorbox}[title=\hfill \mytitle]}%
# +LATEX_HEADER: \AfterEndEnvironment{minted}{\end{tcolorbox}}%
# #
# Before a code block, write {{{code(title-of-block)}}}
# #
# +MACRO: code     @@latex:\def\mytitle{$1}@@
# #
# let's always break newlines, with a ‘↪’ indicated new lines.
# emacs-lisp is treated as common-lisp via minted
# +LaTeX: \setminted[common-lisp]{fontsize=\footnotesize, breaklines}
#+LaTeX: \setminted[common-lisp]{breaklines}

# Removing the red box that appears in "minted" when using unicode.
# Src: https://tex.stackexchange.com/questions/343494/minted-red-box-around-greek-characters
#
#+LATEX_HEADER: \makeatletter
#+LATEX_HEADER: \AtBeginEnvironment{minted}{\dontdofcolorbox}
#+LATEX_HEADER: \def\dontdofcolorbox{\renewcommand\fcolorbox[4][]{##4}}
#+LATEX_HEADER: \makeatother

#+latex_header: \newunicodechar{𝓃}{\ensuremath{n}}
#+latex_header: \newunicodechar{⋯}{\ensuremath{\cdots}}

# +LATEX_HEADER: \usepackage[dvipsnames]{xcolor} % named colours
#+latex_header: \definecolor{darkblue}{rgb}{0.0, 0.0, 0.55}
#+LATEX_HEADER: \hypersetup{colorlinks,linkcolor=darkblue,citecolor=darkblue,urlcolor=darkblue}

# https://taopeng.me/org-notes-style/
# #
#+HTML_HEAD: <link href="https://alhassy.github.io/next-700-module-systems/prototype/org-notes-style.css" rel="stylesheet" type="text/css" />

# +SETUPFILE: https://fniessen.github.io/org-html-themes/setup/theme-readtheorg.setup
#+latex_header:  \usepackage{multicol}
* Lisp Package Preamble                                            :noexport:
  :PROPERTIES:
  :CUSTOM_ID: Preamble
  :END:
#+BEGIN_SRC emacs-lisp  :noweb yes
;;; org-special-block-extras.el --- 46 new custom blocks & 56 link types for Org-mode   -*- lexical-binding: t; -*-

;; Copyright (c) 2021 Musa Al-hassy

;; Author: Musa Al-hassy <alhassy@gmail.com>
;; Version: 26.10.18
;; Package-Requires: ((s "1.13.1") (dash "2.18.1") (emacs "28.2") (org "9.8") (lf "26.10.1") (seq "2.0"))
;; Keywords: org, blocks, colors, convenience
;; URL: https://alhassy.com/org-special-block-extras


;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; This library provides common desirable features using the Org interface for
;; blocks and links:
;;
;; 0. A unified interface, the ‘defblock’ macro, for making new block and link types.
;;
;; 1. Colours: Regions of text and inline text can be coloured using 19 colours;
;;  easily extendable; below is an example.
;;
;;             #+begin_red org
;;             /This/
;;                   *text*
;;                          _is_
;;                               red!
;;             #+end_red
;;
;; 2. Multiple columns: Regions of text are exported into multiple side-by-side
;; columns
;;
;; 3. Remarks: First-class visible editor comments
;;
;; 4. Details: Regions of text can be folded away in HTML
;;
;; 5. Badges: SVG badges have the pleasant syntax
;; badge:key|value|colour|url|logo; only the first two are necessary.
;;
;; 6. Tooltips: Full access to Lisp documentation as tooltips, or any other
;; documentation-backend, including user-defined entries; e.g., doc:thread-first
;; retrives the documentation for thread-first and attachs it as a tooltip to
;; the text in the HTML export and as a glossary entry in the LaTeX export
;;
;; 7. Various other blocks: Solution, org-demo, spoiler (“fill in the blanks”).
;;
;; This file has been tangled from a literate, org-mode, file; and so contains
;; further examples demonstrating the special blocks it introduces.
;;
;; Full documentation can be found at
;; https://alhassy.com/org-special-block-extras

;;; Code:

;; String and list manipulation libraries
;; https://github.com/magnars/dash.el
;; https://github.com/magnars/s.el

(require 's)               ;; “The long lost Emacs string manipulation library”
(require 'dash)            ;; “A modern list library for Emacs”
(require 'subr-x)          ;; Extra Lisp functions; e.g., ‘when-let’.
(require 'cl-lib)          ;; New Common Lisp library; ‘cl-???’ forms.

(require 'cus-edit) ;; To get the custom-* faces

(require 'org)
(require 'ox-latex)
(require 'ox-html)
(require 'seq)

(require 'lf)

(defconst org-special-block-extras-version (package-get-version))
(defun org-special-block-extras-version ()
  "Print the current version of the package in the minibuffer."
  (interactive)
  (message org-special-block-extras-version))

<<forward-decls>>
#+END_SRC

# ;; Finally, the system is extensible: Users just use defblock!
# ;; org--TYPE for a new custom block TYPE, which is then
# ;; invoked.  The handler takes three arguments: - CONTENTS: The string contents
# ;; delimited by the custom block.  - BACKEND: The current exportation backend;
# ;; e.g., 'html or 'latex.  The handler must return a string.
#
#+BEGIN_SRC emacs-lisp :noweb yes
  (defcustom org-special-block-add-html-extra t
    "Whether to let `org-special-block-extras' to add content to the `ox-html' head tag.

The `org-special-block-extras' mode adds a lot of extra HTML/JS code that
1. [Bloat] may not be needed by everyone using this package,
2. [Security Threat] loads stuff from foreign websites.

Since the extra stuff is for beautiful tooltips or styles,
for ease of use, the default behaviour is to use such
“untrusted data from untrusted websites”.

To avoid such behaviour, set this variable to `nil'.")
#+END_SRC

#+BEGIN_SRC emacs-lisp :noweb yes
;;;###autoload
(define-minor-mode org-special-block-extras-mode
    "Provide 46 new custom blocks & 56 link types for Org-mode.

All relevant Lisp functions are prefixed ‘org-’; e.g., `org-docs-insert'.

This minor mode uses “untrusted data from untrusted websites” when exporting
to HTML, this is done for beautiful tooltips or styles.
Disable this behaviour by setting `org-special-block-add-html-extra' to `nil'.
"
  :lighter " OSBE"
  (if org-special-block-extras-mode
      (progn
        <<enable-mode>>
      ) ;; Must be on a new line; I'm using noweb-refs
    <<disable-mode>>
    )) ;; Must be on a new line; I'm using noweb-refs
#+END_SRC

#+RESULTS:

# With noweb, we need those new lines; otherwise in “x <<y>> z” results in every
# line of <<y>> being prefixed by x and postfixed by z.
# #
# See https://github.com/alhassy/emacs.d#what-does-literate-programming-look-like

* COMMENT Testing                                                  :noexport:
  :PROPERTIES:
  :CUSTOM_ID: Testing
  :END:
#+begin_src emacs-lisp :tangle tests.el
(setq needed-libraries
      '(s cl-lib dash org seq quelpa lf))

(require 'package)
(push '("melpa" . "https://melpa.org/packages/") package-archives)
(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))
(dolist (pkg needed-libraries)
  (unless (package-installed-p pkg)
    (package-install pkg)))

(load-file "lisp/org-special-block-extras.el")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Personal Testing Utils ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(require 'lf)  ;; to make use of “lf-string”
(require 'ert) ;; to make use of “should”


(cl-defun ⟰  (input &optional (backend 'html))
  "Export Org INPUT along BACKEND.

In particular, both org special blocks & links are exported into BACKEND.

Pictogram explanation: ⟰ is read ‘export’; it “exports upward to the moon whatever we have”."
  (org-special-block-extras-mode) ;; Ensure new blocks are registered
  (org-export-string-as
     input
     backend
     :body-only))

(defmacro ≋ (lhs rhs)
    "A shorthand for (should (equal LHS RHS))."
    `(should (equal ,lhs ,rhs)))

(defmacro ↯ (form &optional message)
    "The given FORM should error (with MESSAGE, ignoring whitespace).

Example: (↯ (error \"hola\") \"hola\")

Pictogram explanation: You've made such a big mistake, that the
heavens strike you down with a lightening bolt ↯↯"
  (if message
      `(should (equal (s-collapse-whitespace (cl-second (should-error ,form)))
                      (s-collapse-whitespace ,message)))
    `(should-error ,form)))


;; I like the shapes: (× some-crashing-form) and (↯ crashes with-this-message)
(defalias '✓ 'should)
(defalias '× '↯)


(defmacro ⇝ (expr &rest regexp)
    "The given EXPR should match the given REGEXP, which is wrapped by ‘rx’.

REGEXP could also be a string, in which case we are doing string equality.
Either way, whitespace is ignored in both arguments.

The symbol “⇝” should be read “rewrites to” or “elaborates to”.

I prefer this form since it has the main form we're asserting
against-at the forefront and makes it clear we're matching
against strings.

For example,

  (should (s-matches? \"An English greeting.\" (documentation 'speak)))

Becomes:

  (⇝ (documentation 'speak) \"An English greeting.\")

Pictogram explanation: A given expression “rewrites, reduces,” to
a given matching pattern. Such arrows are popular in Term Rewriting Systems."
  `(should (s-matches? (s-collapse-whitespace (rx ,(cons 'seq regexp)))
                       (s-collapse-whitespace ,expr))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#+end_src

#+RESULTS:
: ⇝

--------------------------------------------------------------------------------

The following creates the “Github Actions Workflow” file;
this way, Github will run your tests every time you commit ^_^

#+begin_src shell :tangle .github/workflows/main.yml
# This workflow will do a clean install of dependencies and run tests
# For more information see: https://help.github.com/actions/language-and-framework-guides/

name: Tests

# Controls when the action will run.
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Set up Emacs
        uses: purcell/setup-emacs@v3.0
        with:
          # The version of Emacs to install, e.g. "24.3", or "snapshot" for a recent development version.
          version: 27.1 # optional

      # Runs a single command using the runners shell
      # - name: Run a one-line script
      #  run: echo Hello, world!

      # Runs a set of commands using the runners shell
      # - name: Run a multi-line script
      #  run: |
      #    echo Add other actions to build,
      #    echo test, and deploy your project.

      - name: Run tests
        run: emacs -batch -l ert -l tests.el -f ert-run-tests-batch-and-exit
#+end_src

      # Upload coverage
      - uses: codecov/codecov-action@v1
* COMMENT Test that this org file itself exports without problems  :noexport:
:PROPERTIES:
:CUSTOM_ID: Test-that-this-org-file-itself-exports-without-problems
:END:

#+begin_src emacs-lisp :exports none :tangle "tests.el"
;; Even though I intend to “C-c C-e h o” myself to update
;; the webpage for this package, I like having this test
;; since it's run in “emacs -Q” which ensures there's no
;; implicit state / packages being used when I run “C-c C-e h o”.
;;
(deftest "OSBE org source exports to HTML without any problems"
  [html-export]
  (find-file "org-special-block-extras.org")

  ;; The html-export-style:𝒳 link downloads styles, let's disable/mock it.
  (org-deflink html-export-style () "")

  ;; Some doc:𝒳 links refer to my personal docs, so let's get those.
  (org-docs-load-libraries (list "~/org-special-block-extras/documentation.org"))

  ;; FIXME: I should not have to set this up; this is an error with “show:𝒳”?
  (setq o-value "whoops")

  (should (org-html-export-to-html)))
#+end_src

* COMMENT Abstract                                                   :ignore:
  :PROPERTIES:
  :CUSTOM_ID: Abstract
  :END:


#+begin_center

badge:Emacs|27|green|https://www.gnu.org/software/emacs|gnu-emacs
badge:Org|9.4|blue|https://orgmode.org|gnu

#+html: <span>
melpa:org-special-block-extras

[[badge:license|GNU_3|informational|https://www.gnu.org/licenses/gpl-3.0.en.html|read-the-docs][gnu 3 license badge]]
[[badge:docs|literate|success|https://github.com/alhassy/emacs.d#what-does-literate-programming-look-like|read-the-docs][read-the-docs badge]]
tweet:https://github.com/alhassy/org-special-block-extras
badge:contributions|welcome|green|https://github.com/alhassy/org-special-block-extras/issues

badge:author|musa_al-hassy|purple|https://alhassy.github.io/|nintendo-3ds
badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee

# badge:Hire|me|success|https://alhassy.github.io/about

badge:EmacsConf|2020|informational|https://youtu.be/BQdNhtJSbqk|youtube
#+end_center

:Outdated_pics:
#+begin_quote
The full article may be read as a PDF or as HTML ---or visit the repo.
Installation instructions are below.
#+end_quote

#+caption: Extensibility! /Plug and play support for new block types!/
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/foo_block.png

#+latex: \newpage
/First, a gallery of what's possible!/

| *Write Org-markup once, generate for many backends ^_^* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/colours.jpg

https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/colour_links.png

#+latex: \newpage
| *Displaying thoughts side-by-side ^_^* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/parallel.png
# | ( I use prettify symbols mode ) |

#+latex: \newpage
| *“First-class editor comments” In order: Chrome, Emacs Web Wowser, Org source, PDF* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/edcomm.png

#+latex: \newpage
| *Visually hiding, folding away, details* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/details.png


# Broke_Org_9_4:
#+latex: \newpage
| *An Emacs interface to https://shields.io/* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/badges.png
# :End:
# +latex: \newpage
| *Tooltips for documentation and glossary items --in the browser!* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_browser.png

# +latex: \newpage
| *Tooltips for documentation and glossary items --in Emacs!* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_emacs.png

# +latex: \newpage
| *Tooltips for documentation and glossary items --in the PDF!* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_pdf.png

# +latex: \newpage
| *Declaring documentation-glossary items* |
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_declaration.png
:End:

#+begin_center
*Abstract*
#+end_center
#+begin_quote
The aim is to write something once using Org-mode markup
then generate the markup for multiple backends.
That is, /*write once, generate many!*/

In particular, we are concerned with /‘custom’, or ‘special’, blocks/ which
delimit how a particular region of text is supposed to be formatted according to
the possible export backends.  In some sense, special blocks are meta-blocks.
Rather than writing text in, say, LaTeX environments using LaTeX commands or in
HTML =div='s using HTML tags, we promote using Org-mode markup in special blocks
---Org markup cannot be used explicitly within HTML or LaTeX environments.


/Special blocks/, like ~centre~ and ~quote~, allow us to use Org-mode as the primary
interface regardless of whether the final result is an HTML or PDF article;
sometime we need to make our own special blocks to avoid a duplication of
effort.  However, this can be difficult and may require familiarity with
relatively advanced ELisp concepts, such as macros and hooks; as such, users may
not be willing to put in the time and instead use ad-hoc solutions.

#+latex: \vspace{1em}
We present a new macro, defblock, which is similar in-spirit to Lisp's standard
doc:defun except that where the latter defines functions, ours defines new
special blocks for Emacs' Org-mode ---as well as, simultaneously, defining new
Org link types. Besides the macro, the primary contribution of this effort is an
interface for special blocks that /admits/ arguments and is familar to Org users
---namely, we ‘try to reuse’ the familiar ~src~-block interface, including
header-args, but for special blocks.

#+latex: \vspace{1em}
It is hoped that the ease of creating custom special blocks will be a gateway
for many Emacs users to start using Lisp.
#+latex: \iffalse
*A 5-page PDF covering ELisp fundamentals* can be found *here*.
# a video lecture for this article can be found at
# badge:EmacsConf|2020|informational|https://youtu.be/BQdNhtJSbqk|youtube.

This article is featured in EmacsConf2020, with slides here:
No pictures, instead we use this system to make the  slides
have a variety of styling information; i.e., we write Org
and the result looks nice. “Look ma, no HTML required!”

#+latex: \fi

#+latex: \vspace{1em}
# A tutorial on special blocks, link types, and this macro is found in the [[#A-unified-interface-for-special-blocks-and-links-defblock][first
# section]] below. The remaining sections are examples of ~defblock~; namely, the
# construction of the special blocks used in the tutorial ;-)
#
#+latex: \vspace{1em}
#+latex: \textbf{Almost little to no attention has been afforded to making the PDF “look nice”; consider reading the HTML.}

# Consequently, we extend the number of block types available to the Emacs
# Org-mode user *without forcing the user* to learn HTML or LaTeX.
# Indeed, I am not a web developer and had to learn a number of HTML concepts
# in the process ---the average Org user should not have to do so.
#
# Similarly, we provide a number of ‘link types’ ~[[linktype:label][description]]~
# for producing in-line coloured text and SVG “badges”.
#
# We begin with the first two sections serving as mini-tutorials on special blocks
# and on link types. The special block setup we use is /extensible/ in that a new
# block named ~𝒞~ will automatically be supported if the user defines a function
# ~org--𝒞~ that formats the text of a block.  *The remaining
# sections are literate implementation matter, along with examples and
# screenshots.*
#
# In summary, we provide 20 colour block types and 20 colour link types,
# an ‘editor comment’ block type as well as a link type,
# a ‘details’ block type, a ‘parallel’ multiple columns view block type,
# a ‘link here’ link type, 8 badge link types,
# and block and link types for making documentation-glossary entries.
# That is, *we provide 46 block types and 56 link types*.
#+end_quote

#+attr_html: :width 1000px
#+attr_latex: :width 100px
#+caption: Write in Emacs using Org-mode, export beautifully to HTML or LaTeX
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/minimal-working-example-multiforms.png

* COMMENT org-tutorial                                               :ignore:
  :PROPERTIES:
  :CUSTOM_ID: org-tutorial
  :END:
#+include: ~/.emacs.d/init.org::#Mini-tutorial-on-Org-mode

#+html: <!--
#+latex: \vfill
#+begin_quote
The full article may be read as a PDF or as HTML ---or visit the repo.
Installation instructions are below.
#+end_quote
#+html: -->

#+latex: \newpage
#+begin_quote
The full article may be read as a PDF or as HTML ---or visit the repo.
Installation instructions are below.
#+end_quote
#+latex: \newpage

* COMMENT A unified interface for special blocks and links: ~defblock~
  :PROPERTIES:
  :CUSTOM_ID: A-unified-interface-for-special-blocks-and-links-defblock
  :END:

**    /How do I make a new special block?/ ---Core Utility :ignore:introduction:
   :PROPERTIES:
   :CUSTOM_ID: How-do-I-make-a-new-special-block-Core-Utility
   :END:

An Org-mode block of type 𝒳 is a bunch of text enclosed in ~#+begin_𝒳~ and
~#+end_𝒳~, upon export it modifies the text ---e.g., to center it, or to display
it as code. We show how to make /new/ blocks using a simple interface
---defblock--- that lets users treat 𝒳 as a string-valued function in the style
of doc:defun.

The notable features of the system are as follows.

- Familiar ~defun~ syntax for making block ---~defblock~
- Familiar ~src~ syntax for passing arguments ---e.g., ~:key value~
  # - Fine-grained control over export translation phases —c.f., ~org-parse~ above
- Modular: New blocks can be made out of existing blocks really quickly using
  ~blockcall~ ---similar to Lisp's ~funcall~.


#+begin_details EmacsConf 2020 Abstract

# From https://emacsconf.org/2020/schedule/22/:

Users will generally only make use of a few predefined /special blocks/, such as
~example, centre, quote~, and will not bother with the effort required to make new
ones. When new encapsulating notions are required, users will either fallback on
HTML or LaTeX specific solutions, usually littered with ~#+ATTR~ clauses to pass
around configurations or parameters.

Efforts have been exerted to mitigate the trouble of producing new special
blocks. However, the issue of passing parameters is still handled in a clumsy
fashion; e.g., by having parameters be expressed in a special block's content
using specific keywords.

We present a novel approach to making special blocks in a familiar fashion and
their use also in a familiar fashion. We achieve the former by presenting
~defblock~, an anaphoric macro exceedingly similar to ~defun~, and for the latter we
mimic the usual ~src~-block syntax for argument passing to support special blocks.

For instance, here is a sample declaration.

#+begin_src emacs-lisp :tangle no
(org-defblock stutter (nil nil reps 2)
  "Output the CONTENTS of the block REPS many times"
  (org-parse (s-repeat reps contents)))
#+end_src

Here is an invocation that passes an optional argument; which defaults to 2 when
not given.

#+begin_example org
,#+begin_stutter 5
Emacs for the win :-)
,#+end_stutter 5
#+end_example

Upon export, to HTML or LaTeX for instance, the contents of this block are
repeated (/stuttered/) 5 times. The use of ~src~-like invocation may lead to a
decrease in ~#+ATTR~ clauses.

In the presentation, we aim to show a few *practical* special blocks that users
may want: A block that …

- translates /some selected/ text ---useful for multilingual blogs
- hides /some selected/ text ---useful for learning, quizzes
- folds/boxes text ---useful in blogs for folding away details

In particular, all of these examples will be around ~5 lines long!

We also have a larger collection of more useful block types, already implemented.

The notable features of the system are as follows.

- Familiar ~defun~ syntax for making block ---~defblock~
- Familiar ~src~ syntax for passing arguments —e.g., ~:key value~
- Fine-grained control over export translation phases ---c.f., ~org-parse~ above
- Modular: New blocks can be made out of existing blocks really quickly using
  ~blockcall~ ---similar to Lisp's ~funcall~. We will show how to fuse two blocks to
  make a new one, also within ~5 lines.

#+latex: \iffalse
*It is hoped that the ease of creating custom special blocks will be a gateway for many Emacs users to start using Lisp.*
#+latex: \fi

#+end_details

**   /What is a special block?/
   :PROPERTIES:
   :CUSTOM_ID: What-is-a-special-block
   :END:

  An Org mode block is a region of text surrounded by =#+BEGIN_𝒳 … #+END_𝒳=; they
  serve various purposes as summarised in the table below.  However, we shall
  *use such blocks to execute arbitrary code on their contents*.

  | 𝒳       | Description                                        |
  |---------+----------------------------------------------------|
  | =example= | Format text verbatim, leaving markup as is         |
  | =src=     | Format source code                                 |
  | =center=  | Centre text                                        |
  | =quote=   | Format text as a quotation ---ignore line breaks   |
  | =verse=   | Every line is appended with a line break           |
  | =tiny=    | Render text in a small font; likewise =footnotesize= |
  | =comment= | Completely omit the text from export               |

  - They can be folded and unfolded in Emacs by pressing TAB in the =#+BEGIN= line.
  - The contents of blocks can be highlighted as if they were of language ℒ such
    as =org, html, latex, haskell, lisp, python, …= by writing =#+BEGIN_𝒳 ℒ= on the
    starting line, where ~𝒳~ is the name of the block type.
  - Verbatim environments =src= and =example= may be followed by switch =-n= to
    display line numbers for their contents.

I use snippets in my init to quickly insert special blocks (•̀ᴗ•́)و

#+begin_box
 You can ‘zoom in temporarily’, /narrowing/ your focus to only on a particular
 block, with doc:org-narrow-to-element, ~C-x n e~, to make your window only show
 the block.  Then use ~C-x n w~ to /widen/ your vision of the buffer's contents.
#+end_box

#+begin_details Warning! Special blocks of the same kind do not nest!
By their very nature, special blocks of /the same name/ cannot be nested ---e.g.,
try to put one ~quote~ block within another and see what (does not) happen.

Moreover, special blocks cannot contain unicode in their names and no
underscore, ‘_’, in their names; e.g., a special block named ~quote₀~ will
actually refer to ~quote~.
#+end_details

Our goal is to turn Org blocks into LaTeX environments and HTML divs.

Why not use LaTeX or HTML environments directly?
   - Can no longer use Org markup in such settings.
   - Committed to one specific export type.

#+begin_remark Aside
The export syntax =@@backend: 𝒳@@= inserts text 𝒳 literally as-is precisely when
the current backend being exported to is =backend=. This is useful for inserting
=html= snippets or =latex= commands. We can use =@@comment: 𝒳@@= to mimic inline
comments ;-)  ---Since there is [hopefully] no backend named =comment=.
#+end_remark

#+begin_box :background-color blue
#+begin_parallel 3
In general, a “special block” such as
   #+begin_example org
   #+begin_𝒳
   I /love/ Emacs!
   #+end_𝒳
   #+end_example

#+columnbreak:

   Exports to LaTeX as:
   #+begin_src latex :tangle no :exports code
   \begin{𝒳}
   I \emph{love} Emacs!
   \end{𝒳}
   #+end_src

   #+RESULTS:
   #+begin_export latex
   \begin{𝒳}
      I \emph{love} Emacs!
      \end{𝒳}
   #+end_export

#+columnbreak:

   Exports to HTML as:
   #+begin_src html :tangle no
   <div class="𝒳">
   I <em>love</em> Emacs!
   </div>
   #+end_src
#+end_parallel
#+end_box

#+begin_center
/Notice that the standard org markup is also translated according to the export
type./
#+end_center

If the ~𝒳~ environment exists in a backend ---e.g., by some ~\usepackage{⋯}~ or
manually with {{{newline}}}
~\newenvironment{𝒳}{⋯}{⋯}~ in LaTeX--- then the file will compile
without error.  Otherwise, you need to ensure it exists ---e.g., by defining the
backend formatting manually yourself.

#+latex: \vspace{1em}
#+begin_remark Aside
LaTeX packages that a user needs consistently are declared in the
{{{newline}}} list ~org-latex-packages-alist~. See its documentation, with ~C-h o~,
to learn more.  To export to your own LaTeX classes, ~C-h o org-latex-classes~.
#+end_remark
#+latex: \vspace{1em}

#+begin_box What is an HTML ‘div’? :background-color pink
A ~div~ tag defines a division or a section in an HTML document that is styled in
a particular fashion or has JavaScript code applied to it.  For example
---placing the following in an ~#+begin_export html ⋯ #+end_export~--- results in
a section of text that is editable by the user ---i.e., one can just alter text
in-place--- and its foreground colour is red, while its background colour is
light blue, and it has an uninformative tooltip.
#+begin_parallel
_Source_
#+begin_src html :tangle no
<div contenteditable="true"
     title="woah, a tool tip!"
     style="color:red; background-color:lightblue">
This is some editable text! Click me & type!
</div>
#+end_src

#+html: <br>
_Result_
#+html: <br><br>

#+begin_export html
<div contenteditable="true"
     title="woah, a tool tip!"
     style="color:red; background-color:lightblue">
This is some editable text! Click me & type!
</div>
#+end_export
#+end_parallel
#+end_box

#+begin_box What is a CSS ‘class’?
To use a collection of style settings repeatedly, we may declare them in a =class=
---which is just an alias for the ;-separated list of =attribute:value=
pairs. Then our ~div~'s refer to that particular ~class~ name.

#+latex: \vspace{1em}
#+begin_parallel :bar t
For example, in an HTML export block, we may declare the following style class
named ~red~.
#+begin_example org
#+begin_export html
<style>
.red { color:red; }
</style>
#+end_export
#+end_example

#+columnbreak:

Now, the above syntax with ~𝒳~ replaced by ~red~ works as desired in HTML export:
HTML now knows of a class named ~red~.

#+latex: \vspace{1em}
#+html: <br><hr>
For instance, now this
#+begin_src C :tangle no
,#+begin_red
I /love/ Emacs!
,#+end_red
#+end_src
Results in:
#+begin_red
I /love/ Emacs!
#+end_red
#+html: <hr>

#+latex: \vspace{1em}
This approach, however, will not work if we want to produce LaTeX and so
requires a duplication of efforts. We would need to declare such formatting once
for each backend.

#+end_parallel
#+end_box
**   /How do I make a new link type?/
   :PROPERTIES:
   :CUSTOM_ID: Links
   :END:

#+begin_center
/Sometimes using a block is too verbose and it'd be better to ‘inline’ it; for
this, we use Org's link mechanism./
#+end_center

#+begin_box "What would I use links for?" :background-color custard
+ Buttons :: ~[[elisp:(find-file user-init-file)][Go to my init!]]~ is a nice
  clickable-/actionable/ button within Emacs. The =elisp= link is part of Emacs.

  #+html: <br>

+ Textual expansions :: =show:user-full-name= expands, upon export, to /Musa
  Al-hassy/ on my machine. Or maybe we want a splash of colour in our lives:
  =*<pink: super neato stuff>*= becomes *<pink: super neato stuff>*.

  Similarly, ~link-here:usefulness-of-links~ becomes:
  link-here:usefulness-of-links. When you click on it, the URL of the webpage
  changes: It is a local anchor to a possibly interesting location in your
  article. Similarly, ~octoicon:home~ becomes octoicon:home; doc:org-link/octoicon.

  More aesthetically, =<badge: Emacs | is awesome | blue |
  https://www.google.com/search?q=hello%20world | gnu-emacs>= exports to <badge:
  Emacs | is awesome | blue | https://www.google.com/search?q=hello%20world |
  gnu-emacs>.

  These link types are all defined below.

  #+html: <br>

+ Definitions / Personal Glossary :: ~doc:thread-first, doc:family, doc:Hussain~
  export as the link labels but with tooltips for the Lisp function
  doc:thread-first, for the English definition of doc:family, and my personal
  documentation for the phrase doc:Hussain.

  Similarly, ~[[kbd:M-s h .]]~ becomes 〔M-s h .〕, which has a tooltip for
  the Lisp function associated with the keybinding.

  # (org-docs-load-libraries (list "~/org-special-block-extras/documentation.org"))
#+end_box

#+begin_details Example Mini-Article Using The Above Link Types
( link-here:example-article-via-links ) 〔C-x ESC ESC〕 invokes
doc:repeat-complex-command, you will see a Lisp form of the previous /interactive/
action you performed. You can press 〔RET〕 to repeat that command, or, more
likely, to convert your actions to Lisp code for a personal function.

This is a super neato way to get Lisp from your actions.
Conversely, use 〔M-: 〕 to evaluate any Lisp you have in-hand 😉

badge:Emacs|is_so_cool|informational||gnu-emacs.
#+end_details

Just as there is doc:defun for “def”ining “fun”ctions and doc:defmacro for
“def”ining “mac”ros, there is also doc:org-deflink for “def”ining “link”s for
“O”rg, and it behaves similar to them.

However, there are usually multiple ways to define things ---e.g., macros are
code-valued functions defined with doc:cl-defun. Indeed, Org links are popularly
defined using doc:org-link-set-parameters ---which, unlike doc:org-deflink, is not
consistent with doc:defun--- and so let's take a look at it first.

*** A comprehensive example of doc:org-link-set-parameters and doc:org-link-parameters
    :PROPERTIES:
    :CUSTOM_ID: A-comprehensive-example-of-doc-org-link-set-parameters-and-doc-org-link-parameters
    :END:

 Use src_emacs-lisp[:exports code]{(org-link-set-parameters params)} to add a new
 link type ---an older obsolete method is doc:org-add-link-type.  The list of all
 supported link types is doc:org-link-parameters; its documentation identifies
 the possibilities for =params=.

  Let's produce an example link type, then discuss its code.

  Intended usage:
  Raw use example:salam and descriptive, using ‘example’ link type ^_^
  https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/example_link.png

  # The “(ref:𝓍𝓍𝓍)” declarations are for line number referencing and not
  # part of the Lisp code needed to produce the example link type.
  # Consult the HTML/PDF rendition of this file or tangle the block below.
  # #
 #+name: startup-code
  #+begin_src emacs-lisp -n -r :tangle no
(org-link-set-parameters
  ;; The name of the new link type, usage: “example:label”
  "example"  (ref:extype)

  ;; When you click on such links, “let me google that for you” happens
  :follow (lambda (label) (browse-url (concat "https://lmgtfy.com/?q=" label))) (ref:exfollow)

  ;; Upon export, make it a “let me google that for you” link
  :export (lambda (label description backend)     (ref:exexport)
            (format (pcase backend
                      ('html "<a href=\"%s\">%s</a>")
                      ('latex "\\href{%s}{%s}")
                      (_ "I don’t know how to export that!"))
                    (concat "https://lmgtfy.com/?q=" label)
                    (or description label)))

  ;; These links should *never* be folded in descriptive display;
  ;; i.e., “[[example:lable][description]]” will always appear verbatim
  ;; and not hide the first pair […].
  ;; :display 'full (ref:exdisplay)

  ;; The tooltip alongside a link
  :help-echo (lambda (window object position)   (ref:exhelpecho)
               (save-excursion
                 (goto-char position)
                 (-let* (((&plist :path :format :raw-link :contents-begin :contents-end)
                          (cadr (org-element-context)))
                         ;; (org-element-property :path (org-element-context))
                         (description
                          (when (equal format 'bracket)
                            (copy-region-as-kill contents-begin contents-end)
                            (substring-no-properties (car kill-ring)))))
                   (format "“%s” :: Let me google “%s” for you -__- %s and %s"
                          raw-link (or description raw-link)))))

  ;; How should these links be displayed
  :face '(:foreground "red" :weight bold    (ref:exface)
          :underline "orange" :overline "orange")

  ;; Any special keybindings when cursour is on this link type?
  ;; On ‘example:’ links, C-n/p to go to the next/previous such links.
 :keymap (let ((map (copy-keymap org-mouse-map)))
           ;; Populate the keymap
           (define-key map (kbd "C-p")
             (lambda () (interactive) (re-search-backward "example:" nil t)))
           (define-key map (kbd "C-n")
             (lambda () (interactive) (re-search-forward "example:" nil t)))
           ;; Return the keymap
           map))
  #+end_src

  #+RESULTS: startup-code
  : org-osbe-html-export-preserving-whitespace





  + Line (extype) ="example"= :: Add a new =example= link type.
    - If the type already exists, update it with the given arguments.

    The syntax for a raw link is =example:path=
    and for the bracketed descriptive form ~[[example:path][description]]~.

    - Some of my intended uses for links including colouring text and doing
      nothing else, as such the terminology ‘path’ is not sufficiently generic and
      so I use the designation ‘label’ instead.

  + Line (exfollow) =:follow= :: What should happen when a user clicks on such links?

    This is a function taking the link path as the single argument and does
    whatever is necessary to “follow the link”, for example find a file or display
    a message. In our case, we open the user's browser and go to a particular URL.

  + Line (exexport) =:export= :: How should this link type be exported to HTML, LaTeX, etc?

    This is a three-argument function that formats the link according to the given
    backend, the resulting string value os placed literally into the exported
    file. Its arguments are:

    1. =label= ⇒ the path of the link, the text after the link type prefix
    2. =description= ⇒ the description of the link, if any
    3. =backend= ⇒ the export format, a symbol like =html= or =latex= or =ascii=.

    In our example above, we return different values depending on the =backend=
    value.

    - If =:export= is not provided, default Org-link exportation happens.

  + Line (exdisplay) =:display= :: Should links be prettily folded away when a description
    is provided?

  + Line (exhelpecho) =:help-echo= :: What should happen when the user's mouse is over
    the link?

    This is *either a string or a string-valued function* that takes the current
    window, the current buffer object, and its position in the current window.

    In our example link, we go to the position of the object, destructure the Org
    link's properties using ~-let~, find the description of the link, if any, then
    provide a string based on the link's path and description.

    #+begin_details The general textual property ‘help-echo’
    We may use ~help-echo~ to attach tooltips to arbitrary text in a file, as
    follows. I have found this to be useful in *metaprogramming* to have
    elaborated, generated, code shown as a tooltip attached to its named
    specification.
    #+begin_src emacs-lisp :tangle no
;; Nearly instantaneous display of tooltips.
(setq tooltip-delay 0)

;; Give user 30 seconds before tooltip automatically disappears.
(setq tooltip-hide-delay 300)

(defun tooltipify (phrase notification &optional underline)
  "Add a tooltip to every instance of PHRASE to show NOTIFICATION.

We only add tooltips to PHRASE as a standalone word, not as a subword.

If UNDERLINE is provided, we underline the given PHRASE so as to
provide a visual clue that it has a tooltip attched to it.

The PHRASE is taken literally; no regexp operators are recognised."
  (assert (stringp phrase))
  (assert (stringp notification))
  (save-excursion  ;; Return cursour to current-point afterwards.
    (goto-char 1)
    ;; The \b are for empty-string at the start or end of a word.
    (while (search-forward-regexp (format "\\b%s\\b" (regexp-quote phrase))
                                  (point-max) t)
      ;; (add-text-properties x y ps)
      ;; ⇒ Override properties ps for all text between x and y.
      (add-text-properties (match-beginning 0)
                           (match-end 0)
                           (list 'help-echo (s-trim notification)))))
 ;; Example use
(tooltipify
  "Line"
  "A sequential formatation of entities or the trace of a particle in linear motion")
    #+end_src

    We will use the tooltip doc:documentation later on ^_^

  Useful info on tooltips:
  + Changing text properties ---GNU
  + Tooltips on text in Emacs ---Kitchin
  + Getting graphical feedback as tooltips in Emacs ---Kitchin
  + Defining new tooltips in Emacs ---Stackoverflow

    #+end_details

  + Line (exface) =:face= :: What textual properties do these links possess?

    This is *either a face or a face-valued function* that takes the current link's
    path label as the only argument. That is, we could change the face according
    to the link's label ---which is what we will do for the =color= link type as in
    =[[color:brown][hello]]= will be rendered in brown text.

    - If ~:face~ is not provided, the default underlined blue face for Org links is used.
    - Learn more about faces!

  + More :: See =org-link-parameters= for documentation on more parameters.

*** Define links as you define functions: doc:org-deflink
    :PROPERTIES:
    :CUSTOM_ID: NEW-org-deflink
    :END:

 For export purposes, an Org link can be thought of as a string-valued function
 whose inputs are the link's label, description, and the export backend.  Since
 the input arguments are fixed, the ~org-deflink~ interface is similar to ~cl-defun~ in
 that it takes a name, (no input arguments), an optional docstring, and a body
 which may make use of (the unchanging input) names ~o-label, o-description,
 o-backend~. Moreover, after the documentation string, it may take an optional
 vector of display settings: Org links can be declared to look aesthetically
 pleasing within Emacs and to behave (via clicks/hovers/key-bindings) in
 meaningful ways.

 #+attr_html: :width 100% :height 100%
 https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/org-deflink.png

 Here is a minimal working example.  After evaluating this, in an Org buffer,
 phrases such as ~shout:hello~ will (1) be shown in bold red, (2) have a hover
 tooltip that shows the documentation of the link /and/ an HTML export preview, and
 (3) the HTML export of the Org buffer will render the label ~hello~ as capitalised
 red text.
 #+begin_src emacs-lisp :tangle no
(org-deflink shout
  "Capitalise the link description, if any, otherwise capitalise the label.

The link text appears as red bold in both Emacs and in HTML export."
  [:face '(:foreground "red" :weight bold)]
  (format "<span style=\"color:red\"> %s </span>"
          (upcase (or o-description o-label))))
 #+end_src
 :Example_uses:

 angle <shout: hello    world budo!>

 bracket hello world!

 plain shout:hola

 shout: hello wolrd

 :End:

 #+begin_details A parent keymap inherited by org-deflink keymaps
 #+begin_src emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; We define a parent keymap that org-deflink keymaps inherit from.
;; We also define a few useful functions that we then bind to this parent map.

(defvar org-special-block-extras-mode-map (make-keymap)
  "A keymap of actions, on link types, that is inherited by all `org-deflink' link keymaps.

To learn about keymap inheritance, run:  C-h i m elisp RETURN m Inheritance and Keymaps RETURN.

This keymap has the following bindings setup:

    (define-key org-special-block-extras-mode-map (kbd \"C-n\") #'org-this-link-next)
    (define-key org-special-block-extras-mode-map (kbd \"C-p\") #'org-this-link-previous)
    (define-key org-special-block-extras-mode-map (kbd \"C-h\") #'org-this-link-show-docs)

The use of `C-n' and `C-p' may be a nuisance to some users, since they override `forward-line'
and `previous-line' when the cursor is on an org-link type. As such, place something like the following
in your initialisation file.

    ;; Use  C-c C-f  to move to the next link of the same link-type as the one under the cursor
    (define-key org-special-block-extras-mode-map (kbd \"C-c C-f\") #'org-this-link-next)

Alternatively, if you don't find much value in these basic bindings, you can remove them all:

    ;; Disable basic org-special-block-extras link keybindings
    (setcdr org-special-block-extras-mode-map nil)

    ;; Or, remove a single binding
    (define-key org-special-block-extras-mode-map (kbd \"C-n\") nil)")

(defvar org-special-block-extras-mode-map--link-keymap-docs nil
  "An alist referencing key bindings for Org links; used in `org-this-link-show-docs'.")

(defun org-link-at-point ()
  "Get the Org link type at point, with suffix colon."
  (interactive)
  (let ((working-line (line-number-at-pos)))
    (save-excursion
      ;; Account for cursour being on anywhere on the links “name:key”.
      (backward-word 2)
      (unless (= working-line (line-number-at-pos))
        (goto-line working-line))
      (let* ((here-to-eol (buffer-substring-no-properties (point) (point-at-eol)))
             ;; E.g., “kbd:”, the name part of an Org link
             (link-name (cl-second (s-match "\\([^ ]+:\\).+" here-to-eol))))
        link-name))))

(defun org-this-link-next ()
  "Go to the next Org link that is similar to the link at point."
  (interactive)
  (re-search-forward (org-link-at-point) nil t))
(defun org-this-link-previous ()
  "Go to the previous Org link that is similar to the link at point."
  (interactive)
  (re-search-backward (org-link-at-point) nil t))
(defun org-this-link-show-docs ()
  "Show documentation for the Org link at point in a read-only buffer.

                     Press ‘q’ to kill the resulting buffer and window."
  (interactive)
  (let* ((link (s-chop-suffix ":" (org-link-at-point)))
         (msg (ignore-errors
                (concat
                 (documentation (intern (format "org-link/%s" link)))
                 "\nKEY BINDINGS:\n"
                 "\nUnless indicated below otherwise..."
                 "\n\tC-h: Shows this helpful message buffer"
                 "\n\tC-n/C-p on the link to jump to next/previous links of this type;"
                 "\n\tC-c C-x C-n/p for moving between arbitrary link types.\n\n"
                 (pp-to-string
                  (cdr (assoc link org-special-block-extras-mode-map--link-keymap-docs))))))
         ;; i.e., insist on displaying in a dedicated buffer
         (max-mini-window-height 0))
    (display-message-or-buffer msg)
    (switch-to-buffer-other-window "*Message*")
    (rename-buffer (format "Help: Org Link “%s”" link))
    (read-only-mode)
    (local-set-key "q" #'kill-buffer-and-window)
    (message "Read-only; “q” to kill buffer and window.")))

(define-key org-special-block-extras-mode-map (kbd "C-n") #'org-this-link-next)
(define-key org-special-block-extras-mode-map (kbd "C-p") #'org-this-link-previous)
(define-key org-special-block-extras-mode-map (kbd "C-h") #'org-this-link-show-docs)
#+end_src
#+end_details

 #+begin_details Implementation of org-deflink
#+begin_src emacs-lisp
(cl-defmacro org-deflink
    (name &optional docstring display &rest body)
  "Make a new Org-link NAME that exports using form BODY.

Since Org links are essentially string-valued functions,
a function ‘org-link/NAME’ is created.

DOCSTRING is optional; it is visible with
   (documentation 'org-link/NAME)

BODY is a string-valued expression, that may make use of the names
o-label, o-description, o-backend. The final one refers to the export
backend, such as 'html or 'latex. The first two are obtained from uses:

   o-description

In particular, the use case “name:o-label” means that o-description is nil.

---------------------------------------------------------------------------

Example use:

   ;; In a Lisp buffer, press “C-x C-e” to load this definition
   (org-deflink shout (upcase (or o-description o-label)))

   ;; In an Org-buffer, press “C-c C-e h o” to see how this exports
   <shout: hello world!>

   ;; Or using the bracket format
   hello world!
   shout: hello world!

   ;; or using the plain format
   shout:hello_world

Here is a more complex, involved, example that makes use of
‘:let’ for local declarations. For instance, “define:hello”
renders as the word “hello” with a tooltip defining the word; the
definition is obtained from the command line tool ‘wn’.

  (org-deflink define
    \"Define the given word using WordNet, along with synonyms and coordinate terms.\"
    [:let (definition (shell-command-to-string (format \"wn %s -over -synsn -coorn\" o-label)))
     :help-echo definition]
    (--> definition
      (s-replace-regexp \"\\\\\\\"\" \"''\" it) ;; The presence of ‘\\\"’ in tooltips breaks things, so omit them.
      (s-replace-regexp \"\\n\" \"<br>\" it)
      (format \"<abbr class=\\\"tooltip\\\" title=\\\"%s\\\">%s</abbr>\" it o-label)))

For HTML tooltips, see `org-osbe-html-export-preserving-whitespace'.

More generally, org-special-block-extra's “doc” link type
supports, in order of precedence: User definitions, Emacs Lisp
documentation of functions & variables, and definitions of
English words. For example, “doc:existential_angst” for an entry
‘existential_angst’ whose associated documentation-glossary is
user-defined in a ‘#+documentation’ Org-block, or
“doc:thread-first” for the Emacs Lisp documentation of the
function `thread-first', or “doc:user-mail-address” for the Emacs
Lisp documentation of the variable `user-mail-address', or
“doc:hello” for the definition of the English word ‘hello’.

DISPLAY is a vector consisting of key-value pairs that affects how the link
is displayed in Emacs Org buffers. The keys are as follows.

+ :help-echo is a string-valued expression of the tooltip that should accompany
  the new link in Org buffers. It has access to o-format being one of ‘plain’,
  ‘angle’, ‘bracket’ which indicates the format of the link, as shown above.
  It also has access to o-label and o-description.

  By default, the tooltip is the link name followed by the documentation
  of the link, and, finally, the HTML export of the link.
  That way, upon hover, users can visually see the link contents,
  know what/how the link exports, and actually see the HTML export.

  That is to say, for the ‘shout’ example aboce, the default display is essentially:
  [:help-echo (org-link/shout o-label o-description 'html)]

  You may want to add the following to your Emacs init file:

    ;; Nearly instantaneous display of tooltips.
    (setq tooltip-delay 0)
    ;; Give user 30 seconds before tooltip automatically disappears.
    (setq tooltip-hide-delay 300)

+ :face specifies how should these links be displayed within Emacs.
   It is a list-valued expression.
   As usual, it may make use of O-LABEL (but O-DESCRIPTION has value nil).
   Example:
               :face '(:underline \"green\")

   See https://www.gnu.org/software/emacs/manual/html_node/elisp/Face-Attributes.html

+ [:display 'full] if you do not want bracket links to be
  folded away in Org buffers; i.e., “Y” does not render as just “Y”.

+ :follow is a form that is executed when you click on such links; e.g., to open
   another buffer, browser, or other action. It makes use of (an implicit argument) ‘o-label’.
   Be aware that ‘o-label’ is a string that may contain spaces; e.g., when the action is to open
   a URL in a browser.

   If you are in need of providing similar, related, actions on a single link
   then your :follow can condition on the current prefix argument via ‘o-prefix’
   (which is essentially `current-prefix-arg').
   For instance, a user presses “C-u RET” on your link to do one thing
   but “C-u 72 RET” to do another action.

+ :keymap is an alternating list of keys and actions to be
  performed when those keys are pressed while point is on the link.
  For example:
      [:keymap (C-h (message-box \"hola\"))]

  By default, C-n and C-p are for moving to next and previous occruances of the same link type.

+ :let is a list of alternating variable symbol name and value, which are then used to form
  a concrete `let*' clause. This is useful for introducing local variables for use in the DISPLAY
  as well as in the CONTENTS. Such local declarations may make use of O-LABEL and O-DESCRIPTION, as usual."
  (cl-destructuring-bind (docstring display body)
      (lf-extract-optionals-from-rest docstring #'stringp
                                      display   #'vectorp
                                      body)
    (setq display (seq--into-list display))
    (let ((org-link/NAME (intern (format "org-link/%s" name)))
          (navigation "Press “C-h” to see possible actions on this link type.")
          (lets (cl-loop for (variable value)
                      on (cl-getf display :let)
                      by #'cddr
                      collect (list variable value))))
      `(progn
       ;; Declare the underlying function and documentation
       (cl-defun ,org-link/NAME ;; function name
           (o-label o-description o-backend)         ;; function args
           ;; new function documentation
           ,docstring
           ;; function body
           (let* ,lets ,@body))
       ;; Construct the Org-link
       (org-link-set-parameters
        ,(format "%s" name)
        :export (quote ,org-link/NAME)
        ;; How should these links be displayed?
        ;; (We augment the namespace with the missing o-description that local variables may be using.)
        :face (lambda (o-label)  (let (o-description) (let* ,lets ,(cl-getf display :face))))
        ;; When you click on such links, what should happen?
        ;; (We augment the namespace with the missing o-description that local variables may be using.)
        :follow (lambda (o-label o-prefix) (let (o-description) (let* ,lets ,(cl-getf display :follow))))
         ;; These links should *never* be folded in descriptive display;
        ;; i.e., “description” will always appear verbatim
        ;; and not hide the first pair […].
        :display (cl-the symbol ,(cl-getf display :display)) ;; e.g.,: 'full
        ;; Any special keybindings when cursour is on this link type?
        ;; On ‘NAME:’ links, C-n/p to go to the next/previous such links.
        :keymap (let ((o-keymap (copy-keymap org-mouse-map))
                      (pattern (format "%s:" (quote ,name))))

                  ;; If this Org-link has additional key bindings, then save
                  ;; them in an alist for reference in `org-this-link-show-docs'.
                  (when (quote ,(cl-getf display :keymap))
                    (push (cons (format "%s" (quote ,name)) (quote ,(cl-getf display :keymap)))
                          org-special-block-extras-mode-map--link-keymap-docs))

                  ;; Let's inherit some possibly useful key bindings.
                  (set-keymap-parent o-keymap org-special-block-extras-mode-map)

                  ;; Populate the keymap
                  (cl-loop for (key action) on (quote ,(cl-getf display :keymap))
                           by #'cddr
                           do (define-key o-keymap (kbd (format "%s" key))
                                `(lambda () (interactive) ,action)))
                  ;; Return the keymap
                  o-keymap)
        ;; The tooltip alongside a link
        :help-echo (lambda (window object position)
                     (save-excursion
                       (goto-char position)
                       (-let* (((&plist :path :format :contents-begin :contents-end)
                                (cadr (org-element-context)))
                               (org-format format)
                               (o-label path)
                               (o-description
                                (when (equal format 'bracket)
                                  (copy-region-as-kill contents-begin contents-end)
                                  (substring-no-properties (car kill-ring)))))
                         (or (let* ,lets ,(cl-getf display :help-echo))
                             (format "%s:%s\n\n%s\nHTML Export:\n\n%s"
                                     (quote ,name)
                                     (or o-description o-label)
                                     ,(concat (or docstring "") "\n\n" navigation "\n")
                                     (,org-link/NAME o-label o-description 'html)))))))
        ;; Return value is the name of the underlying function.
        ;; We do this to be consistent with `defun'.
        (quote ,org-link/NAME)))))
 #+end_src

 # shout:hi

 Let's have some sanity tests...
 #+begin_src emacs-lisp :tangle tests.el :comments link
(org-deflink shout
  "Capitalise the link description, if any, otherwise capitalise the label.

The link text appears as red bold in both Emacs and in HTML export."
  [:face '(:foreground "red" :weight bold)
   ;; :help-echo (org-link/shout o-label o-description 'html)
   :display 'full
   :keymap (C-m (message-box "hola"))
   :follow (message-box "%s and %s" pre current-prefix-arg)
   ]
  (format "<span style=\"color:red\"> %s </span>"
          (upcase (or o-description o-label))))

(deftest "org-deflink makes documented functions"
  [org-deflink]
  (⇝ (documentation #'org-link/shout)
     "Capitalise the link description, if any, otherwise capitalise the label.

     The link text appears as red bold in both Emacs and in HTML export."))

(deftest "org-deflink works as expected, plain links"
  [org-deflink]
  (should (not (null (symbol-function 'org-link/shout))))
  (⇝ (⟰ "shout:hello")
     "<p> <span style=\"color:red\"> HELLO </span></p>"))

(deftest "org-deflink works as expected, bracket links"
  [org-deflink]
  (⇝ (⟰ "shout:hello")
     "<p> <span style=\"color:red\"> HELLO </span></p>")
  (⇝ (⟰ "world!")
     "<p> <span style=\"color:red\"> WORLD! </span></p>"))

(deftest "org-deflink works as expected, angle links"
  [org-deflink]
  (⇝ (⟰ "<shout: hello world!>")
     "<p> <span style=\"color:red\"> HELLO WORLD! </span></p>"))
 #+end_src

 #+end_details


*pink:Exercise* Here's a useful link we might want: ~melpa:𝒳~ produces a nice badge
for the package 𝒳 that links to the associated Melpa page and shows the version
number of the package, if possible/convenient. For instance,
~melpa:org-special-block-extras~ and ~<melpa:s>~ become
melpa:org-special-block-extras and <melpa:s>.

#+begin_details "One possible arcane implementation"

#+begin_src emacs-lisp
(org-deflink melpa
 "Produce a Melpa badge for a given pacakge O-LABEL, which links to the Melpa page.
We try to get the package's version from a constant “⟨O-LABEL⟩-version” if it exists."
 [:face '(:box "purple" :foreground "purple")]
 (format (concat "<a href=\"https://melpa.org/#/%s\">"
                 "<img alt=\"MELPA\" src=\"https://img.shields.io/badge/%s-%s-green?logo=Gnu-Emacs\"></img>"
                 "</a>")
         o-label
         (s-replace "_" "__" (s-replace "-" "--" o-label)) ;; shields.io conventions
         (or (ignore-errors (eval (intern (concat o-label "-version")))) "Melpa")))
#+end_src

#+end_details

**** COMMENT Example links...               :TestingPurposes:Already_in_docs:
     :PROPERTIES:
     :CUSTOM_ID: COMMENT-Example-links
     :END:

  #+begin_src emacs-lisp
(org-deflink define
  "Define the given word using WordNet, along with synonyms and coordinate terms."
  [:help-echo (shell-command-to-string (format "wn %s -over -synsn -coorn" o-label))]
  (--> o-label
    (shell-command-to-string (format "wn %s -over -coorn" it))
    (s-replace-regexp "\\\"" "''" it) ;; The presence of ‘\"’ in tooltips breaks things, so omit them.
    (s-replace-regexp "\n" "<br>" it)
    (format "<abbr class=\"tooltip\" title=\"%s\">%s</abbr>" it o-label)))

#+end_src

#+begin_src emacs-lisp
(org-deflink shout
  "Capitalise the link description, if any, otherwise capitalise the label.

The link text appears as red bold in both Emacs and in HTML export."
  [:face '(:foreground "red" :weight bold)]
  (format "<span style=\"color:red\"> %s </span>"
          (upcase o-label)))
  #+end_src


# orange:Going forward it would be nice to make use of doc:org-edit-special to
# edit the various link types introduced in this article.
** The Core Utility: ~defblock~ and friends
   :PROPERTIES:
   :CUSTOM_ID: The-Core-Utility-defblock-and-friends
   :END:


#+latex_header: \newunicodechar{≈}{\ensuremath{\approx}}
#+latex_header: \newunicodechar{⟦}{\ensuremath{[\![}}
#+latex_header: \newunicodechar{⟧}{\ensuremath{]\!]}}
#+latex_header: \newunicodechar{★}{\ensuremath{\star}}
#+latex_header: \newunicodechar{⇨}{\ensuremath{\Rightarrow}}
#+latex_header: \newunicodechar{⇦}{\ensuremath{\Leftarrow}}
#+latex_header: \newunicodechar{↦}{\ensuremath{\mapsto}}

To have a unified, and pleasant, interface for declaring new blocks and links,
we take the following approach:

0. [@0] ( /Fuse/ the process of link generation and special block support into
   one macro,  defblock which is like doc:defun. )

1. The user writes as string-valued function named 𝒳, possibly with arguments,
   that has access to a ~contents~ and ~backend~ variables.

   :Posterity_OLD_org_export_parse:

(defun org-export (x)
  "Wrap the given X in an export block for the current backend."
  (format "\n#+begin_export %s \n%s\n#+end_export\n"
          (if (equal o--current-backend 'reveal)
              'html
            o--current-backend)
          x))

(defun org--org-parse (x)
  "This should ONLY be called within an ORG-EXPORT call."
   (format "\n#+end_export\n%s\n#+begin_export %s\n" x
           (if (equal 'reveal o--current-backend)
               'html
             o--current-backend)))

    :End:

   #+begin_details ‘defblock’ Implementation
 #+begin_src emacs-lisp
(defvar org--supported-blocks nil
  "Which special blocks, defined with DEFBLOCK, are supported.")

(cl-defmacro org-defblock
  (name kwds &optional link-display docstring &rest body)
  "Declare a new special block, and link, in the style of DEFUN.

A full featured example is at the end of this documentation string.

This is an anaphoric macro that provides export support for
special blocks *and* links named NAME. Just as an Org-mode
src-block consumes as main argument the language for the src
block, our special blocks too consume a MAIN-ARG; it may be a
symbol or a cons-list consisting of a symbolic name (with which
to refer to the main argument in the definition of the block)
followed by a default value, then, optionally, any information
for a one-time setup of the associated link type.

The main arg may be a sequence of symbols separated by spaces,
and a few punctuation with the exception of comma ‘,’ since it is
a special Lisp operator. In doubt, enclose the main arg in
quotes.

Then, just as Org-mode src blocks consume key-value pairs, our
special blocks consume a number of KWDS, which is a list of the
form (key₀ value₀ … keyₙ valueₙ).

After that is an optional DOCSTRING, a familar feature of DEFUN.
The docstring is displayed as part of the tooltip for the
produced link type.

Finally, the BODY is a (sequence of) Lisp forms ---no progn
needed--- that may refer to the names BACKEND and CONTENTS which
refer to the current export backend and the contents of the
special block ---or the description clause of a link.

CONTENTS refers to an Org-mode parsed string; i.e., Org-markup is
acknowledged.

In, hopefully, rare circumstances, one may refer to RAW-CONTENTS
to look at the fully unparsed contents.

Finally, this macro exposes two functions:
+ ORG-EXPORT: Wrap the argument in an export block for the current backend.
+ ORG-PARSE: This should ONLY be called within an ORG-EXPORT call,
             to escape text to Org, and out of the export block.

⇄ We use “@@html:⋯:@@” when altering CONTENTS, but otherwise use raw HTML *around* CONTENTS.
⇄ For example: (format \"<div>%s</div>\" (s-replace \"#+columnbreak:\" \"@@html:<hr>@@\" contents))

----------------------------------------------------------------------

The relationship between links and special blocks:

  [ [type:label][description]]
≈
   ,#+begin_type label
    description
   ,#+end_type

----------------------------------------------------------------------

Example declaration, with all possible features shown:

   ;; We can use variable values when defining new blocks
   (setq angry-red '(:foreground \"red\" :weight bold))

   (org-defblock remark
     (editor \"Editor Remark\" :face angry-red) (color \"red\" signoff \"\")
     \"Top level (HTML & LaTeX) editorial remarks; in Emacs they're angry red.\"
     (format (if (equal backend 'html)
               \"<strong style=\\\"color: %s;\\\">⟦%s:  %s%s⟧</strong>\"
               \"{\\color{%s}\\bfseries %s:  %s%s}\")
             color editor contents signoff))

   ;; Personalised defaults, without changing the definition, as Babel's for a src block of language remark.
   (setq org-babel-default-header-args:remark '((:editor . \"Jasim Jameson\") (:signoff . \"( Aim for success! )\")))

Three example uses:

    ;; ⟨0⟩ As a special blocks with arguments given.
    ,#+begin_remark Bobbert Barakallah :signoff \"Thank-you for pointing this out!\" :color green
    I was trying to explain that ${\large (n × (n + 1) \over 2}$ is always an integer.
    ,#+end_remark

    ;; ⟨1⟩ As a terse link, using default values for the args.
    ;;     Notice that Org-mode formatting is recoqgnised even in links.
    [ [remark:Jasim Jameson][Why are you taking about “$\mathsf{even}$” here?]]

    ;; ⟨2⟩ So terse that no editor name is provided.
    [ [remark:][Please improve your transition sentences.]]

    ;; ⟨★⟩ Unlike 0, examples 1 and 2 will have the default SIGNOFF
    ;; catenated as well as the default red color."
  ;; ⇨ The special block support
  ;;
  (add-to-list 'org--supported-blocks name) ;; global var

  ;; TODO: Relocate
  (defvar org--block--link-display nil
    "Association list of block name symbols to link display vectors.")

  ;; Identify which of the optional features is present...
  (cl-destructuring-bind (link-display docstring body)
      (lf-extract-optionals-from-rest link-display #'vectorp
                                      docstring    #'stringp
                                      body)
      `(progn
        (when ,(not (null link-display)) (push (cons (quote ,name) ,link-display) org--block--link-display))
       (list
      ,(org--create-defmethod-of-defblock name docstring (plist-get kwds :backend) kwds body)
       ;; ⇨ The link type support
      (eval (backquote (org-deflink ,name
                   ,(vconcat `[:help-echo (format "%s:%s\n\n%s" (quote ,name) o-label ,docstring)] (or link-display (cdr (assoc name org--block--link-display))))
                   ;; s-replace-all `((,(format "@@%s:" backend) . "") ("#+end_export" . "") (,(format "#+begin_export %s" backend) . ""))
                   (s-replace-regexp "@@" ""
                                     (,(intern (format "org-block/%s" name)) o-backend (or o-description o-label) o-label :o-link? t)))))))))

;; WHERE ...

(cl-defmethod org--create-defmethod-of-defblock ((name symbol) docstring backend-type (kwds list) (body list))
  "Helper method to produce an associated Lisp function for org-defblock.

+ NAME: The name of the block type.
+ DOCSTRING, string|null: Documentation of block.
+ KWDS: Keyword-value pairs
+ BODY: Code to be executed"
  (cl-assert (or (stringp docstring) (null docstring)))
  (cl-assert (or (symbolp backend-type) (null backend-type)))

  (let ((main-arg-name (or (cl-first kwds) 'main-arg))
        (main-arg-value (cl-second kwds))
        (kwds (cddr kwds)))
       ;; Unless we've already set the docs for the generic function, don't re-declare it.
       `(progn ;; if ,(null body)
         (cl-defgeneric ,(intern (format "org-block/%s" name)) (backend raw-contents &rest _)
           ,docstring)

       (cl-defmethod ,(intern (format "org-block/%s" name))
     ((backend ,(if backend-type `(eql ,backend-type) t))
      (raw-contents string)
      &optional
      ,main-arg-name
      &rest _
      &key (o-link? nil) ,@(--reject (keywordp (car it)) (-partition 2 kwds))
      &allow-other-keys)
     ,docstring
     ;; Use default for main argument
     (when (and ',main-arg-name (s-blank-p ,main-arg-name))
       (--if-let (org--header-arg-of ',name ,(intern (format ":%s" main-arg-name)))
           (setq ,main-arg-name it)
         (setq ,main-arg-name ,main-arg-value)))

     (cl-letf (((symbol-function 'org-export)
                 (lambda (x) "Wrap the given X in an export block for the current backend."
                   (if o-link? x (format "#+begin_export %s \n%s\n#+end_export" backend x))))
         ((symbol-function 'org-parse)
          (lambda (x) "This should ONLY be called within an ORG-EXPORT call."
            (if o-link? x (format "\n#+end_export\n%s\n#+begin_export %s\n" x backend)))))

       ;; Use any headers for this block type, if no local value is passed
       ,@(cl-loop for k in (mapcar #'car (-partition 2 kwds))
                  collect `(--when-let (org--header-arg-of ',name ,(intern (format ":%s" k)))
                             (when (s-blank-p ,k)
                               (setq ,k it))))

       (org-export
        (let ((contents (org-parse raw-contents))) ,@body)))))))
  #+end_src

  #+RESULTS:
  : org-defblock---support-link-type

# (fmakunbound 'org--org-parse)

# Going forward,
Going forward, it would be nice to have a set of switches that apply to all
special blocks. For instance, ~:ignore~ to simply bypass the user-defined
behaviour of a block type, and ~:noexport~ to zero-out a block upon export.  These
are super easy to do ---just need a few minutes to breath.  It may also be
desirable to provide support for drawers ---just as we did to ‘fuse’ the
block-type and link-type approaches used here into one macro.

 #+end_details

2. [@2] We tell Org to please look at all special blocks
   #+begin_src org :tangle no
,#+begin_𝒳 main-arg :key₀ value₀ … :keyₙ valueₙ
contents
,#+end_𝒳
   #+end_src
   Then, before export happens, to replace all such blocks
   with the /result/ of calling the user's 𝒳 function; i.e.,
   replace them by, essentially,
   #+begin_src emacs-lisp :tangle no
(𝒳 main-arg :key₀ value₀ … :keyₙ valueₙ :o-contents contents)
#+end_src

   #+begin_details Implementing the hooking mechanism

The mechanism that rewrites your source...
 #+begin_src emacs-lisp
(defun org--pp-list (xs)
  "Given XS as (x₁ x₂ … xₙ), yield the string “x₁ x₂ … xₙ”, no parens.
  When n = 0, yield the empty string “”."
  (s-chop-suffix ")" (s-chop-prefix "(" (format "%s" (or xs "")))))

(defvar org--current-backend nil
  "A message-passing channel updated by
org--support-special-blocks-with-args
and used by DEFBLOCK.")

(defun org--support-special-blocks-with-args (backend)
  "Remove all headlines in the current buffer.
BACKEND is the export back-end being used, as a symbol."
  (setq org--current-backend backend)
  (let (blk-start        ;; The point at which the user's block begins.
        header-start ;; The point at which the user's block header & args begin.
        kwdargs          ;; The actual key-value arguments for the header.
        main-arg         ;; The first (non-keyed) value to the block.
        blk-column       ;; The column at which the user's block begins.
        body-start       ;; The starting line of the user's block.
        blk-contents         ;; The actual body string.
        ;; ⟨blk-start/column⟩#+begin_⟨header-start⟩blk main-arg :key₀ val ₀ … :keyₙ valₙ  ;; ⟵ ⟨kwdargs⟩
        ;; ⟨body-start⟩ body
        ;; #+end_blk
        )
  (cl-loop for blk in org--supported-blocks
        do (goto-char (point-min))
        (while (ignore-errors (re-search-forward (format "^\s*\\#\\+begin_%s" blk)))
          ;; MA: HACK: Instead of a space, it should be any non-whitespace, optionally;
          ;; otherwise it may accidentlly rewrite blocks with one being a prefix of the other!
          (setq header-start (point))
          ;; Save indentation
          (re-search-backward (format "\\#\\+begin_%s" blk))
          (setq blk-start (point))
          (setq blk-column (current-column))
          ;; actually process body
          (goto-char header-start)
          (setq body-start (1+ (line-end-position)))
          (thread-last
              (buffer-substring-no-properties header-start (line-end-position))
            (format "(%s)")
            read
            (--split-with (not (keywordp it)))
            (setq kwdargs))
          (setq main-arg (org--pp-list (car kwdargs)))
          (setq kwdargs (cadr kwdargs))
          (forward-line -1)
          (re-search-forward (format "^\s*\\#\\+end_%s" blk))
          (setq blk-contents (buffer-substring-no-properties body-start (line-beginning-position)))
          (kill-region blk-start (point))
          ;; TODO: Make the `main-arg' just be the first keyword arg. That is “begin_X main-value :keyₖ value-k” ≈ “begin_X :key₀ main-value :keyₖ value-k”.
          ;; This will simplify cases where this is no sense of a main-arg, such as org-demo, whose arg list starts with “nil nil” since there's no main-arg and its default is nil.
          ;; One consequence of this approach is that the first keyword arg is special, it's key can be omitted when it occurs first: “begin_X main-value” ≈ “begin_X :key₀ main-value”.
          (-let [val (eval `(,(intern (format "org-block/%s" blk))
                             (quote ,backend)
                             ,blk-contents
                             ,main-arg
                             ,@(--map (list 'quote it) kwdargs)))]
            ;; TODO: This `margin` specific logic should not be here.
            (when (or (equal blk 'margin) (equal blk 'tooltip)) (setq val (format "@@html: %s@@" (s-replace "@" "@" (s-chop-prefix "#+begin_export html \n" (s-chop-suffix "\n#+end_export" val))))))
            (insert val))
          ;; See: https://github.com/alhassy/org-special-block-extras/issues/8
          ;; (indent-region blk-start (point) blk-column) ;; Actually, this may be needed...
          ;; (indent-line-to blk-column) ;; #+end...
          ;; (goto-char blk-start) (indent-line-to blk-column) ;; #+begin...
          ;; the --map is so that arguments may be passed
          ;; as "this" or just ‘this’ (raw symbols)
      ))))
#+end_src

Let's have some sanity tests...
#+begin_src emacs-lisp :tangle old_tests.el
(deftest "pp-list works as desired"
  (should (equal "1 2 3 4 5"
                 (org--pp-list '(1 2 3 4 5))))
  (should (equal "1"
                 (org--pp-list '(1))))
  (should (equal ""
                 (org--pp-list nil))))

;; Using propcheck, we run this test on /arbitrary/ buffer contents.
(deftest "No supported blocks means buffer is unchanged"
  :tags '(core)
  (let* (org--supported-blocks
         (propcheck-seed (propcheck-seed))
         (buf (propcheck-generate-string nil)))
    (should (equal buf
                   (with-temp-buffer
                     (insert buf)
                     (org--support-special-blocks-with-args 'html)
                     (buffer-string))))))

(deftest "Constant blocks preserve indentation/enumeration"
  :expected-result :failed
  :tags '(core)
  (org-defblock go nil "doc" "hello") ;; Constantly “hello”
  (should (equal
"
  1. item one
  2. item two
     ,#+begin_export html
hello
,#+end_export
  3. item three"
    (with-temp-buffer
      (insert
  "
  1. item one
  2. item two
     ,#+begin_go
  world
  ,#+end_go
  3. item three")
      (org--support-special-blocks-with-args 'html)
      (buffer-string)))))

(deftest "Constant blocks export to LaTex preserves indentation/enumeration"
(should (equal
"\\begin{enumerate}
\\item item one
\\item item two
hello
\\item item three
\\end{enumerate}
"
(org-export-string-as
  "
  1. item one
  2. item two
     ,#+begin_go
  world
  ,#+end_go
  3. item three"
  'latex :body-only-please))))


(deftest "Constant blocks export to HTML preserves indentation/enumeration"
(should (equal
"<ol class=\"org-ol\">
<li>item one</li>
<li><p>
item two
</p>
hello</li>
<li>item three</li>
</ol>
"
(org-export-string-as
  "
  1. item one
  2. item two
     ,#+begin_go
  world
  ,#+end_go
  3. item three"
  'html :body-only-please))))


(deftest "Identity blocks preserve indentation/enumeration"
    :expected-result :failed
  :tags '(core)
  (org-defblock id nil "doc" contents)
  (should (equal
"
  1. item one
  2. item two
     ,#+begin_export html

     ,#+end_export
     world

     ,#+begin_export html

     ,#+end_export
  3. item three"
    (with-temp-buffer
      (insert
  "
  1. item one
  2. item two
     ,#+begin_id
  world
  ,#+end_id
  3. item three")
      (org--support-special-blocks-with-args 'html)
      (buffer-string)))))

(deftest "Identity blocks export to LaTex preserves indentation/enumeration"
    :expected-result :failed
(org-defblock id nil "doc" contents)
(should (equal
"\\begin{enumerate}
\\item item one
\\item item two

world
\\item item three
\\end{enumerate}
"
(org-export-string-as
  "
  1. item one
  2. item two
     ,#+begin_id
  world
  ,#+end_id
  3. item three"
 'latex :body-only-please))))

(deftest "Identity blocks export to HTML preserves indentation/enumeration"
    :expected-result :failed
(org-defblock id nil "doc" contents)
(should (equal

"<ol class=\"org-ol\">
<li>item one</li>
<li><p>
item two
</p>

<p>
world
</p></li>
<li>item three</li>
</ol>
"
(org-export-string-as
  "
  1. item one
  2. item two
     ,#+begin_id
  world
  ,#+end_id
  3. item three"
 'html :body-only-please))))
#+end_src

When you enable the ~org-special-block-extras~ mode, it is activated...
#+begin_src emacs-lisp :noweb-ref enable-mode :tangle no
;; https://orgmode.org/manual/Advanced-Export-Configuration.html
(add-hook 'org-export-before-parsing-hook 'org--support-special-blocks-with-args)
 #+end_src

 #+RESULTS:
 | org--support-special-blocks-with-args | org-ref-acronyms-before-parsing | org-ref-glossary-before-parsing |

When you disable the ~org-special-block-extras~ mode, it is deactivated...
#+BEGIN_SRC emacs-lisp :noweb-ref disable-mode :tangle no
(remove-hook 'org-export-before-parsing-hook 'org--support-special-blocks-with-args)
#+END_SRC

#+RESULTS:
| org-ref-acronyms-before-parsing | org-ref-glossary-before-parsing |

#+end_details

   #+begin_details ‘header-args’ Implementation
   Then:
 #+begin_src emacs-lisp
;; A NAME block takes its defaults as a src block of language NAME takes its header-args:
;; org-babel-default-header-args:NAME, #+property: header-args:NAME, :header-args:NAME: drawers,
;; and #+header: lines; see org-block-header-args.el.
(setq org-babel-default-header-args:remark '((:editor . "Jasim Jameson")))
 #+end_src

#+end_details

   This interface is essentially that of Org's ~src~ blocks, with the ~main-arg~
   being the first argument to 𝒳 and the only argument not needing to be
   preceded by a key name ---it is done this way to remain somewhat consistent
   with the Org ~src~ interface. The user definition of 𝒳 decides on /how optional/
   the arguments actually are.

Perhaps an example will clarify things ...

*** Example: Jasim providing in-place feedback to Bobbert
    :PROPERTIES:
    :CUSTOM_ID: Example-Jasim-providing-in-place-feedback-to-Bobbert
    :END:

 Suppose we want to devise a simple special block for editors to provide
 constructive feedback to authors so that the feedback appears as top-level
 elements of the resulting exported file ---instead of comments that may
 accidentally not be handled by the author.

 In order to showcase the multiple bells and whistles of the system, the snippet
 below is twice as long than it needs to be, but it is still reasonably small and
 accessible.
 # Not anymore: ( The documentation string to ~defblock~ is mandatory. )
 #+begin_src emacs-lisp :tangle no
;; We can use variable values when defining new blocks
(setq angry-red '(:foreground "red" :weight bold))

;; This is our 𝒳, “remark”.
;; As a link, it should be shown angry-red;
;; it takes two arguments: “color” and “signoff”
;; with default values being "red" and "".
(org-defblock rremark
  (editor "Editor Remark" color "red" signoff "")
  (vector :face angry-red)
  "Top level (HTML & LaTeX) editorial remarks; in Emacs they're angry red."
  (format (if (equal backend 'html)
            "<strong style=\"color: %s;\">⟦%s:  %s%s⟧</strong>"
            "{\\color{%s}\\bfseries %s:  %s%s}")
          color editor contents signoff))

;; I don't want to change the definition, but I'd like to have the following as personalised defaults for the
;; “rremark” block, as Babel's are for a src block; links, which have no header line, take them too.
(setq org-babel-default-header-args:rremark '((:editor . "Jasim Jameson") (:signoff . "( Aim for success! )")))
 #+end_src

 #+RESULTS:
 | ((:editor . Jasim Jameson) (:signoff . ( Aim for success! ))) |

 _Example use_
 #+begin_example org :tangle no
The sum of the first $n$ natural numbers is $\sum_{i = 0}^n i = {n × (n + 1)
\over 2}$. Note that $n × (n + 1)$ is even.
[[rremark:Jasim Jameson][Why are you taking about “$\mathsf{even}$” here?]]
,#+begin_rremark Bobbert Barakallah :signoff "Thank-you for pointing this out!" :color green
I was trying, uh ...

Yeah, to explain that ${\large n × (n + 1) \over 2}$ is always an integer.
,#+end_rremark

Hence, we only need to speak about whole numbers.
[[rremark:][Then please improve your transition sentences.]]
 #+end_example

 _Resulting rendition_
 #+begin_quote
 The sum of the first $n$ natural numbers is $\sum_{i = 0}^n i = {n × (n + 1)
 \over 2}$. Note that $n × (n + 1)$ is even.
 Why are you taking about “$\mathsf{even}$” here?
 #+begin_rremark Bobbert Barakallah :signoff "Thank-you for pointing this out!" :color green
 I was trying, uh ...

 Yeah, to explain that ${\large n × (n + 1) \over 2}$ is always an integer.
 #+end_rremark
 Hence, we only need to speak about whole numbers.
 Then please improve your transition sentences.
 #+end_quote

 Notice that the result contains text ---the signoff message--- that the user
 Jasim did not write explicitly.

… Why the /stuttered/ ~rremark~? Because this package comes with a ~remark~ block that
has more bells and whistles … keep reading ;-)

 # For the Lisp
 #+name: startup-code
 #+begin_src emacs-lisp :exports none
;; This is our 𝒳, “remark”.
;; As a link, it should be shown angry-red;
;; it takes two arguments: “color” and “signoff”
;; with default values being "red" and "".
(org-defblock rremark
  (editor "Editor Remark" color "red" signoff "")
  [:face '(:foreground "red" :weight bold)]
  ; :please-preserve-new-lines
  "Top level (HTML & LaTeX) editorial remarks; in Emacs they're angry red."
  (format (if (equal backend 'html)
            "<strong style=\"color: %s;\">⟦%s: %s%s⟧</strong>"
            "{\\color{%s}\\bfseries %s:  %s%s}")
          color editor contents signoff))

;; I don't want to change the definition, but I'd like to have the following as personalised defaults for the
;; “rremark” block, as Babel's are for a src block; links, which have no header line, take them too.
(setq org-babel-default-header-args:rremark '((:editor . "Jasim Jameson") (:signoff . "( Aim for success! )")))
 #+end_src

** Modularity with ~thread-blockcall~
   :PROPERTIES:
   :CUSTOM_ID: modularity_with_thread-blockcall
   :END:

Since defblock let's us pretend block ---and link--- types are string-valued
functions, then one would expect that we can compose blocks /modularly/ as
functions compose. Somewhat analogously to doc:funcall and doc:thread-last, we
provide a macro thread-blockcall.

#+begin_box Example
#+begin_src emacs-lisp :tangle no
(thread-blockcall raw-contents
                  (box name)
                  (details (upcase name) :title-color "green")
#+end_src
=
#+begin_src C :tangle no
,#+begin_details NAME :title-color "green"
,#+begin_box name
contents
,#+end_box
,#+end_details
#+end_src
#+end_box

#+html: <br>
#+begin_details Implementation
First, we need to handle the case of one block…
#+begin_src emacs-lisp
(cl-defmacro org--blockcall (blk &optional main-arg &rest keyword-args-then-contents)
  "An anaologue to `funcall` but for blocks.

Usage: (blockcall blk-name main-arg even-many:key-values raw-contents)

One should rarely use this directly; instead use
`org-thread-blockcall'.
"
  `(concat "#+end_export\n" (,(intern (format "org-block/%s" blk))
    backend ;; defblock internal
    ; (format "\n#+begin_export html\n\n%s\n#+end_export\n" ,(car (last keyword-args-then-contents))) ;; contents
    ,@(last keyword-args-then-contents) ;; contents
    ,main-arg
    ,@(-drop-last 1 keyword-args-then-contents)) "\n#+begin_export"))
 #+end_src

 #+RESULTS:
 : org--blockcall

Using the above sequentially does not work due to the plumbing of
~defblock~, so we handle that plumbing below …
#+BEGIN_SRC emacs-lisp
(defmacro org-thread-blockcall (body &rest forms)
  "Thread text through a number of blocks.

BODY is likely to be ‘raw-contents’, possibly with user manipulations.

Each FORMS is of the shape “(block-name main-argument
:key-value-pairs)”

(thread-blockcall x)       = x
(thread-blockcall x (f a)) = (blockcall f a x)
(thread-blockcall x f₁ f₂) ≈ (f₂ (f₁ x))

The third is a ‘≈’, and not ‘=’, because the RHS contains
‘blockcall’s as well as massages the export matter
between conseqeuctive blockcalls.

A full example:

    (org-defblock nesting (name nil)
      \"Show text in a box, within details, which contains a box.\"

      (org-thread-blockcall raw-contents
                        (box name)
                        (details (upcase name) :title-color \"green\")
                        (box (format \"⇨ %s ⇦\" name) :background-color \"blue\")
                        ))
"
  (if (not forms) body
     `(-let [result (org--blockcall ,@(car forms) ,body)]
    ,@(cl-loop for b in (cdr forms)
          collect `(setq result (org--blockcall ,@b
                                     (concat
                                   "#+begin_export\n"
                                   result
                                   "\n#+end_export"
                                   )))) result)))
   #+END_SRC

#+end_details

*** Short Example: /An opportunity to learn!/
  :PROPERTIES:
  :CUSTOM_ID: Short_Example_An_opportunity_to_learn
  :END:

The following tiny block is composed from two details blocks and a box block
---defined elsewhere in this article. It is intended to give the reader another
opportunity to make sure they have tried to solve the puzzle posed in the main
text before seeing the answer ----this works well in HTML, not so in LaTeX.

#+begin_src emacs-lisp
(org-defblock solution
  (title "Solution" reprimand "Did you actually try? Maybe see the ‘hints’ above!"
   really "Solution, for real")
  "Show the answers to a problem, but with a reprimand in case no attempt was made."
  (org-thread-blockcall raw-contents
                    (details really :title-color "red")
                    (box reprimand :background-color "blue")
                    (details title)))
#+end_src

E.g., what is 1 + 1?

#+begin_spoiler
((Useless)) Hint: ((What is a number?))
#+end_spoiler

#+begin_solution
The answer is 2.

If you're interested in such ‘fundamental’ questions, consider reading
  Russel and Whitehead's /Principa Mathematica/ ;-)
#+end_solution

#+latex: \iffalse
The above box was created from:
#+begin_src C :tangle no
,#+begin_solution
The answer is 2.

If you're interested in such ‘fundamental’ questions, consider reading
  Russel and Whitehead's /Principa Mathematica/ ;-)
,#+end_solution
#+end_src
#+latex: \fi

We will make use of this block below when we get to guided problems ;-)

*** Longer Example: Demonstrating Org-markup with ~org-demo~
  :PROPERTIES:
  :CUSTOM_ID: Longer_Example_Demonstrating_Org-markup_with_org-demo
  :END:

  
Sometimes, we want to show verbatim source and its resulting rendition ---which
is a major part of this article! So, let's make a block to mitigate such an
error-prone tedium.

#+begin_details Implementation
 #+begin_src emacs-lisp
(org-defblock org-demo (nil nil source "Source" result "Result"
                        source-color "cyan" result-color "cyan"
                        style "parallel"
                        sep (if (equal backend 'html) "@@html:<p><br>@@" "\n\n\n\n")
                        )
  "Output the CONTENTS of the block as both parsed Org and unparsed.

Label the source text by SOURCE and the result text by RESULT

finally, the source-result fragments can be shown in a STYLE
that is either “parallel” (default) or “sequential”.

SEP is the separator; e.g., a rule ‘<hr>'.
"
  (-let [text (concat
               ;; Source
               (thread-last raw-contents
                 (format (if (equal backend 'html)
                             "<div ><pre class=\"src src-org\">%s</pre></div>"
                           "\n\\begin{verbatim}\n%s\n\\end{verbatim}"))
                 org-export
                 (org--blockcall box source :background-color source-color)
                 org-export)
               ;; Separator
               sep
               ;; Result
               (thread-last raw-contents
                 (org--blockcall box result :background-color result-color)
                 org-export))]

   (if (equal style "parallel")
       (org--blockcall parallel "2" :bar nil text)
       (concat "#+end_export\n" text "\n#+begin_export"))))
 #+end_src

 #+RESULTS:
 | :export | (lambda (label description backend) (s-replace-all `((@@ . )) (org--org-demo backend (or description label) label :o-link? t))) | :help-echo | (lambda (window object position) (save-excursion (goto-char position) (-let* (((&plist :path :format :raw-link :contents-begin :contents-end) (cadr (org-element-context))) (description (when (equal format 'bracket) (copy-region-as-kill contents-begin contents-end) (substring-no-properties (car kill-ring))))) (format %s |




#+end_details
#+html: <br>

 #+begin_box Example
 #+begin_parallel :bar t
 _This_
 #+begin_example org
,#+begin_org-demo
/italics/ and _underline_

$e^{i \times \pi} + 1 = 0$
,#+end_org-demo
 #+end_example

#+html: <hr><br>

 _Yields_
 #+begin_org-demo
 /italics/ and _underline_

 $e^{i \times \pi} + 1 = 0$
 #+end_org-demo
#+end_parallel
 #+end_box

 #+html: <br>

 #+begin_box (Sequential) Example
  #+begin_parallel :bar t
 _This_
 #+begin_example org
,#+begin_org-demo :style seq
/italics/ and _underline_

$e^{i \times \pi} + 1 = 0$
,#+end_org-demo
 #+end_example
#+html: <br><br><br><p><br><p><br><p><hr><p><br><p>

 _Yields_
 #+begin_org-demo :style seq
 /italics/ and _underline_

 $e^{i \times \pi} + 1 = 0$
 #+end_org-demo
#+end_parallel
 #+end_box

 However, since our implementation scheme relies on a preprocessing step before
 export, we cannot use ~org-demo~ to show the results of special blocks: They
 disappear in the preprocessing step!
 #+begin_parallel :bar t
 E.g., this
 #+begin_example org
,#+begin_org-demo
,#+begin_box
There is no special block ‘box’ to touch!
,#+end_box
,#+end_org-demo
 #+end_example

#+html: <br><p><hr><br>
 yields the /mess/
 #+begin_org-demo
 #+begin_box
 There is no special block ‘box’ to touch!
 #+end_box
 #+end_org-demo
#+end_parallel

 However, it does work with links!
 #+begin_org-demo
 Box-as-link! Boxception!
 #+end_org-demo
#+latex: \fi
** Practice Problems: /Now you try!/
   :PROPERTIES:
   :CUSTOM_ID: practice_problems
   :END:

*A 5-page PDF covering ELisp fundamentals* can be found *here*.

The first problem is to /get you going with Lisp/, the next two are actually
useful blocks.  The rename is useful for when you want to change some names or
translate some words; spoiler is useful when we want to test a student's
understanding, or to subtly hide the answer to a puzzle so the reader has the
opportunity to attempt solving it.

*** Sttutttterrr
  :PROPERTIES:
  :CUSTOM_ID: Sttutttterrr
  :END:

Define a block stutter so that the following examples behave as shown.

#+begin_details Hints
1. You need at-most 5 lines of Lisp.
2. These functions /may/ be useful: doc:s-repeat, doc:numberp,
   doc:string-to-number
#+end_details

#+html: <br>
#+begin_box Examples

#+begin_parallel :bar t
The following outputs, well, nothing, since we asked for zero repetitions.
#+begin_src org :tangle no
,#+begin_stutter 0

words

more words
,#+end_stutter
#+end_src

#+begin_stutter 0

Body0

Body1

#+end_stutter

#+columnbreak:

In contrast …
#+begin_org-demo
woah, I'm repeated 5 times!
#+end_org-demo
#+end_parallel
#+end_box

#+html: <br>
#+begin_solution
#+begin_src emacs-lisp
(org-defblock stutter (reps 2)
  "Output the CONTENTS of the block REPS many times"
  (-let [num (if (numberp reps) reps (string-to-number reps))]
    (s-repeat num contents)))
#+end_src

#+RESULTS:


#+end_solution
*** Textual Substitution ---A translation tool
  :PROPERTIES:
  :CUSTOM_ID: Textual_Substitution
  :END:

Define a block
rename so that the following examples behave as shown.

#+begin_details Hints
1. It can be done in less than 10 lines of Lisp.
2. First, try to doc:s-replace-all the substitution
   ~'(("Allah" . "God") ("Yacoub". "Jacob") ("Yusuf" . "Joseph"))~
   only.
3. Then take out such hard-coded substitutions … these functions /may/ be helpful:
   doc:--map / doc:-map, doc:s-split, doc:s-trim
#+end_details

#+html: <br>
#+begin_box Examples

# This…
#+begin_example org
,#+begin_rename "Allah to God, Yacoub to Jacob, Yusuf to Joseph"
Quran 12-4: *_Yusuf_* said to his father ( _*Yacoub*_ ), /“O my father, indeed I have seen (in a dream) eleven
stars and the sun and the moon; I saw them prostrating to me.”/
,#+end_rename
#+end_example
Yields…
#+begin_rename "Allah to God, Yacoub to Jacob, Yusuf to Joseph"
Quran 12-4: *_Yusuf_* said to his father ( _*Yacoub*_ ), /“O my father, indeed I have seen (in a dream) eleven
stars and the sun and the moon; I saw them prostrating to me.”/
#+end_rename

--------------------------------------------------------------------------------
#+begin_org-demo :style sequential

Genesis 41-17: Pharaoh said unto Joseph, /In my dream, behold, I stood upon the
bank of the river/ …

#+end_org-demo

#+end_box

#+html: <br>

#+begin_solution
#+begin_src emacs-lisp
(org-defblock rename (list "")
  "Perform the given LIST of substitutions on the text.
The LIST is a comma separated list of ‘to’ separated symbols.
In a link, no quotes are needed.

Substitution is handy enough that every block has it: the :let switch, much as a src block's :var, replaces
whole words and operators by the values of Lisp forms; e.g., #+begin_box :let (Yusuf \"Joseph\" -> \"⇒\")."
  (s-replace-all
   (--map (cons (car it) (cadr it))
          (--map (s-split " to " (s-trim it))
                 (s-split "," list)))
   contents))
#+end_src

#+RESULTS:



#+end_solution

Substitution is handy enough that every block has it: the :let switch, much as a src block's
=:var=, replaces whole words ---and operators such as =->=--- by the values of Lisp forms. By way of
example, =#+begin_box :let (Yusuf "Joseph" -> "⇒")= is a box whose =Yusuf= reads =Joseph=, and whose
=p -> q= reads =p ⇒ q=.

*** Spoilers! ---“fill in the blanks”
  :PROPERTIES:
  :CUSTOM_ID: spoilers
  :END:

# Warning: Enabling the following ruins the beautiful kbd:𝒳 styling, upon export.
# +html_head: <style>
# +html_head: .spoiler {color: grey; background-color:grey;}
# +html_head: .spoiler:hover {color: black; background-color:white;}
# +html_head: <style>
# Example use: <span class="spoiler"> test </span>

Define a block spoiler so that the following examples behave as shown.

#+begin_details Hints
1. It can be done in less than 10 lines of Lisp.
2. You will need the following style setup …
   #+begin_example org
#+html_head: <style>
#+html_head: .spoiler {color: grey; background-color:grey;}
#+html_head: .spoiler:hover {color: black; background-color:white;}
#+html_head: <style>
# Example use: <span class="spoiler"> test </span>
   #+end_example
3. /Escape/ HTML snippets by enclosing them in ~@@html: … @@~ ---as discussed above
   in the introduction to special blocks.
4. The functions  doc:s-replace-regexp and doc:regexp-quote /may/ be useful.
#+end_details

#+html: <br>
#+begin_box Examples
#+begin_parallel :bar t
#+begin_example org
,#+begin_spoiler
((Yusuf)) said to his father ((Yacoub)), /“O my father, indeed I have seen
((eleven stars)) and ((the sun and the moon)); I saw them prostrating to me.”/
,#+end_spoiler
#+end_example

#+begin_spoiler
((Yusuf)) said to his father ((Yacoub)), /“O my father, indeed I have seen
((eleven stars)) and ((the sun and the moon)); I saw them prostrating to me.”/
#+end_spoiler

#+columnbreak:
#+html: <br>

#+begin_example org
,#+begin_spoiler :left "[" :right "]"
[Yusuf] said to his father [Yacoub], /“O my father, indeed I have seen
[eleven stars] and [the sun and the moon]; I saw them prostrating to me.”/
,#+end_spoiler
#+end_example

#+begin_spoiler :left "[" :right "]"
[Yusuf] said to his father [Yacoub], /“O my father, indeed I have seen
[eleven stars] and [the sun and the moon]; I saw them prostrating to me.”/
#+end_spoiler

#+end_parallel
#+end_box

#+html: <br>
#+begin_solution
Rather than having auxiliary ~#+html_head:~ styling settings, we have moved the
styling information to the ~defblock~ declaration /and/ are using the main argument
to colour the spoiler ---which defaults to grey ;-)

--------------------------------------------------------------------------------

For example, the next segment of text is in a block ~#+begin_spoiler pink~ ...
#+begin_spoiler pink
((Yusuf)) said to his father ((Yacoub)), /“O my father, indeed I have seen
((eleven stars)) and ((the sun and the moon)); I saw them prostrating to me.”/
#+end_spoiler

Whereas, the following begins with ~#+begin_spoiler orange~ ...
#+begin_spoiler orange
((Yusuf)) said to his father ((Yacoub)), /“O my father, indeed I have seen
((eleven stars)) and ((the sun and the moon)); I saw them prostrating to me.”/
#+end_spoiler

--------------------------------------------------------------------------------

#+begin_src emacs-lisp
(org-defblock spoiler (color "grey" left "((" right "))")
  "Hide text enclosed in double parens ((like this)) as if it were spoilers.
   LEFT and RIGHT may be other kinds of delimiters.
   The main argument, COLOR, indicates which color to use.

For LaTeX, this becomes “fill in the blanks”, with the answers
in the footnotes."
  (if (equal backend 'latex)
      (s-replace-regexp
       (concat (regexp-quote left) "\\(.*?\\)" (regexp-quote right))
       "@@latex:\\\\fbox{\\\\phantom{\\1}}\\\\footnote{\\1}@@"
       contents)
  (-let [id (gensym)]
    (concat
     ;; In HTML, a ‘style’ can be, technically, almost anywhere...
     (format
      "<style> #%s {color: %s; background-color:%s;}
       #%s:hover {color: black; background-color:white;} </style>
       " id color color id)
     (s-replace-regexp
      (concat (regexp-quote left) "\\(.*?\\)" (regexp-quote right))
      (format "@@html:<span id=\"%s\"> \\1 </span>@@" id)
      contents)))))
#+end_src

#+RESULTS:
| :export | (lambda (label description backend) (s-replace-all `((@@ . )) (org--spoiler backend (or description label) label :o-link? t))) | :help-echo | (lambda (window object position) (save-excursion (goto-char position) (-let* (((&plist :path :format :raw-link :contents-begin :contents-end) (cadr (org-element-context))) (description (when (equal format 'bracket) (copy-region-as-kill contents-begin contents-end) (substring-no-properties (car kill-ring))))) (format %s |


There's actually a problem with this ‘solution’; can you find it?
#+begin_spoiler
Hint: ((Try the link form and see how it breaks!))
#+end_spoiler
#+end_solution

:OnMouseOver_OnMouseOut_Approach:

An alternative would be to use JS with mouse parameters; e.g.:

#+begin_export html
<a href="http://alhassy.github.io/"
   style="background: pink; padding: 10px; cursor: pointer"
   onMouseOver="this.style.color='#0F0'"
   onMouseOut="this.style.color='#00F'" >Text</a>
#+end_export

Possibly using ID's as the current working solution above.
:End:

*** Judgements: Inference rules and proof trees
    :PROPERTIES:
    :CUSTOM_ID: Judgements-Inference-rules-and-proof-trees
    :END:

 Using a mixture of ~\frac~ and ~\displaystyle~, define a block tree so that the
 following examples behave as shown. Hint: doc:org-list-to-lisp and
 doc:with-temp-buffer may be useful ;-)

#+begin_box Programming ≈ Proving
#+begin_parallel
*Source*
#+begin_src org :tangle no
,#+begin_tree
  + Function Application :: f(a) : B
    - a : A
    - f : A → B

  + Modus Ponens :: q
    - p
    - p ⇒ q
,#+end_tree
#+end_src

# +columnbreak:
#+html: <p>

*Result*
#+begin_tree
+ Function Application :: f(a) : B
  - a : A
  - f : A → B

+ Modus Ponens :: q
  - p
  - p ⇒ q
#+end_tree
#+end_parallel
#+end_box

#+begin_solution
#+begin_src emacs-lisp
(defun org--list-to-math (lst)
  "Get a result LST from ORG-LIST-TO-LISP and render it as a proof tree."
  (cond
   ((symbolp lst) "")
   ((symbolp (car lst)) (org--list-to-math (cadr lst)))
   (t
    (-let* (((conclusion₀ children) lst)
            ((name named?) (s-split " :: " conclusion₀))
            (conclusion (or named? conclusion₀)))
      (if (not children)
          (if named? (format "\\frac{}{%s}[%s]" conclusion name) conclusion)
        (format "\\frac{\\displaystyle %s}{%s}%s"
                (s-join " \\qquad "
                        (mapcar #'org--list-to-math children))
                conclusion
                (if named? (format "[\\text{%s}]" name) "")))))))

(org-defblock tree (main-arg)
  "Write a proof tree using Org-lists.

To get

         premises₀  …   premisesₙ
       ────────────────────────────[ reason ]
               conclusion

You type

       ,#+begin_tree
       + reason :: conclusion
         - premises₀
         - premises₁
         ⋮
         - premisesₙ
       ,#+end_tree

Where each premisesᵢ may, recursively, also have named reasons
and (indented) child premises of its own.

If there are multiple trees, they are shown one after the other.

The text in this block should be considered LaTeX;
as such, Org markup is not recognised.

A proof tree, derivation, is then just a deeply nested
itemisation.  For instance, assuming P = Q(X), X = Y, Q(Y) = R,
the following proves P = R.

  ,#+begin_tree
  + Trans :: P = R
    - P = Q(X)
      + ✓
    - Trans :: Q(X) = R
      + Trans :: Q(X) = Q(Y)
        - Refl :: Q(X) = Q(X)
          + ✓
        - Leibniz :: Q(X) = Q(Y)
          + X = Y
            - ✓
      + Sym :: Q(Y) = R
        - R = Q(Y)
          - ✓
  ,#+end_tree"
  (s-join "" (--map (format "\\[%s\\]"
                                (org--list-to-math it))
                        (cdr (with-temp-buffer
                               (insert raw-contents)
                               (goto-char (point-min))
                               (org-list-to-lisp))))))
#+end_src

#+RESULTS:
| :export | (lambda (label description backend) (s-replace-all `((@@ . )) (org--tree backend (or description label) label :o-link? t))) | :help-echo | (lambda (window object position) (save-excursion (goto-char position) (-let* (((&plist :path :format :raw-link :contents-begin :contents-end) (cadr (org-element-context))) (description (when (equal format 'bracket) (copy-region-as-kill contents-begin contents-end) (substring-no-properties (car kill-ring))))) (format %s |


#+end_solution

  For more on these ‘proof trees’, see ‘Natural Logic’ by Neil Tennant.
  # Out of print, but downloadable as a scanned PDF as the above link.

\[\] (*/Warning!/* For MathJax to activate, you should have some math ~$...$~
somewhere /besides/ the ~tree~ blocks; just ~\[\]~ suffices. )

** What's the rest of this article about?
   :PROPERTIES:
   :CUSTOM_ID: Whats_the_rest_of_this_article_about?
   :END:

The rest of the article showcases the special blocks declared with ~defblock~ to
allow the above presentation ---with folded regions, coloured boxes, tooltips,
parallel columns of text, etc.

Enjoy ;-)

** COMMENT The Older =org--𝒳= Utility
   :PROPERTIES:
   :CUSTOM_ID: Core-Utility
   :END:

 For posterity, below is the original route taken to solve the same problem.
 In particular, the route outlined below /may/ be faster.

 Why is ~defblock~ better?
 - The approach below requires an awkward way to handle arguments, key-values.
 - It requires the user to learn a new interface.
 - Even if it's slower, ~defblock~ uses a very familiar interface and requires less
   Lisp mastery on the user's part.

 --------------------------------------------------------------------------------

 :Hide:
  #+BEGIN_SRC emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Core utility
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 #+END_SRC
 :End:

 The simplest route is to ‘advise’ ---i.e., function patch or overload--- the Org
 export utility for special blocks to consider calling a method
 =org--𝒳= whenever it encounters a special block named =𝒳=.
 #+BEGIN_SRC emacs-lisp :noweb-ref enable-mode :tangle no
(advice-add #'org-html-special-block
   :before-until (apply-partially #'org--osbe-advice 'html))

(advice-add #'org-latex-special-block
   :before-until (apply-partially #'org--osbe-advice 'latex))
 #+END_SRC

 #+RESULTS:

 Here is the actual advice:
 #+BEGIN_SRC emacs-lisp
(defun org--osbe-advice (backend blk contents _)
  "Invoke the appropriate custom block handler, if any.

A given custom block BLK has a TYPE extracted from it, then we
send the block CONTENTS along with the current export BACKEND to
the formatting function org--TYPE if it is
defined, otherwise, we leave the CONTENTS of the block as is.

We also support the seemingly useless blocks that have no
contents at all, not even an empty new line."
  (let* ((type    (nth 1 (nth 1 blk)))
         (handler (intern (format "org-block/%s" type))))
    (ignore-errors (apply handler backend (or contents "") nil))))
 #+END_SRC

 #+RESULTS:
 :

 #+latex: \noindent
 *To support a new block named 𝒳:*
 1. Define a function =org--𝒳=.
 2. It must take two arguments:
    - ~backend~ ⇒ A symbol such as ='html= or ='latex=,
    - ~content~ ⇒ The string contents of the special block.
 3. The function must return a string, possibly depending on the backend being
    exported to. The resulting string is inserted literally in the exported file.
 4. Test out your function as in =(org--𝒳 'html "some input")=
    ---this is a quick way to find errors.
 5. Enjoy ^_^

 #+begin_center
 If no such function is defined, we export =𝒳= blocks using the default
 mechanism, as discussed earlier, as a LaTeX environment or an HTML =div=.
 #+end_center

 #+latex: \noindent
 An example is provided at the end of this section.

 #+latex: \noindent
 Of-course, when the user disables our mode, then we remove such advice.
 #+BEGIN_SRC emacs-lisp :noweb-ref disable-mode :tangle no
(advice-remove #'org-html-special-block
               (apply-partially #'org--osbe-advice 'html))

(advice-remove #'org-latex-special-block
               (apply-partially #'org--osbe-advice 'latex))
 #+END_SRC

 #+RESULTS:

***   =:argument:= Extraction
    :PROPERTIES:
    :CUSTOM_ID: argument-Extraction
    :END:

 As far as I can tell, there is no way to provide arguments to special blocks.
 As such, the following utility looks for lines of the form =:argument: value=
 within the contents of a block and returns an updated contents string that no
 longer has such lines followed by an association list of such argument-value
 pairs.

  #+BEGIN_SRC emacs-lisp
(defun org--extract-arguments (contents &rest args)
"Get list of CONTENTS string with ARGS lines stripped out and values of ARGS.

Example usage:

    (-let [(contents′ . (&alist 'k₀ … 'kₙ))
           (…extract-arguments contents 'k₀ … 'kₙ)]
          body)

Within ‘body’, each ‘kᵢ’ refers to the ‘value’ of argument
‘:kᵢ:’ in the CONTENTS text and ‘contents′’ is CONTENTS
with all ‘:kᵢ:’ lines stripped out.

+ If ‘:k:’ is not an argument in CONTENTS, then it is assigned value NIL.
+ If ‘:k:’ is an argument in CONTENTS but is not given a value in CONTENTS,
  then it has value the empty string."
  (let ((ctnts contents)
        (values (cl-loop for a in args
                         for regex = (format ":%s:\\(.*\\)" a)
                         for v = (cadr (s-match regex contents))
                         collect (cons a v))))
    (cl-loop for a in args
             for regex = (format ":%s:\\(.*\\)" a)
             do (setq ctnts (s-replace-regexp regex "" ctnts)))
    (cons ctnts values)))
  #+END_SRC

  #+RESULTS:
  : org--extract-arguments

 For example, we use this feature to indicate when a column break should happen
 in a =parallel= block and which person is making editorial remarks in an
 =remark= block.

 Why the =:𝒳:= notation? At the start of a line, a string of this form is coloured
 ---I don't recall why that is--- and that's a good enough reason to make use of
 such an existing support.

 #+begin_remark Aside
 In org-mode, ‘drawers’ are pieces of text that begin with
 =:my_drawer_name:= on a line by itself and end with =:end:= on a line by itself, and
 these delimiters allow us to fold away such regions and possibly exclude them
 from export. That is, drawers act as a light-weight form of blocks. Anyhow, Org
 colours drawer delimiters,
 #+end_remark

*** An Example Special Block ---=foo=
    :PROPERTIES:
    :CUSTOM_ID: COMMENT-An-Example-Special-Block-foo
    :END:

 Herein we show an example function =org--𝒳= that makes use of
 arguments.  In a so-called =foo= block, all occurrences of the word =foo= are
 replaced by =bar= unless the argument =:replacement:= is given a value.

 https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/foo_block.png

 #+name: startup-code
 #+begin_src emacs-lisp :tangle no
(defun org--foo (backend contents)
  "The FOO block type replaces all occurances of ‘foo’ with ‘bar’,
unless a ‘:replacement:’ is provided."
  (-let [(contents′ . (&alist 'replacement))
           (org--extract-arguments contents 'replacement)]
    (s-replace "foo" (or replacement "bar") contents′)))
 #+end_src

:Outdated_hide:

 Here's an example usage:
 #+begin_parallel
 #+begin_example org
#+begin_foo
:replacement: woah
I am foo; Indeed FoO is what I fOo!
#+end_foo
 #+end_example

 :columnbreak:

 #+begin_foo
 :replacement: woah
 I am foo; Indeed FoO is what I fOo!
 #+end_foo
 #+end_parallel

# See the implementation matter of ~edcomm~ or ~parallel~ for a more involved definition
# that behaves differently depending on the export backend.

:End:
** Fontifying all blocks as if they were Org blocks       :relocate:noexport:
:PROPERTIES:
:CUSTOM_ID: Fontifying-all-blocks-as-if-they-were-Org-blocks
:END:

Looking at =org-src-fontify-natively='s documentation leads up to looking at =org-fontify-meta-lines-and-blocks-1= which
uses ~(match-string 7)~ to obtain the language used to fontify a block.  We advice this function so that it's call to
~match-string~ behaves slightly different on input 7: We try to get the language used for fontification from
=my/block-fontifications= if possible, otherwise defaulting to the existing mechanism.

#+begin_src emacs-lisp
(defun osbe--block-fontifications ()
"Yields a cons list of block type and language pairs.

The intent is that the block types are fontified using the given language name."
    (--map (cons (symbol-name it) "org") (-cons* 'tiny 'center 'quote  org--supported-blocks)))

(defvar osbe--original-match-string (symbol-function 'match-string))

(cl-defun osbe--match-string (n &optional str)
          (let* ((block-type (string-remove-prefix "_" (funcall osbe--original-match-string 4 str)))
             (fontification (cdr (assoc block-type (osbe--block-fontifications)))))
        ;; (message "%s - %s -> %s" n block-type fontification) ;; For debugging.
        (if (and (equal n 7) fontification)
            fontification
          (funcall osbe--original-match-string n str))))

;; TODO: This should only be enabled when org-special-blocks-mode is enabled and otherwise should be removed.
(advice-add 'org-fontify-meta-lines-and-blocks
            :around (lambda (fontify &rest args)
                  (cl-letf (((symbol-function 'match-string) #'osbe--match-string))
                    (apply fontify args))))
 #+end_src

With the above setup, the following is fontified nicely in Org mode.
#+begin_box musa and then some more!
woah, nelly

# hello
# world

then:
#+begin_src emacs-lisp :tangle no
;; super neato
(defun hola () "HI")
#+end_src

Bye!
#+end_box
** Basic defblock test                                    :relocate:noexport:
:PROPERTIES:
:CUSTOM_ID: Basic-defblock-test
:END:
#    scream:hello
#
#    ≈
#
#    #+begin_scream hello
#    words
#    #+end_scream
#
#+begin_src elisp :tangle "tests.el"
(org-defblock scream
  (speaker "Default_Speaker")
  [:face '(:foreground "green" :weight bold)]
  "Capitalise the contents! Seen in red bold in Emacs!"
  (format "%s: %s" speaker (upcase contents)))

(deftest "Upcase works as expected on links, with only labels"
         [basic-defblock org-link]
         (⇝ (⟰ "pre scream:hello post")
            "pre hello: HELLO post"))

(deftest "Upcase works as expected on links, with descriptions"
         [basic-defblock org-link]
         (⇝ (⟰ "pre [[scream:hello][my dear friends]] post")
            "hello: MY DEAR FRIENDS post"))

(deftest "Upcase works as expected on blocks"
         [basic-defblock]
         (⇝ (⟰ "pre
#+begin_scream hello
my amigos
#+end_scream
post")
"pre"
(* anything)
"hello: "
"\n<p>"
"\nMY AMIGOS"
"\n</p>"
(* anything)
"<p>\npost"))

(deftest "Upcase works as expected on blocks, with default main argument"
         [basic-defblock main-arg]
         (⇝ (⟰ "pre
#+begin_scream
my amigos
#+end_scream
post")
"pre"
(* anything)
"Default_Speaker: "
"\n<p>"
"\nMY AMIGOS"
"\n</p>"
(* anything)
"<p>\npost"))
#+end_src

** Dispatch on =backend= ---open for extensibility
:PROPERTIES:
:CUSTOM_ID: Dispatch-on-backend-open-for-extensibility
:END:

Consider the source and how it exports ...
#+begin_org-demo
The link “ hello to the world ” exports with bold in HTML and large in LaTeX.
#+end_org-demo
# C-c C-e h o ⇒ bold
# C-c C-e l o ⇒ large

This could be declared via ...
#+begin_src elisp :tangle no
;; Declare the new defblock, along with how it should be displayed as an org link
(org-defblock shout0 (speaker)
  [:face '(:foreground "orange" :weight bold) :display 'full]
  "Capitalise the contents! Seen in orange bold in Emacs!"
  (pcase backend
    ('html (format "Yuck/%s: <strong>%s</strong>" speaker contents))
    ('latex (format "Yuck/%s: \\emph{\\LARGE %s}" speaker contents))
    (t (error "org-block/shout: Unsupported backend “%s”" backend))))
#+end_src

Rather than defining it with a single defblock declaration and a condition on the backend, we can define it using three
defblock declarations: One to declare the block along with top-level documentation and display link information; the
second for the HTML export; the third for the LaTeX backend export. (Your favourite backend ℬ can easily be supported by
declaring a new defblock in /your own code/!)

#+name: startup-code
#+begin_src elisp :tangle no
;; Declare the new defblock, along with how it should be displayed as an org link
(org-defblock shout (speaker)
  [:face '(:foreground "orange" :weight bold) :display 'full]
  "Capitalise the contents! Seen in orange bold in Emacs!")


;; Specialise its definition for when we export to the HTML backend
(org-defblock shout (speaker nil :backend html)
   "To shout is to be bold; i.e., strong."
  (format "%s: <strong>%s</strong>" speaker contents))


;; Specialise its definition for when we export to the LaTeX backend
(org-defblock shout (speaker nil :backend latex)
  "Shouting is a what LARGE brutes do"
  (format "%s: \\emph{\\LARGE %s}" speaker contents))
#+end_src

Try 〔C-h o org-defblock/shout〕 and see two implementations.
- This means that users can always re-define an org special block, or extend it to support a new backend. Neato!
- Free user extensibility!

Such “open methods” are known as “multimethods”; e.g., see doc:cl-defgeneric and doc:cl-defmethod.

:Multimethod_invocation_examples_of_SHOUT:
#+begin_src elisp :tangle no
;; Example uses of the multimethods approach
(org-block/shout 'random-backend "hi") ;; should error!
(org-block/shout 'html "hi")
(org-block/shout 'latex "hi")
#+end_src
:End:

* 🧙‍♂️ /Write Once, Export Everywhere/: Say Hello to =org-special-block-extras=
:PROPERTIES:
:CUSTOM_ID:   org-special-block-extras
:TITLE:       org-special-block-extras: Write Once, Export Everywhere
:DESCRIPTION: A unified interface for special blocks and links: defblock.
:END:

# MELPA's own badge, drawn live, shows the version MELPA serves; melpa: would show ours at export time.
https://melpa.org/packages/org-special-block-extras-badge.svg

*Tired of repeating yourself when writing in Org-mode for LaTeX and HTML
exports?* =org-special-block-extras= is your magical toolkit for
creating /custom Org-mode blocks/ and /links/ that work seamlessly
across backends ---without diving into the dark arts of raw HTML or
LaTeX!

Reading in glare?  Pick a background ---a pale colour soothes the eyes.

** 🎁  What Does It Do?
  :PROPERTIES:
  :CUSTOM_ID: what-does-it-do
  :END:

- *🎨 Style with ease* --- add colors, badges, tooltips (from a dictionary, Emacs
  Help, or custom file), keystroke notations, inline editorial comments, or even
  colourful ASCII cows with fortune cookies.
- *📚 Glossary support* --- embed hoverable documentation with =doc:= links and auto-generated glossaries.
- *📦 Add interactive content*: from collapsible detail sections and parallel columns to spoiler tags and equational proofs.
- *🎛 Switch any block*: =:when (eq backend 'html)=, =:noexport t=, =:let (N 7)=, =:boxed "Title"=, =:folded t=, and
  =:verbatim t=, and =:C-c_C-c ACTION= work on every block ---ours, yours, or Org's own src and quote blocks; see
  switches.
- badge:Hello|World Use *badge-style links* to embed GitHub stars, Reddit subs, or custom  project metadata via =shields.io=.
- *🛠 Use =org-defblock=, =org-deflink= and =org-deftag=* ---Org, extended as one extends Lisp:
  each is declared like a ~cl-defun~, with =&optional= and =&key= arguments; or, for the
  terse-minded, with a flattened arglist.
  + Create powerful custom blocks with ~org-defblock~: Define a block once and export to
    LaTeX /and/ HTML effortlessly. With /header-args/ support like
    =:color red :signoff "Thanks!"= for locally customised exports. Each block is also a
    link and a tag, for free; and =:fontify= says how it looks in the buffer.
  + Use ~org-deflink~ to create custom links, as functions of their label and description.
  + Use ~org-deftag~ to create custom tags, as functions of the Org sections they tag.
    
# - *🧩 Compose blocks modularly* --- nest and thread blocks functionally, just like  Lisp =funcall=.
# TODO. FIXME. - Embrace *modularity*: Build new blocks from existing ones with  =thread-blockcall= --- like Lisp =funcall=.
 
   # With a single macro =defblock=, this package provides *dozens of
   # built-in Org-mode blocks*, all tailored for rich export and seamless
   # Emacs display:

--------------------------------------------------------------------------------
   
 *🧱 Ready-to-Use Custom Blocks*
  
  | Block                       | Use Case                                                                              |
  |-----------------------------+---------------------------------------------------------------------------------------|
  | =details=                   | Foldable sections --- perfect for hiding spoilers, proofs, or long explanations.      |
  | =parallel=                  | Display content in multiple columns --- great for comparisons or saving space.        |
  | =margin=                    | Add subtle explanatory tooltips or side remarks --- delightful for scholarly writing. |
  | =box=                       | Emphasize content with nicely styled borders --- great for callouts or side notes.    |
  | =spoiler=                   | Hide content visually until the reader chooses to see it --- useful in teaching.      |
  | =tree=                      | Display proof trees and logical derivations --- fantastic for formal logic.           |
  | =rename=                    | Automated text substitution --- great for translation or glossary effects.            |
  | =stutter=                   | Repeat content multiple times --- e.g., for emphasis or stylistic flair.              |
  | =solution=                  | Reveal answers in stages --- perfect for educational content.                         |
  | =org-demo=                  | Show Org markup alongside its rendered result --- ideal for tutorials.                |
  | =math=                      | Display maths wherein =red:𝒳= colours a symbol, as it colours prose.                  |
  | =calc=                      | Step-by-step equational reasoning --- beautiful for math walkthroughs.                |
  | =graph=                     | Draw nested Org lists as Graphviz diagrams --- =C-c C-c= renders a PNG in place.      |
  | =note=, =tip=, =warning=, … | GitHub-style callouts ---a coloured rule and a titled heading.                        |
  | =highlight=                 | Colour a paragraph's background, rather than its text.                                |
  | =package-docs=              | A table of a package's public API, each name a =doc:= tooltip.                        |
  | =style=                     | Page-wide CSS, verbatim; nothing outside HTML.                                        |
  # | =documentation=      | Define glossary/tooltips --- enrich your articles with inline help.                   |
  # | =remark= / =rremark= | Editorial comments --- provide in-place or top-level reviewer feedback.               |

--------------------------------------------------------------------------------
  
*Ready-to-Use Custom Links*
    | Link                 | Purpose                                                                                         |
    |----------------------+-------------------------------------------------------------------------------------------------|
    | =doc:label=          | Glossary tooltips ---e.g., doc:cl-loop; our own terms, even =<<<radio targets>>>=, too          |
    | =kbd:=               | Stylized keybindings with tooltips --- e.g., =kbd:C-x_C-e=; in Emacs, 〔C-x C-e〕, click to run |
    | =color:= or =red:=   | Inline text colouring --- supports both names and hex codes.                                    |
    | =highlight:=         | Colour the background instead ---so highlighted in Emacs too.                                   |
    | =palette:=           | A button for readers to pick the page's background colour.                                      |
    | =toggle-details:=    | A button to unfold, or fold, every =details= block at once.                                     |
    | =html-export-style:= | Pick a visual theme for HTML exports --- one click, new style.                                  |
    | =badge:=             | Embed project badges --- e.g., GitHub stars, Reddit subs, versioning.                           |
    | =fortune:=           | Insert ASCII animals saying jokes or phrases --- joy in your docs!                              |
    | =octoicon:=          | GitHub-style icons --- for styling and linking like a pro.                                      |
    | =link-here:=         | Local anchors --- create navigable sections anywhere.                                           |
    | =show:=              | Show a variable value --- dynamically insert content like your name or version.                 |
    | =elisp:=             | Make clickable actions --- buttons that run Emacs Lisp.                                         |
    

--------------------------------------------------------------------------------
    
💡 Ideal For
+ 🧑‍🏫 Educators building interactive lessons and glossaries
+ 🧑‍💻 Developers documenting APIs with style
+ 📚 Writers crafting scholarly or explorable documents
+ ✨ Emacsers who want rich export without leaving Org-mode
+ ✏️ Bloggers wanting powerful interactivity
  - This is /the/ reason I made this package. 
+ 1️⃣ Anyone who wants to keep Org-mode as the single source of truth for pink:rich
  exports
 

🪄 *Just load the package, write in Org, and let =defblock= handle the
rest.* Now your Org-mode documents are not just structured ---they're
/spectacular/.

--------


*Write rich Org-mode documents --- one source, many formats.*
The =org-special-block-extras= package empowers you to define and use
/custom blocks/ and /links/ that make your Org files export beautifully
to both *HTML and LaTeX*, /without ever writing raw HTML or LaTeX
again/.


** 🗺 The package at a glance
  :PROPERTIES:
  :CUSTOM_ID: at-a-glance
  :END:

Every node below leads to its section; hover, or tap, one for its gist. The map is itself a graph
block ---an Org list, coloured by ~#+name:~ tables folded in its ~:TEMPLATES:~ drawer, and laid out radially by ~:layout twopi~.

#+begin_graph :svg t :size "10,10" :layout twopi :root osbe :ranksep 1.6 :wrap 16 :directed nil :node.fontname Helvetica :node.shape box :node.style "rounded,filled" :node.fillcolor white :edge.color gray50 :overlap false
:TEMPLATES:
#+name: glance_write
| fillcolor | "#e5f5e5" |
#+name: glance_read
| fillcolor | "#ffe8cc" |
#+name: glance_act
| fillcolor | "#e0ecff" |
#+name: glance_make
| fillcolor | "#f3e0ff" |
:END:
+ <<osbe>> [[https://github.com/alhassy/org-special-block-extras][*org-special-block-extras*]] [fn::Blocks, links, and switches for Org, exported alike to HTML, LaTeX, and Markdown.]
  + Blocks to write :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Callouts][Callouts]] \\ note · tip · important · warning · caution [fn::GitHub's alerts: a coloured rule and a titled heading; Markdown gets the alerts themselves.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Boxed-Text][Folding & framing]] \\ box · details · solution · spoiler · parallel [fn::Draw attention to text, fold it away, or set ideas side by side.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#tooltip][Remarks]] \\ margin · tooltip · remark [fn::Notes that stay out of the reader's way: in the margin in LaTeX, hovered or tapped in HTML. Org's own footnotes join them.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Highlights][Colour]] \\ red · blue · … · highlight [fn::19 named colours, each a block and a link, and a highlight that colours the background.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Aligned-equations][Maths & proofs]] \\ math · align · calc · tree [fn::Display maths wherein =red:𝒳= colours a symbol; aligned equations, with coloured tags that =eqref:𝒳= cites; equational proofs and proof trees, as Org lists.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Graphs][Graphs]] \\ graph [fn::Org lists drawn by Graphviz; this very map is one.] :glance_write:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Glossaries][Glossaries]] \\ documentation [fn::Define a term once, cite it everywhere with =doc:𝒳=; =show:GLOSSARY= lists every citation.] :glance_write:
  + Links to cite :glance_read:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Glossaries][=doc:𝒳=]] \\ =show:𝒳= [fn::A term's definition as a tooltip; or a Lisp expression's value, inline.] :glance_read:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#nice-keystroke-renditions][=kbd:C-x_C-s=]] [fn::Keys as keycaps, their command's documentation as a tooltip; click one in Emacs to run it.] :glance_read:
    + [[doc:org-make-badge][Badges]] \\ badge · melpa · github-* [fn::Shields.io badges, for a project's README.] :glance_read:
    + Every block, as a link [fn::=red:𝒳=, =[[box:Title][…]]=, and the like: a block's one-line form.] :glance_read:
  + Switches on any block :glance_act:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Switches-for-every-block][:when · :noexport]] [fn::Export a block only for some backends, or never.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Switches-for-every-block][:let · :ignore]] [fn::Substitute variables beforehand; or drop the block's behaviour, keeping its text.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Switches-for-every-block][:boxed · :folded]] [fn::Box the result, or fold it away; on src and quote blocks too.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-blocks-and-links#Switches-for-every-block][:verbatim]] [fn::Show the block's source; with demo, beside its result.] :glance_act:
  + Keys in Emacs :glance_act:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#C-c-C-c-for-your-own-blocks][C-c C-c]] [fn::A block's action: render a graph, run a :C-c_C-c form.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#C-c-quote-for-your-own-blocks][C-c ']] [fn::Edit any special block's contents in a buffer of their own.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#C-c-C-v-C-d-to-split-a-block][C-c C-v C-d]] [fn::Split any special block in two at point.] :glance_act:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#eldoc-for-blocks-and-links][eldoc]] [fn::Hover a #+begin_ line, or a link, for its arguments and gist.] :glance_act:
  + Make your own :glance_make:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#Make-your-own-blocks][org-defblock]] [fn::A block, its link, and its tag, from one cl-defun-style definition.] :glance_make:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#Make-your-own-links][org-deflink]] [fn::A link type: how it looks in Emacs and how it exports.] :glance_make:
    + [[https://alhassy.com/org-special-block-extras-developers-guide#tags-are-functions-of-org-sections][org-deftag]] [fn::A heading tag as a function of its section.] :glance_make:
    + [[doc:org-thread-blockcall][org-thread-blockcall]] [fn::Compose blocks: solution is details of a box of details.] :glance_make:
  + Options :glance_make:
    + org-defblock-evaluate-switches [fn::May a document's :when, :let, and :C-c_C-c run Lisp? Ask, by default.] :glance_make:
    + org-special-block-add-html-extra [fn::Inline the tooltips' CSS and JS in HTML exports; on, by default.] :glance_make:
    + org-docs-libraries [fn::Org files whose glossary entries every document may cite.] :glance_make:
#+end_graph

* Block and link types provided by this package
:PROPERTIES:
:CUSTOM_ID:   org-special-block-extras-blocks-and-links
:TITLE:       org-special-block-extras: The block and link types
:DESCRIPTION: Boxes, details, tooltips, glossaries, graphs, callouts, colours, and more ---each shown beside its export.
:END:
** Boxed Text —Calling out super duper info
   :PROPERTIES:
   :CUSTOM_ID: Boxed-Text
   :END:

   osbe-example:box

*** TODO COMMENT Extra notes, either make into yaml tests or more to an FAQ section
   
**** Three demos of  box
 #+latex_header: \newunicodechar{ᵒ}{\ensuremath{{}^o}}
 #+html: <br>
 #+begin_box Example: A super boring observation presented obscurely :background-color blue

 If you start walking ---say, counterclockwise--- along the unit circle from its
 right-most point and walk 180ᵒ, then you will be at its left-most point. That
 is, \[ e^{i · \pi} \;=\; - 1 \]

 #+end_box

 #+html: <br>
 Or, with just the header option ~:shadow t~ …
 #+begin_box Example: A super boring observation presented obscurely :shadow t

 If you start walking ---say, counterclockwise--- along the unit circle from its
 right-most point and walk 180ᵒ, then you will be at its left-most point. That
 is, \[ e^{i · \pi} \;=\; - 1 \]

 #+end_box

 #+html: <br>
Or, with the header option ~:shadow (:left "inset cyan" :right "inset pink"
:deep-right orange)~ …
 #+begin_box Example: A super boring observation presented obscurely :background-color blue :shadow (:left "inset cyan" :right "inset pink" :deep-right orange)

 If you start walking ---say, counterclockwise--- along the unit circle from its
 right-most point and walk 180ᵒ, then you will be at its left-most point. That
 is, \[ e^{i · \pi} \;=\; - 1 \]

 #+end_box

 For further header options, see the documentation of box.

**** Subtle Colours
 #+html: <br>
 In the first example above, /how did we get that nice light blue? What
 is its HTML code?/ That's not something I care to remember, so let's
 make a handy dandy utility … Now when users request a colour to ~box~
 their text, it will be a ‘subtle colour’ ;-)

 #+begin_details Implementation for Subtle Colours
 #+begin_src emacs-lisp -r -n
(defun org-subtle-colors (c)
  "HTML codes for common colours.

Names are very rough approximates.

   Translations from: https://www.december.com/html/spec/softhues.html"
  (pcase c
    ("teal"    "#99FFCC") ;; close to aqua
    ("brown"   "#CCCC99") ;; close to moss
    ("gray"    "#CCCCCC")
    ("purple"  "#CCCCFF")
    ("lime"    "#CCFF99") ;; brighter than ‘green’
    ("green"   "#CCFFCC")
    ("blue"    "#CCFFFF")
    ("orange"  "#FFCC99")
    ("peach"   "#FFCCCC")
    ("pink"    "#FFCCFF")
    ("yellow"  "#FFFF99")
    ("custard" "#FFFFCC") ;; paler than ‘yellow’
    (c c)
  ))
 #+end_src

To use these colour names, you will need the following incantations in
your Org file.

#+begin_src org :tangle no
#+latex_header: \usepackage{xcolor}

#+latex_header: \definecolor{teal}    {HTML}{99FFCC}
#+latex_header: \definecolor{brown}   {HTML}{CCCC99}
#+latex_header: \definecolor{gray}    {HTML}{CCCCCC}
#+latex_header: \definecolor{purple}  {HTML}{CCCCFF}
#+latex_header: \definecolor{lime}    {HTML}{CCFF99}
#+latex_header: \definecolor{green}   {HTML}{CCFFCC}
#+latex_header: \definecolor{blue}    {HTML}{CCFFFF}
#+latex_header: \definecolor{orange}  {HTML}{FFCC99}
#+latex_header: \definecolor{peach}   {HTML}{FFCCCC}
#+latex_header: \definecolor{pink}{HTML}{FFCCFF}
#+latex_header: \definecolor{yellow}  {HTML}{FFFF99}
#+latex_header: \definecolor{custard}{HTML}{FFFFCC}

#+latex_header: \definecolor{cyan}{HTML}{00FFFF}
#+end_src

In the future, it'd be nice to account for colours for LaTeX as well.  ( E.g.,
src_latex[:exports code]{\color{blue}} is a nightmare. )
 #+end_details

** Folded Details ---Let the user see stuff only if they're interested
  :PROPERTIES:
  :CUSTOM_ID: Folded-Details
  :END:

   osbe-example:details

   Src blocks fold too: the header argument =:folded t= exports a src block, exactly as Org
   otherwise would, inside a =details= block titled by its language; =:folded "TITLE"= picks
   the title.
   #+begin_example
,#+begin_src emacs-lisp :folded "How is it done?"
(org-defblock details …)
,#+end_src
   #+end_example

   A page with many folded blocks may offer a button to unfold them all at once:
   =[[toggle-details:][Show me everything]]= is that button; pressed again, it folds them
   all. Without a description, it reads “Unfold all details”.
*** TODO COMMENT Extra notes, either make into yaml tests or more to an FAQ section
:PROPERTIES:
:CREATED:  [2025-06-06 Fri 20:12]
:END:
The implementation of ~details~ above is hidden away, and this is a
concrete example of hiding a boring, but important, code snippet.
Below is a concrete example of a ‘conversation-style’ usage of the
~details~ block:
#+begin_box "Here's a nifty puzzle, can you figure it out? 👽"
Reductions ---incidentally also called ‘folds’[fn:1]--- embody
primitive recursion and thus computability. For example, what does
~(-reduce #'/ (number-sequence 1.0 𝓃))~ compute when given a whole
number 𝓃?

#+begin_details Solution :title-color pink
Rather than guess-then-check, let's /calculate/!

#+begin_src emacs-lisp :tangle no
  (-reduce #'/ (number-sequence 1.0 𝓃))
= ;; Lisp is strict: Evaluate inner-most expression
  (-reduce #'/ '(1.0 2.0 3.0 … 𝓃))
= ;; Evaluate left-associating reduction
  (/ (/ (/ 1.0 2.0) ⋯) 𝓃)
=;; Arithmetic: (/ (/ a b) c) = (* (/ a b) (/ 1 c)) = (/ a (* b c))
  (/ 1.0 (* 2.0 3.0 … 𝓃))
#+END_SRC

We have thus found the above Lisp program to compute the inverse factorial of 𝓃;
i.e., $\large \frac{1}{𝓃!}$.
#+end_details

Neato, let's do more super cool stuff ^_^
#+end_box


--------------------------------------------------------------------------------


#+begin_box "Tip 🌼"
If you fear that your readers may not click on details boxes in the HTML export,
you could, say, have the details heading “flash pink” whenever the user hovers
over it. This can be accomplished by inserting the following incantation into
your Org file or place it into your ~org-html-head~ variable.
#+begin_example org
#+html: <style>  summary:hover {background:pink;} </style>
#+end_example

# Which, I will do, for fun.
#+html: <style>  summary:hover {background:pink;} </style>
#+end_box


Sometimes you want to remark on details without drawing too much
attention, and so a tooltip via tooltip suffices.

** Nice Keystroke Renditions: 〔C-h t〕
  :PROPERTIES:
  :CUSTOM_ID: nice-keystroke-renditions
  :END:
  
Anyone who writes /about/ Emacs will likely want to mention keystrokes in an
aesthetically pleasing way, such as 〔C-u 80 -〕 to insert 80 dashes,
or 〔C-c C-e h o〕 to export an Org-mode file to HTML,
or the useful 〔M-s h .〕.

- ~kbd:𝒳~ will show a tooltip defining 𝒳, as an Emacs Lisp function, if possible.
  For example, ~kbd:C-h_t~ is 〔C-h t〕; and likewise =<kbd:M-s h .>= is 〔M-s h
  .〕 (we need to use ~<...>~ since punctuation is not picked up as part of link
  labels).  In contrast, ~kbd:nope~ renders as 〔nope〕 /without/ a tooltip (nor a
  red border).

  You can also supply explicit tooltip description: =[[kbd:key
  sequence][description]]= will show as 〔key sequence〕; i.e.,
  the key sequence in nice key font along with a tooltip explaining it.

- In Emacs itself, each of these displays as 〔C-x C-s〕: the =kbd:= markup becomes the
  brackets and each =_= a space. Only the markup is displayed differently, so the keys
  stay editable as ever. Moreover, clicking one runs its keys ---after asking, as =elisp:=
  links do--- so readers may try them on the spot.


# To make a screenshot, add the following to the above :PROPERTIES: drawer.
#   :UNNUMBERED: t
#
#+attr_html: :width 80% :height 80%s
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/kbd.png

*** TODO COMMENT Extra notes, either make into yaml tests or more to an FAQ section

#+begin_details Implementation

#+begin_src emacs-lisp
(org-deflink kbd
  "Show keysequence O-LABEL in a nice grey button-like font, along with a tooltip of its documentation, if any.

Such links do not get folded in bracket style, and are rendered as buttons within Emacs.

Moreover, O-LABEL may use ‘_’ in-lieu of spaces or bracket link notation.

Examples:
    〔C-x C-s〕
  ≈ 〔C-x C-s〕
  ≈ 〔C-x C-s〕"
  [:display 'full
   :let (the-label  (s-trim (s-replace "_" " " o-label))
         lisp-func  (ignore-errors (cl-second (help--analyze-key (kbd the-label) the-label)))
         tooltip    (or o-description (ignore-errors (documentation lisp-func)) "")
         tooltip?   (not (equal tooltip ""))
         style      (if tooltip? "border-color: red" "")
         keystrokes (format "<kbd style=\"%s\">%s</kbd>" style the-label))
   ;; o-description is always nil when it comes to deciding the :face.
   :face (list :inherit 'custom-button :box (if tooltip? "red" t))
   :help-echo (format "%s ∷ %s\n%s" the-label (or lisp-func "") tooltip)]
  (if (equal o-backend 'latex)
      (format "\\texttt{%s}" the-label)
    (if tooltip?
        ;; The style=⋯ is to remove the underlining caused by <abbr>.
        (format "<abbr class=\"tooltip\" style=\"border: none; text-decoration: none;\" title=\"%s ∷ %s<br>%s\">%s</abbr>"
                the-label (or lisp-func "") (org-osbe-html-export-preserving-whitespace tooltip)
                keystrokes)
      keystrokes)))
#+end_src

The following styling rule is used to make the keystrokes displayed nicely.
#+begin_src emacs-lisp :noweb-ref enable-mode :tangle no
  (defvar org--osbe-kbd-html-setup nil
    "Has the necessary keyboard styling HTML beeen added?")

  (unless org--osbe-kbd-html-setup
    (setq org--osbe-kbd-html-setup t))
  (when org-special-block-add-html-extra
   (setq org-html-head-extra
    (concat org-html-head-extra
     "
  <style>
  /* From: https://endlessparentheses.com/public/css/endless.css */
  /* See also: https://meta.superuser.com/questions/4788/css-for-the-new-kbd-style */
  kbd
  {
    -moz-border-radius: 6px;
    -moz-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
    -webkit-border-radius: 6px;
    -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
    background-color: #f7f7f7;
    border: 1px solid #ccc;
    border-radius: 6px;
    box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
    color: #333;
    display: inline-block;
    font-family: 'Droid Sans Mono', monospace;
    font-size: 80%;
    font-weight: normal;
    line-height: inherit;
    margin: 0 .1em;
    padding: .08em .4em;
    text-shadow: 0 1px 0 #fff;
    word-spacing: -4px;

    box-shadow: 2px 2px 2px #222; /* MA: An extra I've added. */
  }
  </style>")))
#+end_src

Let's have some sanity tests...
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "It becomes <kbd> tags, but final symbol non-ascii *may* be ignored"
  [kbd direct-org-links]
  (⇝ (⟰ "〔C-u 80 -〕∀") "<p>\n<kbd style=\"\">C-u 80</kbd>_-∀</p>"))

(deftest "It becomes <kbd> tags"
  [kbd square-org-links]
  (⇝ (⟰ "〔C-u 80 -〕") "<p>\n<kbd style=\"\">C-u 80 -</kbd></p>"))

(deftest "<It> becomes <kbd> tags, and surrounding space is trimmed"
  [kbd angle-org-links]
  (⇝ (⟰ "〔C-u 80 - 〕")  "<p>\n<kbd style=\"\">C-u 80 -</kbd></p>"))

;; FIXME: uh-oh!
(when nil
(deftest "It has a tooltip documenting the underlying Lisp function, when possible"
  [kbd tooltip]
  (⇝ (⟰ "〔M-s h .〕")

     "<abbr class=\"tooltip\""
     (* anything)
     "Highlight each instance of the symbol at point.<br>Uses the
     next face from ‘hi-lock-face-defaults’ without
     prompting,<br>unless you use a prefix argument.<br>Uses
     ‘find-tag-default-as-symbol-regexp’ to retrieve the symbol
     at point.<br><br>This uses Font lock mode if it is enabled;
     otherwise it uses overlays,<br>in which case the
     highlighting will not update as you type.&emsp;The
     Font<br>Lock mode is considered ''enabled'' in a buffer if
     its ‘major-mode’<br>causes ‘font-lock-specified-p’ to return
     non-nil, which means<br>the major mode specifies support for
     Font Lock."
     (* anything)
     "<kbd style=\"border-color: red\">M-s h .</kbd></abbr>")))
#+end_src

#+end_details

:Hide:
#+HTML: <style>
#+HTML: kbd
#+HTML: {
#+HTML:   -moz-border-radius: 6px;
#+HTML:   -moz-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
#+HTML:   -webkit-border-radius: 6px;
#+HTML:   -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
#+HTML:   background-color: #f7f7f7;
#+HTML:   border: 1px solid #ccc;
#+HTML:   border-radius: 6px;
#+HTML:   box-shadow: 0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
#+HTML:   color: #333;
#+HTML:   display: inline-block;
#+HTML:   font-family: 'Droid Sans Mono', monospace;
#+HTML:   font-size: 80%;
#+HTML:   font-weight: normal;
#+HTML:   line-height: inherit;
#+HTML:   margin: 0 .1em;
#+HTML:   padding: .08em .4em;
#+HTML:   text-shadow: 0 1px 0 #fff;
#+HTML:   word-spacing: -4px;
#+HTML:
#+HTML:   box-shadow: 2px 2px 2px #222; /* MA: An extra I've added. */
#+HTML: }
#+HTML: </style>
#+HTML:
:End:
** Remark —Inline footnotes, viz HTML tooltips and LaTeX notes in the margin
  :PROPERTIES:
  :CUSTOM_ID: tooltip
  :END:

Sometimes you want to remark on details without drawing too much
attention, and so a tooltip via remark suffices.
  
   osbe-example:tooltip

   A tooltip opens when its word is hovered with a mouse, or tapped on a phone; it closes when we
   leave both, tap elsewhere, or press =Escape=. Its text is Org, exported as Org, so it may hold
   links ---clickable, since moving into the tooltip keeps it open--- and any other markup; an
   Elisp docstring is shown just as it is written. The machinery is tooltips.js, about eighty
   lines with no dependencies, in the look of tooltips.css; both are inlined into each exported
   page, which so fetches nothing for them.

   Org's own footnotes are such remarks too: in HTML, each footnote's number is a tooltip of its
   definition, the footnotes section staying below, for print; in LaTeX, each is a margin note, as
   the margin block's are, numbered as footnotes are. All three of Org's spellings serve: an
   anonymous =[fn::…]=, a named =[fn:NAME]= defined elsewhere, and a named inline =[fn:NAME: …]=, which
   later =[fn:NAME]= references share.

   osbe-example:footnote

*** TODO COMMENT Extra notes, either make into yaml tests or more to an FAQ section

   
#+begin_details "★ Example: A ‘margin’ with an ‘export’ in the middle" :title-color orange
 An HTML “marquee”
 #+begin_tooltip
 An example is best:
 #+begin_export html
 <marquee>Catch me if you can!</marquee>
 #+end_export
 It is pronounced “mar key”.
 #+end_tooltip
 is a scrolling piece of text.

--------------------------------------------------------------------------------
*Source:*
#+begin_src org
 An HTML “marquee”
 ♯+begin_tooltip
 An example is best:
 ♯+begin_export html
 <marquee>Catch me if you can!</marquee>
 ♯+end_export
 It is pronounced “mar key”.
 ♯+end_tooltip
 is a scrolling piece of text.
#+end_src
#+end_details
#+begin_details Example: Brief code snippet in tooltip/margin
It's a
#+begin_tooltip simple
/Proof Sketch:/ “Squint” your eyes to see ~zero : ℕ~ and ~nothing : Maybe ℕ~ as
essentially the same, and “squint” your eyes to see that ~suc~ is essentially the
same as ~just~.

More formally, here's one direction:
#+begin_src haskell :tangle no
to : Maybe ℕ → ℕ
to nothing  = zero
to (just n) = suc n
  #+end_src

The rest is an arduous exercise if you don't know what's going on.
#+end_tooltip
exercise to show that ℕ is fixedpoint of ~Maybe~.
--------------------------------------------------------------------------------
*Source:*
#+begin_src org
It's a
,#+begin_tooltip simple
/Proof Sketch:/ “Squint” your eyes to see ~zero : ℕ~ and ~nothing : Maybe ℕ~ as
essentially the same, and “squint” your eyes to see that ~suc~ is essentially the
same as ~just~.

More formally, here's one direction:
,#+begin_src haskell :tangle no
to : Maybe ℕ → ℕ
to nothing  = zero
to (just n) = suc n
,#+end_src

The rest is an arduous exercise if you don't know what's going on.
,#+end_tooltip
exercise to show that ℕ is fixedpoint of ~Maybe~.
#+end_src
#+end_details
#+begin_details "★ Example: Lengthy ‘remark’ with multiple code blocks!" :title-color orange
It's a
#+begin_tooltip simple
  We show that there is an /isomorphism/; i.e., a non-lossy protocol between ~Maybe ℕ~
  and ~ℕ~ in stages.

  First, let's recall the definitions ... in Agda ...
  #+begin_src haskell :tangle no :tangle no
data Maybe (A : Set) : Set₁ where
  nothing : Maybe A
  just    : A → Maybe A

data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ
   #+end_src

  We can show ~Maybe ℕ ≅ ℕ~ by writing two functions...
  #+begin_src haskell :tangle no
to : Maybe ℕ → ℕ
to nothing = zero
to (just n) = suc n

from : ℕ → Maybe ℕ
from zero = nothing
from (suc n) = just n
  #+end_src

  ...and, finally, checking that the two functions undo each other...
  #+begin_src emacs-lisp :tangle no
to∘from : ∀ {n} →  to (from n)  ≡  n
to∘from n = {! try it! }

from∘to : ∀ {m} →  from (to m)  ≡  m
from∘to m = {! try it! }
  #+end_src


  This is “simple”, but involved!
   #+end_tooltip
exercise to show that ℕ is fixedpoint of ~Maybe~.
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
It's a
,#+begin_tooltip simple
We show that there is an /isomorphism/; i.e., a non-lossy protocol between ~Maybe ℕ~
and ~ℕ~ in stages.

First, let's recall the definitions ... in Agda ...
,#+begin_src haskell :tangle no :tangle no
data Maybe (A : Set) : Set₁ where
  nothing : Maybe A
  just    : A → Maybe A

data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ
,#+end_src

We can show ~Maybe ℕ ≅ ℕ~ by writing two functions...
,#+begin_src haskell :tangle no
to : Maybe ℕ → ℕ
to nothing = zero
to (just n) = suc n

from : ℕ → Maybe ℕ
from zero = nothing
from (suc n) = just n
,#+end_src

...and, finally, checking that the two functions undo each other...
,#+begin_src emacs-lisp
to∘from : ∀ {n} →  to (from n)  ≡  n
to∘from n = {! try it! }

from∘to : ∀ {m} →  from (to m)  ≡  m
from∘to m = {! try it! }
,#+end_src

This is “simple”, but involved!
,#+end_tooltip
exercise to show that ℕ is fixedpoint of ~Maybe~.
#+end_src
#+end_details

# HTML Setup -- I want the code in the tooltips to look nice :-)
# +html:      <style> code, pre {color: black; background-color:Snow;} </style>
#+html:      <style> pre.tooltip {color: black; background-color:Snow;} </style>

For the tooltips containing code snippets, I've declared
the following to make the code look nice.
#+begin_src org :tangle no
,#+html:      <style> pre.tooltip {color: black; background-color:Snow;} </style>
#+end_src
# ,#+html:      <style> code, pre {color: black; background-color:Snow;}
# </style>

*** COMMENT margins MWE
   :PROPERTIES:
   :CUSTOM_ID: COMMENT-margins-MWE
   :END:
 # HTML Setup -- I want the code in the tooltips to look nice :-)
 #+html:      <style> code, pre {color: black; background-color:Snow;} </style>

 # LaTeX Setup -- For Unicode & wider margin in the examples; not needed in general!
 # ###############################################################################
 # https://armkeh.github.io/unicode-sty/
 #+latex_header: \usepackage{\string~"/unicode-sty/unicode"}
 #+latex_header: \usepackage[includemp,
 #+latex_header:             paperwidth=18.90cm,
 #+latex_header:             paperheight=24.58cm,
 #+latex_header:             top=2.170cm,
 #+latex_header:             bottom=3.510cm,
 #+latex_header:             inner=2.1835cm,
 #+latex_header:             outer=2.1835cm,
 #+latex_header:             hmargin=15mm, vmargin=20mm,
 #+latex_header:             marginparwidth=5cm,
 #+latex_header:             marginparsep=0.4cm]{geometry}
 # ###############################################################################

**** Brief Margin Note
    :PROPERTIES:
    :CUSTOM_ID: Brief-Margin-Note
    :END:

   # Quran 2:286
  /Allah[[margin:][The God of Abraham; known as Elohim in the Bible]] does not burden a soul beyond what it can bear./

**** Long Margin Note
    :PROPERTIES:
    :CUSTOM_ID: Long-Margin-Note
    :END:

  # Place the following in the margin header to change the width of the margin note.
  # :width .55\\textwidth

  It's a
   #+begin_margin simple
  We show that there is an /isomorphism/; i.e., a non-lossy protocol between ~Maybe ℕ~
  and ~ℕ~ in stages.

  First, let's recall the definitions ... in Agda ...
  #+begin_src haskell :tangle no :tangle no
data Maybe (A : Set) : Set₁ where
  nothing : Maybe A
  just    : A → Maybe A

data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ
   #+end_src

  We can show ~Maybe ℕ ≅ ℕ~ by writing two functions...
  #+begin_src haskell :tangle no
to : Maybe ℕ → ℕ
to nothing = zero
to (just n) = suc n

from : ℕ → Maybe ℕ
from zero = nothing
from (suc n) = just n
  #+end_src

  ...and, finally, checking that the two functions undo each other...
  #+begin_src emacs-lisp :tangle no
to∘from : ∀ {n} →  to (from n)  ≡  n
to∘from n = {! try it! }

from∘to : ∀ {m} →  from (to m)  ≡  m
from∘to m = {! try it! }
  #+end_src


  This is “simple”, but involved!
   #+end_margin
  exercise to show that ℕ is fixedpoint of ~Maybe~.

** Glossaries ---Define a term once, cite it with =doc:𝒳=
  :PROPERTIES:
  :CUSTOM_ID: Glossaries
  :END:

  A =doc:𝒳= link shows the documentation of 𝒳 as a tooltip in HTML, and as a glossary
  reference in LaTeX. Here 𝒳 is an Emacs Lisp function or variable, a word in the English
  dictionary ---via WordNet's =wn=, should we have it--- or, best of all, a term of our own.

  osbe-example:doc

  Our own terms are /data/ in an Org file: an entry is either a =documentation= block, which
  exports nothing, or a heading tagged =:documentation:=, which exports as an ordinary
  section. The heading's title is the term's name, its =:DOC_KEYS:= property lists the labels
  by which we cite it, and its own text is the definition. Either way, the name with
  underscores in lieu of spaces is a label too; e.g., =doc:Category_Theory=. Moreover,
  =show:GLOSSARY= lists every term the page cites, wherever it sits.

  osbe-example:documentation

  Terms we cite across many files go in a library: a list of Org files in
  ~org-docs-libraries~, whose entries ---blocks and headings alike--- every =doc:𝒳= link may
  cite. The files are read, not exported, so loading them is quick; =M-x
  org-docs-load-libraries= reloads them after an edit, and =M-x org-docs-insert= inserts a
  =doc:𝒳= link by searching all the terms we have.

  A radio target is a term too: in =A <<<monoid>>> is a set with an associative operation
  and a unit.=, the target names the term and its paragraph defines it; so =doc:monoid=
  cites it, in the same file or, from a library, in any other.

  Finally, a package's whole API makes a glossary of its own: the =package-docs= block
  exports a table of the public functions, macros, and variables that a feature defines,
  each name a =doc:𝒳= link whose tooltip is its documentation.
  #+begin_example
,#+begin_package-docs org-deflink
,#+end_package-docs
  #+end_example

** Parallel ---/Place ideas side-by-side, possibly with a separator/
  :PROPERTIES:
  :CUSTOM_ID: Parallel
  :END:

     osbe-example:parallel

** Display maths ---=#+begin_math=, wherein =red:𝒳= colours a symbol
  :PROPERTIES:
  :CUSTOM_ID: math
  :END:

  To colour a formula, LaTeX ---and MathJax, which typesets it in HTML--- would have us write
  ={\color{red} x}=; yet our prose colours by =red:x=. A math block is display maths
  wherein our links are LaTeX's: =red:ATOM= colours a ={group}=, =\left(…\right)=, a
  =\command{with}{arguments}=, a word, else one character; =[[red:][a + b]]= colours =a + b=. So too
  for =color:#ff0066=, =highlight:=, =eqref:=, web links, and =tooltip:= and =doc:=, which hover in
  HTML; as does a footnote, =x[fn::the current element]=. A tooltip in maths is as one in prose: the
  same box in HTML, and in LaTeX, a margin note, its number on =x=. Org's emphasis is read when its markers
  hug their text, as in prose: =*f(a)*= is bold, whereas =a*b*c= and =a = b= are left be.

  A line that begins =\def=, =\newcommand=, …, begins a definition, through the line that closes
  its braces: declared, but not shown ---in LaTeX, in the preamble; in HTML, hidden, whence MathJax
  knows it page-wide. A line =# …= is a comment. Below, the first block is only definitions, and so
  shows nothing.

  osbe-example:math

  The rest of Org's markup is read as one would hope:
  + An Org table is a matrix ---a =pmatrix=, or whichever environment =:matrix= names--- whose
    columns =TAB= aligns for us. As in Org, a line that begins =|= is a table; so we write
    =\lvert x \rvert= for an absolute value.
  + A line ending =:tag-COLOUR: NAME= is tagged, as in an align block, and
    =[[eqref:NAME]]= cites it; =:numbered t= numbers the rest.
  + Lines that end in =\\= are gathered, each centred on a line of its own; to line them up at
    =&=, we reach for an align block.
  + In Emacs, the block looks as a =#+begin_src latex= block does, with each =red:ATOM= in red, as
    the maths reads it; =C-c C-c= shows the maths as an image atop the block, until =C-c C-c= again,
    or an edit; and =C-c '= edits it in =latex-mode=.

  #+begin_example
,#+begin_math :numbered t :matrix bmatrix
R_{teal:\theta} =
| \cos teal:\theta | -\sin teal:\theta |
| \sin teal:\theta | \cos teal:\theta  |
,#+end_math
  #+end_example

** Aligned equations ---=#+begin_align=, cited by =eqref:𝒳=
  :PROPERTIES:
  :CUSTOM_ID: Aligned-equations
  :END:

  An align block's contents are LaTeX, aligned at each =&=; as in LaTeX, a line ends in
  =\\=, unless it ends in a tag =:tag-COLOUR: NAME=, which is =NAME= in that colour and is what
  =[[eqref:NAME]]= cites. Following such a link in Emacs visits the line; failing that, any
  =\tag{…NAME…}=, as in a math block. An =align :numbered t= numbers its untagged lines too.
  The contents are LaTeX, read as a math block's are, so =red:𝒳= colours a symbol; shorthands are
  welcome too: the :let switch gives them, as below.

  osbe-example:align

  To share shorthands among many blocks, name them once, in a table that need not itself export:
  #+begin_example
,#+begin_align :let logic
p -> q &== \neg p \lor q
,#+end_align

,* Shorthands :noexport:
,#+name: logic
| Variable | Value       |
|----------+-------------|
| ->       | \Rightarrow |
| ==       | \equiv      |
  #+end_example
  The rows above the rule are a header, and are skipped. A Lisp variable serves too, across
  documents: =(setq logic '(-> "\\Rightarrow"))= and then =:let logic=.

** Graphs ---/Org lists, drawn by Graphviz/
  :PROPERTIES:
  :CUSTOM_ID: Graphs
  :END:

  osbe-example:graph

  The graph block is opt-in, so we load it separately with
  ~(require 'org-graph-block)~. Rendering needs the =dot= executable from Graphviz:
  HTML export embeds a PNG ---or an inline SVG, with tooltips intact, via =:svg t=--- whereas
  other backends receive the dot source. Inside the block, =#+graph:=, =#+node:= and =#+edge:=
  tables set Graphviz's defaults; =C-h o org-block/graph= documents every option.

  osbe-example:smartdiagram

  Under =:smartdiagram TYPE=, the =#+graph:= rows are LaTeX's =\smartdiagramset= keys, and
  =C-M-i= completes those rather than Graphviz's; rendering needs =pdflatex=, with the
  smartdiagram package, and =pdftoppm=. Org's own markup ---=#+macro:=, =~code~=, colour
  links, src blocks--- replaces LaTeX's =\newcommand=, =\texttt=, =\textcolor=, and
  hand-tuned =\hspace='s; graphs-README.org sets the two side by side.

** Switches for every block: =:when=, =:let=, =:folded=, …
  :PROPERTIES:
  :CUSTOM_ID: Switches-for-every-block
  :END:

  Just as every src block understands =:exports= and =:results=, every block understands these
  header arguments ---ours, those made with ~org-defblock~, Org's own src, example, quote, verse,
  and center blocks, and any =#+begin_𝒳= at all, no declaration needed:

  | Switch           | Effect upon export                                                           |
  |------------------+------------------------------------------------------------------------------|
  | =:noexport t=    | Nothing at all; e.g., notes to self                                          |
  | =:when FORM=     | Nothing at all, unless the Lisp =FORM= is non-nil; it may mention =backend= |
  | =:let (VAR VAL …)= | Each whole-word =VAR=, or operator such as =->=, in the contents becomes its value, beforehand |
  | =:let NAME=      | Likewise, for the =VAR= and =VAL= of each row of the table =#+name: NAME=, else of the variable =NAME= |
  | =:ignore t=      | The contents, as plain Org; i.e., the block's own behaviour is bypassed      |
  | =:boxed TITLE=   | The result, within a box titled =TITLE=; =t= for untitled               |
  | =:folded TITLE=  | The result, folded within details titled =TITLE=; =t= for the block's name |
  | =:verbatim t=    | The block as written, sans its switches, shown as Org source                  |
  | =:verbatim demo= | That source beside what it exports to, as with org-demo           |

  osbe-example:switches

  A src block's =:folded t= is titled by its language, and its code is still exported by Org,
  as ever. Switches apply before Babel runs, so a src block's =:let= changes the code it runs,
  =:noexport= keeps it from running at all, and =:folded= folds away its results too. Other
  switches then apply to a =:verbatim= showing; e.g., =:verbatim demo :folded t= folds away a
  block's source and result alike.

  Moreover, =:C-c_C-c ACTION= gives a block an action in Emacs: pressing =C-c C-c= within it
  calls =ACTION= when it names a function, else evaluates it as a Lisp form; see C-c C-c for
  your own blocks.

  Switches are inherited as a src block's header-args are; e.g., =:header-args:red: :let (N 3)=
  in a heading's drawer gives every =red= block of its subtree that =:let=.

  A block that declares a keyword of the same name keeps it for itself; e.g., a block with
  its own =folded= argument receives =:folded= as usual. Since =:when=, =:let= and =:C-c_C-c=
  run Lisp written in the document, Emacs asks once before running each distinct form;
  ~org-defblock-evaluate-switches~ may instead allow them freely, or never.

** Callouts ---Note, tip, important, warning, caution
  :PROPERTIES:
  :CUSTOM_ID: Callouts
  :END:

  Five blocks, after GitHub's alerts, call out a paragraph with a coloured rule down its
  left under a titled heading; the title defaults to the block's name.

  osbe-example:callout

  The colours, icons, and intended uses live in ~org-callouts~. Since a heading tagged
  =:note:= is common enough to mean something else entirely, callouts claim neither tags nor
  link types.

  Exported to Markdown (=ox-md= or =ox-gfm=), a callout becomes GitHub's own alert,
  => [!WARNING]=; since alerts are untitled, a custom title becomes its bold first paragraph.
  See Markdown export for what the other blocks become.

** Colours ---=red:𝒳=, =[[color:#ff0066][𝒳]]=, and =#+begin_red=
  :PROPERTIES:
  :CUSTOM_ID: Colours-links
  :END:

  Each of the 19 colours that HTML and LaTeX's =xcolor= share ---black, blue, brown, cyan, darkgray, gray,
  green, lightgray, lime, magenta, olive, orange, pink, purple, red, teal, violet, white, and yellow--- is a
  block, a link, and a tag; =color= takes any other, by name or hex code. In Emacs, too, each such link
  shows its text in its colour, as soon as =org-special-block-extras-mode= is on.

  osbe-example:colors

** Quotations, cited ---=#+begin_quote KEY=
  :PROPERTIES:
  :CUSTOM_ID: quote-citations
  :END:

  Org's own quote block, given a bibliography key, cites it, at its pages ---the key given as the
  main argument, or as =:key=:
  #+begin_example
,#+begin_quote zermelo1908 :pages 20-22
Set theory is that branch of mathematics whose task is to investigate
the fundamental notions of number, order, and function.
,#+end_quote
  #+end_example
  In LaTeX, and so in beamer, this is csquotes' =\blockcquote[20-22]{zermelo1908}{…}=, cited by
  our bibliography ---biblatex's ~\addbibresource~, BibTeX's ~\bibliography~, or org-cite---
  which is ours to give; csquotes itself is loaded for us, unless we load it ourselves. In HTML, it is a =<blockquote>= closed by
  “--- /zermelo1908/, 20-22”; in Markdown, a quote closed likewise. A quote sans arguments is
  Org's own, as ever.

  The quoted text hugs its braces, =\blockcquote[20-22]{zermelo1908}{Set theory …function.}=, sans
  the stray spaces LaTeX would read from its newlines; so does the =contents= of any block of ours
  whose LaTeX wraps it in braces, say =(format "\\textbf{%s}" contents)=.

  As a link, a quote is inline: =[[quote:zermelo1908][set theory is …]]= is csquotes'
  =\textcquote{zermelo1908}{…}=, and =[[quote:][to be]]= is just “to be”. A section tagged
  =:quote:= is a quote of its text.

** Highlights ---Colour the background, not the text
  :PROPERTIES:
  :CUSTOM_ID: Highlights
  :END:

  Where =red:𝒳= colours text, =[[highlight:pink][𝒳]]= colours its background; the colour
  defaults to yellow, and the link shows so highlighted in Emacs too.

  osbe-example:highlight

  For the reader who would rather pick the page's background colour themself,
  =[[palette:][Pick a background]]= is a button that unfolds a palette of pale colours,
  ~org-palette-colors~; clicking one makes it the background ---try it: Pick a background.

** Page-wide CSS with =style=
  :PROPERTIES:
  :CUSTOM_ID: style-block
  :END:

  A =style= block is the page's CSS, taken verbatim; it exports to nothing but HTML.
  #+begin_example
,#+begin_style
h2 { color: teal; }
,#+end_style
  #+end_example

** Markdown export ---What survives GitHub, and how to change it
  :PROPERTIES:
  :CUSTOM_ID: Markdown-export
  :END:

  Exporting to Markdown, with =ox-md= or =ox-gfm=, our blocks see =backend= as =html=, since =md=
  derives from it; ~(org-export-markdown-p)~ tells the two apart. A Markdown renderer, such as
  GitHub's, keeps only some HTML: it strips every =style=, =class=, =<style>=, and =<font>=, yet
  keeps =<details>=, =<kbd>=, =<mark>=, =<ins>=, =<abbr title>=, =<img>=, and =$$= maths.

  + Work as-is :: =badge=, =melpa=, =kbd=, =details=, =solution=, =rename=, and =show= export
    just as they do to HTML, and so render on GitHub ---sans colours.

  + Markdown of their own :: these blocks export to Markdown idioms, rather than HTML.
    | Block                   | Markdown export                                                 |
    |-------------------------+-----------------------------------------------------------------|
    | =note=, =tip=, …        | GitHub's own alert, => [!TIP]=; a custom title is a bold line    |
    | =box=                   | a quote, opening with its title in bold                         |
    | =remark=                | a => [!NOTE]= alert, titled by its editor                        |
    | =highlight=             | =<mark>=, which GitHub shows yellow, whatever the colour        |
    | =spoiler=               | numbered blanks, with the answers folded away beneath           |
    | =tree=                  | =$$…$$= displays, as GitHub's maths knows no =\[…\]=           |
    | =org-demo=              | the source as a code block, then its result                     |
    | =doc=, =tooltip=, =kbd= | =<abbr>= with a plain-text =title=, as there is no tooltipster  |
    | =math=                  | a fenced math block, its definitions within                     |
    | =graph=                 | its image, written to its =:file= (else =graph-HASH.png=), linked |

  + Plain HTML :: every other block emits the HTML it always does, which a given Markdown
    renderer may not honour; e.g., on GitHub, colours ---=red:𝒳=, =#+begin_color=--- and
    =parallel='s columns are stripped, leaving plain, stacked text. Then there are =style=,
    =palette=, =html-export-style=, and =toggle-details=, which are HTML-only by design: they
    dress the page itself, and Markdown has no say over the page.

  Dislike how a block B exports to Markdown? Advise ~org-block/B~ on your own machine; its
  result is Org, so the export makes of it whatever it does of any Org. By way of example,
  boxes between horizontal rules:
  #+begin_src emacs-lisp
(advice-add 'org-block/box :around
            (lambda (box backend raw-contents &rest args)
              "In Markdown, a box is its bold title and text, between rules; elsewhere, as before."
              (if (org-export-markdown-p)
                  (format "-----\n*%s*\n\n%s\n-----" (car args) raw-contents)
                (apply box backend raw-contents args))))
  #+end_src

** PDF export ---The LaTeX packages our blocks need, loaded for us
  :PROPERTIES:
  :CUSTOM_ID: latex-packages
  :END:

Each block names the LaTeX packages it needs ---a box, ~xcolor~ and ~tcolorbox~; a cited quote,
~csquotes~--- and a LaTeX export that uses the block, or its link, loads them just before
=\begin{document}=. So we declare none ourselves; a package we do load, options and all, is left be.
To see what a block needs, read the ~:latex-head~ of its definition, or evaluate
~(get 'org-block/box 'org-latex-head)~ ⇒ ~("xcolor" "tcolorbox")~.

A test, tests/org-pdf-export-tests.el, keeps this honest: it compiles every example of this manual to a
PDF, and to beamer slides, declaring no packages at all. It uses LuaLaTeX, which reads Unicode such
as 𝒳 and ⇒ as is; pdflatex instead needs a ~\newunicodechar~ for each such character. Slides have no
margins, so there our margin notes, tooltips, and Org's footnotes are beamer's own footnotes.

* Make your own blocks and links ---A developer's guide
  :PROPERTIES:
  :CUSTOM_ID:   org-special-block-extras-developers-guide
  :TITLE:       org-special-block-extras: Make your own blocks and links
  :DESCRIPTION: A developer's guide to org-defblock, org-deflink, org-deftag, and the key bindings they get for free.
  :END:

  Every block and link above is made with the very tools below, so a new one of our own is a
  ~defun~ away.

** Make your own blocks with =org-defblock=
  :PROPERTIES:
  :CUSTOM_ID: Make-your-own-blocks
  :END:

  We declare a block just as we declare a function with ~cl-defun~: the block's main
  argument ---written right after =#+begin_NAME=--- is its =&optional= argument, and its
  header arguments are its =&key= arguments. In the body, ~backend~ names the current
  export backend and ~contents~ the block's Org-parsed contents.

  #+begin_src emacs-lisp
(org-defblock note (&optional (title "Note") &key (color "teal"))
  "Call out CONTENTS under TITLE, tinted COLOR."
  (pcase backend
    ('html (format "<div style=\"border-left: 4px solid %s; padding-left: 1em\"><b>%s</b>%s</div>"
                   color title contents))
    (_     (format "\\textbf{\\color{%s}%s} %s" color title contents))))
  #+end_src

  Now the following binds ~title~ to ="Heads up"= and ~color~ to =red=; omit either, and
  its default is used. The main argument may also be given by its name, as a keyword:
  =#+begin_note :title "Heads up"= is the same block.
  #+begin_example
#+begin_note "Heads up" :color red
Mind the gap.
#+end_note
  #+end_example

  For any backend derived from HTML or LaTeX ---org-reveal's, ox-hugo's, ox-gfm's, beamer's, or
  our own--- ~backend~ is =html= or =latex=, so one rendering serves them all. To single one out,
  we ask Org's own ~org-export-current-backend~; by way of example, a docsy alert in Hugo:
  #+begin_src emacs-lisp
(org-defblock noteblock (&optional (title "Note") &key (color "primary"))
  "A note: a docsy alert in Hugo, a noteblock environment in LaTeX, a box elsewhere in HTML."
  (cond ((org-export-derived-backend-p org-export-current-backend 'hugo)
         (format "{{%% alert title=\"%s\" color=\"%s\" %%}}\n%s\n{{%% /alert %%}}" title color raw-contents))
        ((equal backend 'latex) (format "\\begin{noteblock}\n%s\n\\end{noteblock}" contents))
        (t (format "<div class=\"note\">%s</div>" contents))))
  #+end_src
  In similar spirit, ~(org-export-markdown-p)~ and ~(org-export-beamer-p)~ single out Markdown and
  beamer.

  Every block is also a link, with the label as main argument and the description as
  contents: =[[note:Heads up][Mind the gap.]]=.

  A block names what its document's head needs, added once, by ~:latex-head~ and ~:html-head~; say,
  ~(org-defblock thm (&optional title :latex-head ("amsthm" "\\newtheorem{theorem}{Theorem}")) …)~. A
  LaTeX item is a package name or any preamble line; an HTML item is HTML, a symbol holding it, or
  ~mathjax~. An export that uses the block adds each item its head lacks; one that does not, adds none.
  The lists go unquoted; e.g., ~:html-head (mathjax my-html-head "<style>.aside {color: gray}</style>")~.

  Name a package, ~"amsthm"~, rather than write ~"\\usepackage{amsthm}"~: a name is left be when the
  document loads it already, options and all ---say, ~\usepackage[thmmarks]{amsthm}~--- whereas a line
  is left be only when the document has that very line; else the package loads twice, and differing
  options clash.

  Even Org's own blocks ---=quote=, =verse=, =center=, =example=, =src=, =export=, and =comment=---
  are fair game: an ~(org-defblock verse …)~ overrides every =#+begin_verse=, saying so in
  =*Messages*=. To leave some to Org, a handler hands them back; by way of example, a verse
  signed by its poet, else Org's own:
  #+begin_src emacs-lisp
(org-defblock verse (&optional poet)
  "A verse, signed by POET; sans one, Org's own verse."
  (if (org-string-nw-p poet)
      (format "\\begin{verse}\n%s\n\\end{verse}\n--- %s" contents poet)
    (org-parse (org-builtin-block "verse" raw-contents))))
  #+end_src
  Our own =quote= does just this: given a citation, it is ours; else, Org's own. Moreover, defaults may change long after the
  block is defined, just as a src block's header-args do ---there is nothing new to learn. A
  =NAME= block reads them as a src block of language =NAME= would; from weakest to strongest:
  ~(setq org-babel-default-header-args:note '((:color . "orange")))~, then
  =#+property: header-args:note :color orange= for the whole file, then =:header-args:note:= in
  a heading's drawer for its subtree ---=:header-args:note+:= adds to it--- then =#+header:=
  lines just above the block, and finally the block's own line. By way of example, every note
  in this section is orange, and the second is boxed too:
  #+begin_example
,* Exercises
:PROPERTIES:
:header-args:note: :color orange
:END:

,#+begin_note Hint
Try induction.
,#+end_note

,#+header: :boxed t
,#+begin_note Answer
By induction on n.
,#+end_note
  #+end_example
  A main argument is given by its name, as in =:title Hint=; and switches, such as =:let= and
  =:folded=, are inherited alike ---a src block of language =LANG= even takes them from Babel's
  own =header-args:LANG=. See =C-h f org--block-header-args=.

  One definition gives three uses: a block, a link, and a tag. A section tagged =:note:=
  exports as a =note= block around its own text, up to the next heading; the tag's
  underscore-separated items form the main argument ---tags cannot hold spaces--- and the
  section's properties supply keyword arguments by name. So all three of these agree:
  #+begin_example
#+begin_note "Heads up" :color red
Mind the gap.
#+end_note

[[note:Heads up][Mind the gap.]]

,* Why bother?        :note_Heads_up:
:PROPERTIES:
:COLOR: red
:END:
Mind the gap.
  #+end_example
  Likewise, the package's own blocks are links and tags too; e.g., =:details_Hint:= folds a
  section's text away under the title /Hint/. Try tagging a heading =:red:= ---or =:blue:=,
  =:teal:=, … any of the 19 colours--- and its text exports in that colour.

  Should we not want all three, the options =:link nil= and =:tag nil= decline the link and
  the tag, whereas =:block nil= keeps only the link and tag ---e.g.,
  ~(org-defblock note (&optional (title "Note") :tag nil) …)~. The variable
  ~org-defblock-links-and-tags~ sets whether blocks come with links and tags by default; its
  documentation weighs the trade-off ---chiefly namespacing: every block claims the link type
  =NAME:= and the tag =:NAME:=. So, should =:red:= already mean something else in our
  headings, we set ~org-defblock-links-and-tags~ to nil before loading this package. For just a
  link, or just a tag, there are =org-deflink= and =org-deftag=, below.

  A tag wraps only its section's own text, since a block cannot hold a heading. By way of
  example, in =* Abstract :abstract:= with a =** Aside= beneath it, the aside stays outside
  the box. Declaring =:tag [:subsections MODE]= picks what becomes of subsections:
  - =ignore= ---the default, as with =:tag t=--- leaves them outside the block;
  - =error= refuses a tagged section that has any, naming both headings; and
  - =recurse= wraps each subsection's own text in a block of its own, with the same
    arguments, unless the subsection carries the tag itself.

  A block may also say how it looks in our Org buffers, via the option =:fontify=: below,
  =#+begin_proof= shows as /Proof./, =#+end_proof= as ⏹, and the contents in italics too.
  Each part is optional; the text itself is untouched, only displayed differently.
  #+begin_src emacs-lisp
(org-defblock proof (&optional title :fontify [:begin "Proof." :end "⏹" :face 'italic]) …)
  #+end_src
  Moreover, =:keywords= shows patterns within the contents in a face of their choosing; e.g.,
  an align block shows each =:tag-blue:= as a tag, in blue, by
  #+begin_src emacs-lisp
:fontify [:keywords '((":tag-\\([^: \t\n]+\\):" 0 org--align-tag-face))]
  #+end_src
  where a face that is a function is called, with the match data at hand, for the face.

  /Convenience:/ For the terse-minded, the arglist may be flattened into the main argument
  and its default, followed by key-value pairs. The block above is then
  #+begin_src emacs-lisp
(org-defblock note (title "Note" color "teal") …)
  #+end_src

  The full story is at =C-h o org-defblock=.

** Make your own links with =org-deflink=
  :PROPERTIES:
  :CUSTOM_ID: Make-your-own-links
  :END:

  An Org link =[[NAME:label][description]]= is a function of its label and description;
  so, we declare one as we would a ~cl-defun~, then say how it exports and how it looks
  within Emacs.

  #+begin_src emacs-lisp
(org-deflink shout (label &optional description backend)
  "Shout the description, else the label."
  :face '(:weight bold :foreground "red")
  :help-echo (format "I'll shout %s" (or description label))
  :export (format (if (eq backend 'latex) "\\textbf{%s}" "<b>%s</b>")
                  (upcase (or description label))))
  #+end_src

  Then =shout:hello= and =[[shout:hello][hey there]]= export as *HELLO* and *HEY THERE*.
  The arglist names the label, description, and export backend, in that order; any may be
  omitted from the end, and =(description "…")= gives a default. Besides =:export=, the
  keys =:face=, =:help-echo=, =:follow=, =:keymap=, =:display= and =:let= customise the link
  within Emacs; =C-h o org-deflink= has the details.

  /Convenience:/ The arglist may be omitted, whence the anaphoric names ~o-label~,
  ~o-description~ and ~o-backend~ are used instead:
  #+begin_src emacs-lisp
(org-deflink shout
  "Shout the description, else the label."
  :export (upcase (or o-description o-label)))
  #+end_src

** Tags are functions of Org sections: =org-deftag=
  :PROPERTIES:
  :CUSTOM_ID: tags-are-functions-of-org-sections
  :END:

  image:https://i.redd.it/rre5ggpx9jya1.png|100%|100%|center|Musa

  Just as a special block is a function on a region of text, so too a tag is construable
  as a function on an Org section (Reddit post). By way of example, the following
  renders any section tagged =:quote:= as a =<blockquote>=.

  #+begin_src emacs-lisp
(org-deftag quote (&optional (color "black") &key cite)
  "HTML export a section as a <blockquote>, its text coloured COLOR, crediting CITE."
  (insert "\n#+html:" (format "<blockquote style=\"color: %s\">" color))
  (org-next-visible-heading 1)
  (insert (if cite (format "\n#+html: <cite>%s</cite>" cite) "") "\n#+html: </blockquote>"))
  #+end_src

  As with ~cl-defun~, the =&optional= arguments are positional: the underscore-separated
  items after the tag's name bind them in order. Any the tag omits are read from the
  section's property of the same name, and then default. The =&key= arguments are read from
  properties only ---handy for lots of named info.
  #+begin_example
,* Tags are functions of Org sections        :quote_blue:
,* Tags are functions of Org sections        :quote:
:PROPERTIES:
:COLOR: blue
:CITE: Musa
:END:
  #+end_example
  When both the tag and a property give an argument, the tag wins.

  /Convenience:/ The arglist may be flattened into name-default pairs, all positional;
  ~(org-deftag quote (color "black") …)~ is the above, sans =cite=.

  The body runs at export time, with point where the heading used to be ---it has been
  erased, along with its property drawer, so we reinsert ~o-heading~ if we want it. The body may mention
  + ~o-backend~ ---the export backend, such as =html= or =latex=;
  + ~o-heading~ ---the heading's text, sans the tag;
  + ~o-properties~ ---all of the section's properties, as a plist such as =(:color "blue")=; and
  + ~o-drawer~ ---the erased property drawer, as text, should we want it back.

  Sections without the tag are left untouched, property drawers and all.

  Often, all we want is for a section to export as one of our special blocks; for that, we
  need no tag of our own ---see the =:tag t= option of =org-defblock=, above. By way of
  example, =:details_Hint:= folds a section's text away under the title /Hint/.

  The full story is at =C-h o org-deftag=.

** =C-c C-c= for your own blocks
  :PROPERTIES:
  :CUSTOM_ID: C-c-C-c-for-your-own-blocks
  :END:

  Org's =C-c C-c= does the obvious thing at point: it runs a src block, ticks a checkbox,
  recalculates a table. Our special blocks may join in; one ~org-def-action~ gives every
  =#+begin_NAME= … =#+end_NAME= block a =C-c C-c= action, as one ~org-defblock~ gives it an export.

  For a single block, the =:C-c_C-c= switch suffices: =#+begin_quiz :C-c_C-c my/check-answers=
  makes =C-c C-c= within that block call ~my/check-answers~; a Lisp form, rather than a
  function name, is evaluated instead. For every block of a kind, we define an action:

  #+begin_src emacs-lisp
(org-defblock shout () "Upcase the contents." (upcase contents))

(org-def-action shout (&optional greeting &key (volume 1))
  "Announce the shout's GREETING, at VOLUME."
  (message "%s, at %s: %s" greeting volume raw-contents))
  #+end_src

  Then =C-c C-c= within =#+begin_shout Hello :volume 11= … =#+end_shout= says /Hello, at 11: …/.
  The arglist is the block's, in either of ~org-defblock~'s styles; the body sees the
  arguments by name ---those the block inherits, by =header-args:shout=, too--- and the
  block's text as =raw-contents=, with point within the block. A non-nil value claims the key
  press, so Org does nothing else with it; nil declines it, leaving it to the block's
  =:C-c_C-c= switch, if any.

  For a complete worked example, we may mimic the graph block's handler,
  org-graph--cc-handler. It
  + finds its block via ~(re-search-backward "^[ \t]*#\\+begin_graph\\b")~ then ~(org-special-block-after-point "graph")~;
  + reads the block's keyword arguments, so =#+begin_graph :C-c_C-c dot= changes what =C-c C-c= does;
  + honours =C-u= via ~current-prefix-arg~ ---showing the dot source rather than rendering a PNG;
  + inserts a =#+RESULTS:= section after =#+end_graph=, just as src blocks do; and
  + returns =t=, claiming the keypress.

  It is the graph's action, at the end of =org-graph-block.el=:
  #+begin_src emacs-lisp
(org-def-action graph ()
  "Render the graph at point, or show its dot source; see `org-graph--cc-handler'."
  (org-graph--cc-handler))
  #+end_src

  The dispatcher itself ---a single function on ~org-ctrl-c-ctrl-c-hook~--- lives in
  org-ctrl-c-ctrl-c-for-special-block.el.

** =C-c '= to edit a block in its own buffer
  :PROPERTIES:
  :CUSTOM_ID: C-c-quote-for-your-own-blocks
  :END:

  Just as =C-c '= edits a src block in a buffer of its language, so too it edits every special
  block ---ours, or any =#+begin_𝒳= at all--- in an Org buffer; =C-c '= again writes the contents
  back. Org keeps all it already does: a table, a link, or a src block within a special block is
  edited as ever.

  A block may instead choose its buffer's mode: the option =:edit-indirect-mode MODE= makes
  =C-c '= open the block's contents in a buffer in =MODE=. By way of example, the graph block
  is declared with ~:edit-indirect-mode org-graph-edit-mode~, an Org mode that completes Graphviz
  attributes.

  #+begin_src emacs-lisp
(org-defblock poem (&optional title :edit-indirect-mode text-mode)
  "Set CONTENTS in italics, under TITLE."
  (format "<h3>%s</h3><em>%s</em>" title contents))
  #+end_src

  For an action beyond an edit buffer, ~(org-defblock-add-edit-special-handler "poem" #'my-handler)~
  registers any function of no arguments, just as =C-c C-c= handlers are registered ---see
  org-special-block-indirect-edit.el.

** =C-c C-v C-d= to split a block in two
  :PROPERTIES:
  :CUSTOM_ID: C-c-C-v-C-d-to-split-a-block
  :END:

  Just as =C-c C-v C-d= splits a src block at point, so too it splits any special block, after
  Kaushal Modi's trick; each piece keeps the block's whole =#+begin_= line, header arguments
  and all. By way of example, with point at the start of =Two.=,
  #+begin_example
,#+begin_tip Mind
One.
Two.
,#+end_tip
  #+end_example
  becomes
  #+begin_example
,#+begin_tip Mind
One.
,#+end_tip

,#+begin_tip Mind
Two.
,#+end_tip
  #+end_example

  At a line's end, the split falls after that line; an active region is split off as a piece of
  its own; and =C-u C-c C-v C-d= puts a heading between the pieces. In a src block within a
  special block, it is the src block that is split, as ever. The command is
  ~org-special-block-split~, should you want it on a key of its own.

** Hover for a block's arguments: =eldoc=
  :PROPERTIES:
  :CUSTOM_ID: eldoc-for-blocks-and-links
  :END:

  With point on a =#+begin_NAME= or =#+end_NAME= line, or on a =NAME:= link, the echo area
  ---or eldoc-box, should we use it--- shows how the block is called, defaults and all, along
  with the first line of its docstring:
  #+begin_example
#+begin_details TITLE="Details" :background-color "#e5f5e5" :title-color "green": Enclose contents in a folded up box, for HTML.
  #+end_example
  This needs no setup beyond =org-special-block-extras-mode=, and works for our own blocks too.

  A multi-line display, such as eldoc-box, shows more beneath that line: the keys that act on the
  block ---e.g., a math block's =C-c C-c= preview and =C-c '= edit--- and two buttons: /Docs/,
  for the full story, =C-h o org-block/NAME=; and /See the manual/, for the section of this
  manual that documents it. Our own blocks declare these as =org-defblock= options:
  #+begin_example
(org-defblock shy (:hover "Prose that eldoc shows beneath the docstring's first line."
                   :manual "https://example.com/shy") ; or "#ANCHOR", a section of this manual
  "Be shy."
  contents)
  #+end_example
  An =org-deflink= takes =:hover= and =:manual= too.

  Likewise, completing on a =#+begin_= line ---=M-TAB=, or any completion popup--- offers every
  block's name beside the first line of its docstring, and Org's own blocks beside them; a popup's
  documentation pane shows the block's whole docstring.

* COMMENT Colours
  :PROPERTIES:
  :CUSTOM_ID: Colours
  :END:

Let's develop blocks for colouring text and link types for inline colouring;
e.g., color and teal.
 + E.g., ~[[brown: Hello, World!]]~ ⇒ brown: Hello, World!
 + E.g., ~brown:Friends!~
   ⇒ brown:Friends! ( Note the ‘!’ is not coloured; use ~[[...]]~ ! )

 #+begin_box :background-color custard
 Use 〔M-x list-colors-display〕 to see a list of defined colour names in Emacs
   ---see xcolor for the LaTeX side and htmlcolorcodes.com for the HTML side, or
   just visit http://latexcolor.com/ for both.
   # Use =M-: (defined-colors)= to see all colours that are supported on your Emacs.
 #+end_box

  #+html: <br>
  :Examples:
  #+BEGIN_SRC emacs-lisp :results value :wrap no :tangle no
(s-join "\n\n"
(cl-loop for c in org-special-block-extras/colors
      collect (format "#+begin_%s\n This text is %s!\n#+end_%s" c c c)))
  #+END_SRC
  :End:
#+begin_details A Picture and Block Examples

  https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/colours.jpg

  --------------------------------------------------------------------------------

  #+begin_parallel
  #+begin_black
  This text is black!
  #+end_black

  #+begin_blue
  This text is blue!
  #+end_blue

  #+begin_brown
  This text is brown!
  #+end_brown

  # #+begin_cyan
  # This text is cyan!
  # #+end_cyan

  #+begin_darkgray
  This text is darkgray!
  #+end_darkgray

  #+begin_gray
  This text is gray!
  #+end_gray

  #+begin_green
  This text is green!
  #+end_green

  #+begin_lightgray
  This text is lightgray!
  #+end_lightgray

  #+begin_lime
  This text is lime!
  #+end_lime

  #+begin_magenta
  This text is magenta!
  #+end_magenta

  #+begin_olive
  This text is olive!
  #+end_olive

  #+begin_orange
  This text is orange!
  #+end_orange

  #+begin_pink
  This text is pink!
  #+end_pink

  #+begin_purple
  This text is purple!
  #+end_purple

  #+begin_red
  This text is red!
  #+end_red

  #+begin_teal
  This text is teal!
  #+end_teal

  #+begin_violet
  This text is violet!
  #+end_violet

  #+begin_white
  This text is white!
  #+end_white

  #+begin_yellow
  This text is yellow!
  #+end_yellow

  #+end_parallel

  #+end_details

  :Header:
#+BEGIN_SRC emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Load support for 20 colour custom blocks and 20 colour link types
  #+END_SRC
  :End:
  #+html: <br>
#+begin_details Implementation of numerous colour blocks/links
  We declare a list of colors that should be available on most systems.  Then
  using this list, we evaluate the code necessary to produce the necessary
  functions that format special blocks.

  # - To add support for a colour =𝒞=, simply
  #   ~(push '𝒞 org--named-colors)~.
  # #

  By default, Org uses the ~graphicx~ LaTeX package which let's us colour text
  ---see its documentation here.  For example, in an ~#+begin_export latex~ block,
  the following produces blue coloured text.
  #+begin_example latex
{  \color{blue}  This is a sample text in blue.  }
  #+end_example
  # Below, we format colour block types to essentially format block contents like
  # this.

  #+BEGIN_SRC emacs-lisp
(defvar org--named-colors
  '(black blue brown cyan darkgray gray green lightgray lime
          magenta olive orange pink purple red teal violet white
          yellow)
  "Colours that should be available on all systems.")

(cl-loop for colour in org--named-colors
         do (eval `(org-defblock ,colour
                     (the-color "black")
                     (vector :face `(:foreground ,(format "%s" (quote ,colour))))
                     ,(format "Show text in %s color." colour)
                     (let ()
                       (format (pcase backend
                                 (`latex "\\begingroup\\color{%s}%s\\endgroup\\,")
                                 (_  "<span style=\"color:%s;\">%s</span>"))
                               (quote ,colour) contents)))))
                              #+END_SRC

  #+RESULTS:

Let's have some sanity tests...
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "It is an HTML span styled red that contains the user's text"
  [color red block]
  (⇝ (⟰ "#+begin_red
          My cool thoughts...
          ,#+end_red")
     "<span style=\"color:red;\">"
     (* anything)
     "My cool thoughts"
     (* anything)
     "</span>"))

;; We have an HTML span styled with the user's color and it contains the user's text
(deftest "It works as expected"
  [color pink block]
  (⇝ (⟰ "#+begin_color pink
          My cool thoughts...
          ,#+end_color")
     "<span style=\"color:pink;\">"
     (* anything)
     "My cool thoughts"
     (* anything)
     "</span>"))
#+end_src

  :Old:
  #+BEGIN_SRC emacs-lisp :tangle no
(defvar org--named-colors
  '(black blue brown cyan darkgray gray green lightgray lime
          magenta olive orange pink purple red teal violet white
          yellow)
  "Colours that should be available on all systems.")

(cl-loop for colour in org--named-colors
      do (eval (read (format
                      "(defun org--%s (backend contents)
                     (format (pcase backend
                     (`latex \"\\\\begingroup\\\\color{%s}%%s\\\\endgroup\\\\,\")
                     (_  \"<span style=\\\"color:%s;\\\">%%s</span>\"))
                     contents))"
                      colour colour colour))))
  #+END_SRC
  :End:

  #+end_details


  #+html: <br>
  #+begin_details Implementation of ‘color’
  For faster experimentation between colours, we provide a generic =color= block
  that consumes a color argument.

    #+begin_src emacs-lisp
(org-defblock color
  (color black)
  (vector :face (lambda (colour) `(:foreground ,(format "%s" colour))))
  "Format text according to a given COLOR, which is black by default."
  (format (pcase backend
            (`latex "\\begingroup\\color{%s}%s\\endgroup\\,")
            (`html  "<span style=\"color:%s;\">%s</span>"))
          color contents))
  #+end_src

[Posterity] Old version which did /not/ allow ~wombo~ colour:
    #+begin_src emacs-lisp :tangle no
(org-defblock color (color black    :face (lambda (colour)
           (if (member (intern colour) org--named-colors)
               `(:foreground ,(format "%s" colour))
             `(:height 300
               :underline (:color "red" :style wave)
               :overline  "red" :strike-through "red")))) nil
  "Format text according to a given COLOR, which is black by default."
  (format (pcase backend
            (`latex "\\begingroup\\color{%s}%s\\endgroup\\,")
            (`html  "<span style=\"color:%s;\">%s</span>"))
          color contents))
  #+end_src

  #+RESULTS:

  :Old:
  #+begin_src emacs-lisp :tangle no
(defun org--color (backend contents)
  "Format CONTENTS according to the ‘:color:’ they specify for BACKEND."
  (-let* (((contents′ . (&alist 'color))
           (org--extract-arguments contents 'color))
         (block-coloring
          (intern (format "org--%s" (s-trim color)))))
    (if (member (intern (s-trim color)) org--named-colors)
        (funcall block-coloring backend contents′)
      (error "Error: “#+begin_color:%s” ⇒ Unsupported colour!" color))))
  #+end_src
  :End:
  #+end_details

  Moreover, we have that the syntax =red:text= /renders/ ‘text’ with the colour red
  in *both* the Emacs interface and in exported backends.

   https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/colour_links.png

  :Old:
   #+begin_src emacs-lisp :tangle no
;; [[𝒞:text₀][text₁]] ⇒ Colour ‘textₖ’ by 𝒞, where k is 1, if present, otherwise 0.
;; If text₁ is present, it is suggested to use ‘color:𝒞’, defined below.
(cl-loop for colour in org--named-colors
         do (org-link-set-parameters
             (format "%s" colour)
              :follow `(lambda (path) (message "Colouring “%s” %s." path (quote ,colour)))
              :export `(lambda (label description backend)
                        (-let [block-colouring
                               (intern (format "org--%s" (quote ,colour)))]
                          (funcall block-colouring backend (or description label))))
              :face `(:foreground ,(format "%s" colour))))

;; Generic ‘color’ link type [[color:𝒞][text]] ⇒ Colour ‘text’ by 𝒞.
;; If 𝒞 is an unsupported colour, ‘text’ is rendered in large font
;; and surrounded by red lines.
(org-link-set-parameters "color"
   :follow (lambda (_))
   :face (lambda (colour)
           (if (member (intern colour) org--named-colors)
               `(:foreground ,(format "%s" colour))
             `(:height 300
               :underline (:color "red" :style wave)
               :overline  "red" :strike-through "red")))
 :help-echo (lambda (_ __ position)
              (save-excursion
                (goto-char position)
                (-let* (((&plist :path) (cadr (org-element-context))))
                  (if (member (intern path) org--named-colors)
                      "Colour links just colour the descriptive text"
                    (format "Error: “color:%s” ⇒ Unsupported colour!" path)))))
   :export (lambda (colour description backend)
             (-let [block-colouring
                    (intern (format "org-block/%s" colour))]
               (if (member (intern colour) org--named-colors)
                   (funcall block-colouring backend description)
                 (error "Error: “color:%s” ⇒ Unsupported colour!" colour)))))
   #+end_src
  :End:

  #+begin_center
  Observe: red:this green:is cyan:super teal:neato, purple:amigos! and this is brown ‘color’ link and this one is an orange ‘color’ link!

   +Also: If we try to use an unsupported colour ‘wombo’, we render the+
   +descriptive text larger in Emacs along with a tooltip explaining why this is
   the case; e.g., =[[color:wombo][hi]]=.+

  ~[[color:#fad][Using Hex colour code!]]~ ⇒ Using Hex colour code!  ;-)
  #+end_center

 #+latex: \vspace{1em}
 Moreover, it would be nice to extend the =color= block type to take multiple
 arguments, say, =c₁ c₂ … cₙ= such that:

 | /n/ | Behaviour                                                                          |
 |---+------------------------------------------------------------------------------------|
 | 0 | No colouring; likewise if no arguments altogether                                  |
 | 1 | Colour all entries using the given colour c₁                                       |
 | /n/ | Paragraph --region separated by a new line-- =i= is coloured by =cₖ= where =k = i mod n= |

 Besides having a colourful article, another usage I envision for this
 generalisation would be when rendering text in multiple languages; e.g., use red
 and blue to interleave Arabic poetry with its English translation.
  
* COMMENT  :fire: HTML Export Styles as Links
  :PROPERTIES:
  :CUSTOM_ID: HTML-Export-Styles-as-Links
  :END:

  It's annoying to have to introduce HTML into your Org ---especially when
  you don't know HTML and don't want to learn it just to have a pretty webpage.
  - The annoyance stems from looking around for appropriate CSS files and then
    dumping links to them into your Org.
  - Ideally, you would use Org and /declaratively/ request a theme ---from a
    pre-compiled list of themes, which you can add to.
  - Now you can! Just write =html-export-style:𝑻𝑯𝑬𝑴𝑬= anywhere in your Org file.
    + In Emacs, hover over this new link type to see a list of supported themes.
    + By default, we ship themes: =stylish_white solarized_light solarized_dark=
      =simple_gray retro_dark simple_whiteblue rethink_inline imagine_light=
      =comfy_inline default bigblow readtheorg rose latexcss=.
      # src_emacs-lisp[:exports results]{(mapcar #'car org-html-export-styles)}.

  #+begin_src emacs-lisp
(defvar org--html-export-style-choice "default"
  "This variable holds the link label declared by users.
  It is used in the hook to Org's reprocessing; `org--html-export-style-setup'.")

(defvar org-html-export-styles
      `((default . "")
        (bigblow . "#+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-bigblow.setup")
        (readtheorg . "#+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup")
        (rose . "#+HTML_HEAD: <link href=\"https://taopeng.me/org-notes-style/css/notes.css\" rel=\"stylesheet\" type=\"text/css\" />")
        (latexcss . "#+HTML_HEAD: <link rel=\"stylesheet\" href=\"https://latex.now.sh/style.min.css\" />"))
      "An alist of theme-to-setup pairs, symbols-to-strings, used by `org-link/html-export-style'.

  For live examples of many of the themes, see
  https://olmon.gitlab.io/org-themes/.

  In due time, I would like to add more, such as those linked from
  the discussion https://news.ycombinator.com/item?id=23130104.
  A nice, simple, opportunity for someone else to contribute.")
;;
;; Add a bunch more
(cl-loop for theme in '(comfy_inline imagine_light
                        rethink_inline simple_whiteblue
                        retro_dark simple_gray solarized_dark
                        solarized_light stylish_white)
         do (push (cons theme (format "#+SETUPFILE: https://gitlab.com/OlMon/org-themes/-/raw/master/src/%s/%s.theme" theme theme)) org-html-export-styles))

(defun org--html-export-style-setup (_backend)
  "Insert an HTML theme link setup, according to `org-html-export-styles'."
  (save-excursion
    (goto-char (point-min))
    (-> (or (assoc org--html-export-style-choice org-html-export-styles)
           (error  "Error: Unknown html-export-style ∷ %s ∉ '%s"
                   org--html-export-style-choice
                   (-cons* 'random 'default (mapcar 'car org-html-export-styles))))
       cdr
       (format "\n %s \n")
       insert)))

(org-deflink html-export-style
  "Add a dedicated style theme, from `org-html-export-styles'."
  [:face '(:underline "green")
   :keymap ("?" ;; Let use select new choice of style with the “?” key.
            (-let [choice (completing-read
                           "New HTML style: "
                           (cons "random" (--map (pp-to-string (car it)) org-html-export-styles)))]
              (save-excursion
                (beginning-of-line)
                (while (re-search-forward
                        (rx (seq "html-export-style:" (one-or-more word))) nil t)
                  (replace-match (concat "html-export-style:" choice))))))
   :help-echo (thread-last (cons "random" (--map (pp-to-string (car it)) org-html-export-styles))
                (-partition 4)
                (--map (s-join "     " it))
                (s-join "\n")
                (format "Press “?” to change the theme. \n\n Supported themes include:\n\n%s"))
   :let (whatdo (progn
                  (setq org--html-export-style-choice
                        (if (equal "random" o-label)
                            (seq-random-elt (mapcar 'car org-html-export-styles))
                          (intern o-label)))
                  (pcase o-label
                    ;; TODO: Move this to when the mode is enabled/disabled?
                    ("default" (remove-hook 'org-export-before-processing-hook
                                            'org--html-export-style-setup))
                    (_   (add-hook 'org-export-before-processing-hook
                                   'org--html-export-style-setup)))))
   ]
  ;; Result string, nothing.
  "")
#+end_src

* COMMENT Editor Comments
  :PROPERTIES:
  :CUSTOM_ID: editor-comments
  :END:

 “Editor Comments” are intended to be top-level first-class comments in an
 article that are inline with the surrounding text and are delimited in such a
 way that they are visible but drawing attention.  I first learned about this
 idea from Wolfram Kahl ---who introduced me to Emacs many years ago.  We
# implement editor comments as special blocks named remark.

#+begin_box Example

#+begin_parallel
_This_

#+begin_src org :tangle no :tangle no
 In LaTeX, a =remark= appears inline with the text surrounding it.
 ,#+begin_remark Bobert
 org-mode is dope, yo!
 ,#+replacewith:
 Org-mode is essentially a path toward enlightenment.
 ,#+end_remark
 Unfortunately, in the HTML rendition, the =remark= is its own paragraph and thus
 separated by new lines from its surrounding text.
#+end_src

#+html: <p><hr><p>

_Yields_

 In LaTeX, an =remark= appears inline with the text surrounding it.
 #+begin_remark Bobert
 org-mode is dope, yo!
 #+replacewith:
 Org-mode is essentially a path toward enlightenment.
 #+end_remark
 Unfortunately, in the HTML rendition, the =remark= is its own paragraph and thus
 separated by new lines from its surrounding text.
#+end_parallel
#+end_box

:Pics_old:
 #+caption: In order: Chrome, Emacs Web Wowser, Org source, PDF
 https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/edcomm.png
:End:

# | /Any new ---possibly empty--- inner lines in the =remark= are desirably preserved/ |

--------------------------------------------------------------------------------

 #+begin_details "Implementing ‘remark’, from §ection 1, with more bells and whistles" :title-color pink
 #+BEGIN_SRC emacs-lisp
(defvar org-hide-editor-comments nil
  "Should editor comments be shown in the output or not.")

(org-defblock remark
      (editor "Editor Remark" color "black" signoff "" strong nil)
; :inline-please__see_margin_block_for_a_similar_incantation ; ⇒ crashes!
[:face '(:foreground "red" :weight bold)]
"Format CONTENTS as an first-class editor comment according to BACKEND.

The CONTENTS string has an optional switch: If it contains a line
with having only ‘#+replacewith:’, then the text preceding this
clause should be replaced by the text after it; i.e., this is
what the EDITOR (the person editing) intends and so we fromat the
replacement instruction (to the authour) as such.

In Emacs, as links, editor remarks are shown with a bold red; but
the exported COLOR of a remark is black by default and it is not
STRONG ---i.e., bold---. There is an optional SIGNOFF message
that is appended to the remark.
"
  (-let* (;; Are we in the html backend?
          (tex? (equal backend 'latex))

          ;; fancy display style
          (boxed (lambda (x)
                   (if tex?
                       (concat "\\fbox{\\bf " x "}")
                     (concat "<span style=\"border-width:1px"
                             ";border-style:solid;padding:5px\">"
                             "<strong>" x "</strong></span>"))))

          ;; Is this a replacement clause?
          ((this that) (s-split "\\#\\+replacewith:" contents))
          (replacement-clause? that) ;; There is a ‘that’
          (replace-keyword (if tex?
                             "\\underline{Replace:}" "&nbsp;<u>Replace:</u>"))
          (with-keyword    (if tex? "\\underline{With:}" "<u>With:</u>"
                             ))
          (editor (format "[%s:%s" editor
                          (if replacement-clause?
                              replace-keyword
                            "")))
          (contents′ (if replacement-clause?
                         (format "%s %s %s" this
                                 (org-export (funcall boxed with-keyword))
                                 that)
                       contents))

          ;; “[Editor Comment:”
          (edcomm-begin (funcall boxed editor))
          ;; “]”
          (edcomm-end (funcall boxed "]")))

    (setq org-export-allow-bind-keywords t) ;; So users can use “#+bind” immediately
    (if org-hide-editor-comments
        ""
      (format (pcase backend
                ('latex (format "{\\color{%%s}%s %%s %%s %%s %%s}" (if strong "\\bfseries" "")))
                (_ (format "<%s style=\"color: %%s;\">%%s %%s %%s %%s</%s>" (if strong "strong" "p") (if strong "strong" "p"))))
              color edcomm-begin contents′ signoff edcomm-end))))
 #+END_SRC

 #+RESULTS:
 | :face | (:foreground red :weight bold) | :export | (lambda (label description backend) (s-replace-all `((@@ . )) (org--remark backend (or description label) label :o-link? t))) | :help-echo | (lambda (window object position) (save-excursion (goto-char position) (-let* (((&plist :path :format :raw-link :contents-begin :contents-end) (cadr (org-element-context))) (description (when (equal format 'bracket) (copy-region-as-kill contents-begin contents-end) (substring-no-properties (car kill-ring))))) (format %s |



 :Older_version:
  #+BEGIN_SRC emacs-lisp :tangle no
(defvar org-hide-editor-comments nil
  "Should editor comments be shown in the output or not.")

(defun org--edcomm (backend contents)
"Format CONTENTS as an first-class editor comment according to BACKEND.

The CONTENTS string has two optional argument switches:
1. :ed: ⇒ To declare an editor of the comment.
2. :replacewith: ⇒ [Nullary] The text preceding this clause
   should be replaced by the text after it."
  (-let* (
           ;; Get arguments
           ((contents₁ . (&alist 'ed))
            (org--extract-arguments contents 'ed))

           ;; Strip out any <p> tags
           (_ (setq contents₁ (s-replace-regexp "<p>" "" contents₁)))
           (_ (setq contents₁ (s-replace-regexp "</p>" "" contents₁)))

           ;; Are we in the html backend?
           (html? (equal backend 'html))

           ;; fancy display style
           (boxed (lambda (x)
                    (if html?
                        (concat "<span style=\"border-width:1px"
                                 ";border-style:solid;padding:5px\">"
                                 "<strong>" x "</strong></span>")
                    (concat "\\fbox{\\bf " x "}"))))

           ;; Is this a replacement clause?
           ((this that) (s-split ":replacewith:" contents₁))
           (replacement-clause? that) ;; There is a ‘that’
           (replace-keyword (if html? "&nbsp;<u>Replace:</u>"
                              "\\underline{Replace:}"))
           (with-keyword    (if html? "<u>With:</u>"
                              "\\underline{With:}"))
           (editor (format "[%s:%s"
                           (if (s-blank? ed) "Editor Comment" ed)
                           (if replacement-clause?
                               replace-keyword
                             "")))
           (contents₂ (if replacement-clause?
                          (format "%s %s %s" this
                                  (funcall boxed with-keyword)
                                  that)
                        contents₁))

           ;; “[Editor Comment:”
           (edcomm-begin (funcall boxed editor))
           ;; “]”
           (edcomm-end (funcall boxed "]")))

    (setq org-export-allow-bind-keywords t) ;; So users can use “#+bind” immediately
    (if org-hide-editor-comments
        ""
      (format (pcase backend
                ('latex "%s %s %s")
                (_ "<p> %s %s %s</p>"))
              edcomm-begin contents₂ edcomm-end))))
 #+END_SRC
:End:

 In the HTML export, the =edcomm= special block is /not/ in-line with the text
 surrounding it ---ideally, it would be inline so that existing paragraphs are
 not split into multiple paragraphs but instead have an editor's comment
 indicating suggested alterations.



Let's have some sanity tests...
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "The user's remark is enclosed in the default delimiters"
  [remark]
  (⇝ (⟰ "#+begin_remark
                   Here is some meta-commentary...
                  ,#+end_remark")
     (* anything) "[Editor Remark:"
     (* anything) "Here is some meta-commentary"
     (* anything)  "]"))

;; The other features of remark blocks should be tested;
;; but this is not a pressing, nor interesting, concern.
#+end_src

 #+end_details

--------------------------------------------------------------------------------

#+begin_details Example: No optional arguments
 #+begin_remark
 /Please/ *change* _this_ section to be more, ya know, professional.
 #+end_remark

--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark
 /Please/ *change* _this_ section to be more, ya know, professional.
 ,#+end_remark
#+end_src
#+end_details
#+begin_details "Example: Only providing a main argument ---i.e., the remark author, the editor"
 #+begin_remark Bobert
 /Please/ *change* _this_ section to be more, ya know, professional.
 #+end_remark

 #+latex: \vspace{1em}\noindent
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark Bobert
 /Please/ *change* _this_ section to be more, ya know, professional.
 ,#+end_remark
#+end_src

#+end_details
#+begin_details Example: Possibly with no contents:
 #+begin_remark Bobert
 #+end_remark
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark Bobert
 ,#+end_remark
#+end_src
#+end_details
#+begin_details "Example: Empty contents, no authour, nothing"
 #+begin_remark
 #+end_remark
 --------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark
 ,#+end_remark
#+end_src
#+end_details
#+latex: \vspace{1em}\noindent
#+begin_details Example: Possibly with an empty new line
 #+begin_remark

 #+end_remark
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark

 ,#+end_remark
#+end_src
#+end_details
#+latex: \iffalse
#+begin_details "Example: With a “#+replacewith:” clause"
 #+begin_remark
 The two-dimensional notation; e.g., $\sum_{i = 0}^n i^2$
 #+replacewith:
 A linear one-dimensional notation; e.g.,
 $(\Sigma i : 0..n \;\bullet\; i^2)$
 #+end_remark
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
 ,#+begin_remark
 The two-dimensional notation; e.g., $\sum_{i = 0}^n i^2$
 ,#+replacewith:
 A linear one-dimensional notation; e.g.,
 $(\Sigma i : 0..n \;\bullet\; i^2)$
 ,#+end_remark
#+end_src
#+end_details
#+latex: \fi
#+latex: \vspace{1em}\noindent
#+begin_details Example: Possibly “malformed” replacement clauses

Forgot the thing to be replaced…

#+begin_remark
#+replacewith:
A linear one-dimensional notation; e.g.,
$(\Sigma i : 0..n \;\bullet\; i^2)$
#+end_remark

--------------------------------------------------------------------------------

Forgot the new replacement thing…

#+begin_remark
 The two-dimensional notation; e.g., $\sum_{i = 0}^n i^2$
 #+replacewith:
#+end_remark

--------------------------------------------------------------------------------

Completely lost one's train of thought…
#+begin_parallel
 #+begin_remark
 #+replacewith:
 #+end_remark

#+columnbreak:
*Source:*

#+begin_src org :tangle no
 ,#+begin_remark
 ,#+replacewith:
 ,#+end_remark
#+end_src
#+end_parallel

#+end_details

--------------------------------------------------------------------------------

 A block to make an editorial comment could be overkill in some cases; luckily
 defblock automatically provides an associated link type for the declared
 special blocks.

 - Syntax: =[[remark:person_name][editorial remark]]=.
 - This link type exports the same as the =remark= block type;
   however, in Emacs it is shown with an ‘angry’ ---bold--- red face.

:Old_unnecessary_implementaiton:
 #+begin_src emacs-lisp -n -r
(org-link-set-parameters
 "edcomm"
  :follow (lambda (_))
  :export (lambda (label description backend)
            (org--edcomm
             backend
             (format ":ed:%s\n%s" label description)))
  :help-echo (lambda (_ __ position)
               (save-excursion
                 (goto-char position)
                 (-let [(&plist :path) (cadr (org-element-context))]
                   (format "%s made this remark" (s-upcase path)))))
  :face '(:foreground "red" :weight bold))
 #+end_src
:End:

#+begin_box Example: Terse remarks via links

#+begin_parallel :bar t
~[[edcomm:Jasim][Hello, where are you?]]~

# +html: <br>
Hello, where are you?
#+end_parallel
-------
#+begin_parallel :bar t
 The =#+replacewith:= switch ---and usual Org markup--- also works with these
 links: @@html: <br>@@ ~[[remark:Qasim][/‘j’/ #+replacewith: /‘q’/]]~

#+html: <br>
 /‘j’/ #+replacewith: /‘q’/
#+end_parallel

#+end_box

--------------------------------------------------------------------------------

 All editor comments, remarks, are disabled by declaring, in your Org file:
 #+begin_example org
,#+bind: org-hide-editor-comments t
 #+end_example
 The =#+bind:= keyword makes Emacs variables buffer-local during export
 ---it is evaluated /after/ any =src= blocks. To use it, one must declare in
 their Emacs init file the following line, which our mode
 ensures is true.
 #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref enable-mode
(setq org-export-allow-bind-keywords t)
 #+END_SRC

 | ( Remember to =C-c C-c= the =#+bind= to activate it, the first time it is written. ) |

 #+bind: org-hide-editor-comments nil

* COMMENT   /“Link Here!”/ & OctoIcons
  :PROPERTIES:
  :CUSTOM_ID: Link-Here-OctoIcons
  :END:

Use the syntax =link-here:name= to create an anchor link that alters the URL with
=#name= as in “link-here:name”
---it looks and behaves like the Github generated links for a heading.
Use case: Sometimes you want to explicitly point to a particular location in an
article, such as within a =#+begin_details= block, this is a possible way to do so.

Likewise, get OctoIcons with the syntax =octoicon:𝒳= where =𝒳= is one of =home,
link, mail, report, tag, clock=: octoicon:home, octoicon:link, octoicon:mail,
octoicon:report, octoicon:tag, octoicon:clock.

- Within =octoicon:𝒳= and =link-here:𝒳= the label =𝒳= determines the
  OctoIcon shown and the name of the local link to be created, respectively.
  + Descriptions, as in =[[link:label][description]]=, are ignored.
- Besides the HTML backend, such links are silently omitted.

#+begin_details Six OctoIcons and Implementation
The following SVGs are obtained from: https://primer.style/octicons/

#+begin_src emacs-lisp
(defvar
 org--supported-octoicons
 (-partition 2
 '(
   home
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16
   16\" width=\"16\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M16 9l-3-3V2h-2v2L8 1 0 9h2l1 5c0 .55.45 1 1 1h8c.55 0
   1-.45 1-1l1-5h2zm-4 5H9v-4H7v4H4L2.81 7.69 8 2.5l5.19 5.19L12
   14z\"></path></svg>"

   link
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16
   16\" width=\"16\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69
   3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10
   5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0
   2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5
   0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55
   13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg>"

   mail
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 14
   16\" width=\"14\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M0 4v8c0 .55.45 1 1 1h12c.55 0 1-.45
   1-1V4c0-.55-.45-1-1-1H1c-.55 0-1 .45-1 1zm13 0L7 9 1 4h12zM1
   5.5l4 3-4 3v-6zM2 12l3.5-3L7 10.5 8.5 9l3.5 3H2zm11-.5l-4-3
   4-3v6z\"></path></svg>"

   report
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16
   16\" width=\"16\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M0 2a1 1 0 011-1h14a1 1 0 011 1v9a1 1 0 01-1 1H7l-4
   4v-4H1a1 1 0 01-1-1V2zm1 0h14v9H6.5L4 13.5V11H1V2zm6
   6h2v2H7V8zm0-5h2v4H7V3z\"></path></svg>"

   tag
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 15
   16\" width=\"15\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M7.73 1.73C7.26 1.26 6.62 1 5.96 1H3.5C2.13 1 1 2.13 1
   3.5v2.47c0 .66.27 1.3.73 1.77l6.06 6.06c.39.39 1.02.39 1.41
   0l4.59-4.59a.996.996 0 000-1.41L7.73 1.73zM2.38
   7.09c-.31-.3-.47-.7-.47-1.13V3.5c0-.88.72-1.59
   1.59-1.59h2.47c.42 0 .83.16 1.13.47l6.14 6.13-4.73
   4.73-6.13-6.15zM3.01 3h2v2H3V3h.01z\"></path></svg>"

   clock
   "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 14
   16\" width=\"14\" height=\"16\"><path fill-rule=\"evenodd\"
   d=\"M8 8h3v2H7c-.55 0-1-.45-1-1V4h2v4zM7 2.3c3.14 0 5.7 2.56
   5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 011.3 8c0-3.14 2.56-5.7
   5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14
   7-7-3.14-7-7-7z\"></path></svg>"))

"An association list of supported OctoIcons.

Usage: (cadr (assoc 'ICON org--supported-octoicons))")
#+end_src

#+begin_src emacs-lisp
(org-deflink octoicon
  "Show an OctoIcon: home, link, mail, report, tag, clock"
  [:help-echo "Show an OctoIcon: home, link, mail, report, tag, clock"]
  (unless (member (intern o-label) '(home link mail report tag clock))
    (error "octoicon:%s ⇒ This label is not supported!" o-label))
  (if (not (equal o-backend 'html))
      ""
    (s-collapse-whitespace
     (cadr (assoc (intern o-label)
                  org--supported-octoicons)))))

(org-deflink link-here
  "Export a link to the current location in an Org file."
  [:help-echo (format "This is a local anchor link named “%s”" path)]
  (if (not (equal o-backend 'html))
      ""
    (format (s-collapse-whitespace
     "<a class=\"anchor\" aria-hidden=\"true\" id=\"%s\"
          href=\"#%s\">%s</a>")
    o-label o-label (cadr (assoc 'link
                             org--supported-octoicons)))))
#+end_src


# Going forward,
Going forward, it would be desirable to provide a non-whitespace alternative for
the LaTeX rendition.  More usefully, before the HTML export hook, we could place
such ‘link-here’ links before every org-title produce clickable org-headings,
similar to Github's ---the necessary ingredients are likely here.

# Moreover,
Moreover, it may be useful to have =octoicon:𝒳|url= so the resulting
OctoIcon is optionally a link to the given =url=. Another direction
would be to support more, if not all, the possible OctoIcons.

#+end_details

#+html: <br>
#+begin_org-demo Example :source-color custard :result-color custard
link-here:example-location (Click the icon and see the URL has changed!)
#+end_org-demo

#+begin_details Tests
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "It works as expected: We have an anchor with the given ID, and the default SVG chain icon."
  [link:here]
  (⇝ (⟰ "link-here:example-location (Click the icon and see the URL has changed!)")
     "<a class=\"anchor\" aria-hidden=\"true\" id=\"example-location\" href=\"#example-location\"><svg"
     (* anything)
     "</svg></a> (Click the icon and see the URL has changed!)"
     (* anything)))
#+end_src
#+end_details

* COMMENT Badge Links
  :PROPERTIES:
  :CUSTOM_ID: Badge-Links
  :END:

Badges provide a quick and colourful summary of key features of a project,
such as whether it's maintained, its license, and if it's documented.
# Badges are little coloured boxes; e.g., those found all over Github.  Such
# eye-candy can be obtained from https://shields.io/, which has many examples.

#+caption: An Emacs interface to https://shields.io/
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/badges.png

#+begin_quote
As people who are passionate about writing great code we display "badges" in our
code repositories to signal to fellow developers that we set ourselves high
standards for the code we write, think of them as the software-equivalent of
the brand on your jeans or other reliable product. --- repo-badges
#+end_quote

:Header:
#+begin_src emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The badge link types
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#+end_src

#+RESULTS:

:End:

# :style sequential
#+begin_org-demo
What are badges?

badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir

or

[[badge: Let me google that | for you! |orange|
         https://lmgtfy.app/?q=badge+shields.io&iie=1 |Elixir]]

or

badge:Let_me_*not*_google_that|for_you
#+end_org-demo

Notice that the orange:orange badge points to a URL and so is clickable, whereas
the green:green one does not point to a URL and so is not clickable.

#+begin_details Automated Tests
Let's have some sanity tests...
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "It works when all 5 arguments are provided"
  [badge]
  (⇝ (⟰ "badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir")
     "<a href=\"https://lmgtfy.app/?q=badge+shields.io&iie=1\">"
     "<img src=\"https://img.shields.io/badge/Let_me_google_that-for_you%21-orange?logo=Elixir\"></a>"))

(deftest "It works when we use link syntax with generous spaces and newlines"
  [badge]
  (⇝ (⟰ "[[badge: Let me google that | for you! | orange |
         https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir]]")

     "<a href=\"https://lmgtfy.app/?q=badge+shields.io&iie=1\">"
     (* anything)
     "<img src=\"https://img.shields.io/badge/Let%20me%20google%20that-for%20you%21-orange?logo=Elixir\">"))

(deftest "It works when only the first 2 arguments are provided; asterisks are passed unaltered into the first argument"
  [badge]
  (⇝ (⟰ "badge:Let_me_*not*_google_that|for_you")
     "<img src=\"https://img.shields.io/badge/Let_me_%2Anot%2A_google_that-for_you-nil?logo=nil\">"))

(deftest "It works when all 5 arguments are provided - URL ‘here’ makes it a local link"
  [badge]
  (⇝ (⟰ "badge:key|value|informational|here|Elixir")
     "<a id=\"key\" href=\"#key\">"
     "<img src=\"https://img.shields.io/badge/key-value-informational?logo=Elixir\"></a>"))

(deftest "We can use spaces, commas, dashes, and percentage symbols in the first argument"
  [badge]
  (⇝ (⟰ "badge:example_with_spaces,_-,_and_%|points_right_here|orange|here")
     "<a id=\"example_with_spaces,_-,_and_%\" href=\"#example_with_spaces,_-,_and_%\">"
     "<img src=\"https://img.shields.io/badge/example_with_spaces%2C_--%2C_and_%25-points_right_here-orange?logo=nil\"></a>"))

(deftest "It works when only first 2 arguments are given: Default colour & logo are green & no logo shown"
  [badge]
  (⇝ (⟰ "badge:key|value")
     "<img src=\"https://img.shields.io/badge/key-value-nil?logo=nil\">"))

(deftest "When only a key is provided, the value slot is shown as an empty green stub"
  [badge]
  (⇝ (⟰ "badge:key")
     "<img src=\"https://img.shields.io/badge/key--nil?logo=nil\">"))

(deftest "When only a value is provided, only the value is shown in a default green ---no stub for the missing key, yay"
  [badge]
  (⇝ (⟰ "badge:|value")
        "<img src=\"https://img.shields.io/badge/-value-nil?logo=nil\">"))


(deftest "It's only a green stub when provided with an empty key and empty value"
  [badge]
  (⇝ (⟰ "badge:||green")
     "<img src=\"https://img.shields.io/badge/--green?logo=nil\">"))

(deftest "It's only a green stub when we use a totally [[badge:]]"
  [badge]
  (⇝ (⟰ "[[badge:]]")
     "<img src=\"https://img.shields.io/badge/--nil?logo=nil\">"))
#+end_src
#+end_details

** Begin omitting from LaTeX output                                  :ignore:
   :PROPERTIES:
   :CUSTOM_ID: Begin-omitting-from-LaTeX-output
   :END:
#+latex: \iffalse

** Example Badges
   :PROPERTIES:
   :CUSTOM_ID: Example-Badges
   :END:

The general syntax is as follows, with *only the first 2* are mandatory,
with the colour defaulting to green, and the url and logo both to nil.
We can thus have ~badge:label|message~
:Hide:
#+begin_example org
# Standard template
badge:key|value|colour|url|logo

# Minimal template
badge:key|value

# Only show a coloured logo pointed to its location
badge:||colour|here|logo
#+end_example
:End:

+ badge:key|value|informational|here|Elixir
  ⇐ ~badge:key|value|informational|here|Elixir~
  - Standard template; with URL pointing to current location which is named =#key=
    ---click on it and look at your browser's URL ;-)

+ badge:example_with_spaces,_-,_and_%|points_right_here|orange|here
 ⇐ ~badge:example_with_spaces,_-,_and_%|points_right_here|orange|here~
  #  - Use ‘_’ to denote spaces

+ badge:no_colour|given
  ⇐ =badge:key|value=.

+ badge:empty_value||informational
  ⇐ =badge:empty_value||informational=

+ badge:|value
  ⇐ =badge:|value=

+ badge:||green ⇐ =badge:||green= ( No key; nor value! )

  Also: [[badge:]]
  ⇐ ~[[badge:]]~.
#+begin_box General Syntax
#+begin_example org
badge:your_key|its_neato_value|some_url|a_logo_as_shown_below

[[badge: your key | its neato value | some url | a logo as shown below]]

reddit-subscribe-to:exact-name-of-a-subreddit

github-stars:user-name/repository-name

github-watchers:user-name/repository-name

github-forks:user-name/repository-name

github-followers:user-name

twitter-follow:user-name

tweet:url
#+end_example

For now, only ~badge:~ badges redirect to their URL, if any, upon a user's click.
Within Emacs, hovering over a badge displays a tooltip indicating which values
corresponds to which badge fields.

You can make your /own/ badge types with
doc:org-make-badge.
#+end_box

#+begin_details org-make-badge
The implementation is a bit lengthy since it attempts to capture a useful
portion of the shilelds.io badge interface.

#+begin_src emacs-lisp
(cl-defmacro org-make-badge
  (name &optional social-shields-name social-url social-shields-url )
  "Make a link NAME whose export is presented as an SVG badge.

If the link is intend to be a social badge, then, adhering to
shield.io conventions, the appropriate SOCIAL-SHIELDS-NAME must
be given.

The SOCIAL-URL is a URL that the badge points to and it should
have a single ‘%s’ where the link label argument will go.

Some social badges have a uniform URL, but otherwise, such as
twitter, deviate and so need their own SOCIAL-SHIELDS-URL,
which has a single ‘%s’ for the link's label argument.

----------------------------------------------------------------------

E.g., to create a badge named “go”:

     (org-make-badge \"go\")

Then the following exports nicely from an Org file:

     go:key|value|blue|here|gnu-emacs"
  `(org-deflink ,(intern name)
    "Export a Shields.io badge, with general Syntax:  badge:key|value|colour|url|logo.
Precise details for each argument are shown in the Emacs tooltip for this badge."
    [:display 'full
     :follow (--> (s-split "|" path)
               (or (nth 3 it) o-label)
               (browse-url it))
    :help-echo
      (-let [ (key value color url logo)  (mapcar #'s-trim (s-split "|" o-label)) ]
        (lf-string "${o-label}
                    \nGeneral Syntax:  badge:key|value|colour|url|logo
                           Key    : ${key}
                           Value  : ${(or value \"\")}
                           Colour : ${(or color \"green\")}
                           URL    : ${(or url \"\")}
                           Logo   : ${(or logo \"\")}

                    This results in an SVG badge “[key∣value]”, where the ‘key’
                    is coloured grey and the ‘value’ is coloured ‘color’;
                    for the HTML backend, and otherwise are silently omitted.
                    Descriptions are ignored; i.e., ‘[[badge:label][description]]’
                    is the same as ‘[[badge:label]]’.

                    ► ‘key’ and ‘value’ have their underscores interpreted as spaces.
                       ⇒ ‘__’ is interpreted as an underscore;
                         Of course, you can write ‘<badge: ⋯>’, then ‘⋯’ may have multiword, spaced, content.
                       ⇒ ‘|’ is not a valid substring, but ‘-, %, ?’ are okay.

                    ► ‘|color|url|logo’ are optional;
                       ⇒ If ‘url’ is not present, the resulting badge is not a hyperlink.
                       ⇒ if ‘url’ is ‘here’ then we have a local link;
                          i.e., the resulting badge behaves like ‘link-here:key’.
                       ⇒ ‘color’ may be: ‘brightgreen’ or ‘success’,
                                         ‘red’         or ‘important’,
                                         ‘orange’      or ‘critical’,
                                         ‘lightgrey’   or ‘inactive’,
                                         ‘blue’        or ‘informational’,
                         or ‘green’, ‘yellowgreen’, ‘yellow’, ‘blueviolet’, ‘ff69b4’, etc.
                         Consult https://htmlcolorcodes.com/ to see the HEX codes of other colours.
                       ⇒ ‘logo’ examples and how they look can be found at
                          https://alhassy.com/org-special-block-extras#Example-Badge-Icons

                   See also: https://alhassy.com/org-special-block-extras#Common-Project-Badges"))]

    ;; :export #'org--link--badge
    (if (equal o-backend 'latex) ""
      (-let [ (key value color url logo)  (mapcar #'s-trim (s-split "|" o-label)) ]
        (format
         (pcase ,(if social-shields-name `(format ,social-url o-label) 'url)
           ("here" (format "<a id=\"%s\" href=\"#%s\">%%s</a>" (s-replace "%" "%%" key) (s-replace "%" "%%" key)))
           (""      "%s") ;; e.g., badge:key|value|color||logo
           ('nil    "%s") ;; e.g., badge:key|value|color
           (_ (format "<a href=\"%s\">%%s</a>"
                      (s-replace "%" "%%"
                                 ,(if social-shields-name
                                      `(format ,social-url o-label)
                                    'url)))))
         ,(if social-shields-name
              (if social-shields-url
                  `(format ,social-shields-url o-label)
                `(format "<img src=\"https://img.shields.io/%s/%s?style=social\">"
                         ,social-shields-name o-label))
            '(format "<img src=\"https://img.shields.io/badge/%s-%s-%s?logo=%s\">"
                     (url-hexify-string (s-replace "-" "--" key))
                     (url-hexify-string (s-replace "-" "--" (or value "")))
                     color
                     logo)))))))
  #+end_src

# (org-make-badge "badge")
#
# badge:hola
# (Tooltip wont show for Org comments; uncomment previous line to see tooltip!)

Notice that we can have special ~%~-HTML characters in URLs; e.g.,
~<badge:my key|my value| my
colour|https://www.google.com/search?q=hello%20world|gnu-emacs>~
⇒
<badge:my key|my value| my colour|https://www.google.com/search?q=hello%20world|gnu-emacs>.

#+end_details
:OLD:
#+begin_src emacs-lisp :tangle no
(defun org--link--badge
  (label _ backend &optional social)
  "Export a link presented as an SVG badge.

The LABEL should be of the shape ‘key|value|color|url|logo’
resulting in a badge “|key|value|” where the ‘key’
is coloured grey and the ‘value’ is coloured ‘color’.

The optional SOCIAL toggle indicates if we want an icon for
Twitter, Reddit, Github, etc, instead of a badge.
When SOCIAL is provided, we interpret LABEL as an atomic string.

+ Only the syntax ‘badge:key|value|color|url’ is supported.
  - ‘key’ and ‘value’ have their underscores interpreted as spaces.
     ⇒ Underscores are interpreted as spaces;
     ⇒ ‘__’ is interpreted as an underscore;
     ⇒ ‘|’ is not a valid substring, but ‘-, %, ?’ are okay.
  - ‘|color|url|logo’ are optional;
     if ‘url’ is ‘|here’ then the resulting badge behaves
     like ‘link-here:key’.
  - ‘color’ may be: ‘brightgreen’ or ‘success’,
                    ‘red’         or ‘important’,
                    ‘orange’      or ‘critical’,
                    ‘lightgrey’   or ‘inactive’,
                    ‘blue’        or ‘informational’,
            or ‘green’, ‘yellowgreen’, ‘yellow’, ‘blueviolet’, ‘ff69b4’, etc.
+ Such links are displayed using a SVG badges
  and so do not support the DESCRIPTION syntax
  ‘[[link:label][description]]’.
+ Besides the HTML BACKEND, such links are silently omitted."
  (-let* (((lbl msg clr url logo) (s-split "|" label))
          (_ (unless (or (and lbl msg) social)
               (error "%s\t⇒\tBadges are at least “badge:key|value”!" label)))
          ;; Support dashes and other symbols
          (_ (unless social
               (setq lbl (s-replace "-" "--" lbl)
                     msg (s-replace "-" "--" msg))
               (setq lbl (url-hexify-string lbl)
                     msg (url-hexify-string msg))))
          (img (format "<img src=\"https://img.shields.io/badge/%s-%s-%s%s\">"
                        lbl msg clr
                        (if logo (concat "?logo=" logo) ""))))
    (when social
      (-->
          `(("reddit"            "https://www.reddit.com/r/%s")
            ("github/followers"  "https://www.github.com/%s?tab=followers")
            ("github/forks"      "https://www.github.com/%s/fork")
            ("github"            "https://www.github.com/%s")
            ("twitter/follow"    "https://twitter.com/intent/follow?screen_name=%s")
            ("twitter/url"
             ,(format
               "https://twitter.com/intent/tweet?text=%s:&url=%%s"
               (s-replace "%" "%%"
                          (url-hexify-string
                           org--link--twitter-excitement)))
             ,(format
               "<img src=\"https://img.shields.io/twitter/url?url=%s\">"
               label)))
        (--filter (s-starts-with? (cl-first it) social) it)
        (car it)
        (or it (error "Badge: Unsupported social type “%s”" social))
        (setq url (format (cl-second it) label)
              img (or (cl-third it)
                      (format "<img src=\"https://img.shields.io/%s/%s?style=social\">"
                      social label)))))
    (pcase backend
        ('html (if url
                 (if (equal url "here")
                     (format "<a id=\"%s\" href=\"#%s\">%s</a>" lbl lbl img)
                   (format "<a href=\"%s\">%s</a>" url img))
               img))
        ('latex "")
        ;; Markdown syntax: [![image title](url to get image)](url to go to on click)
        (_
         (setq img (s-chop-suffix "\">" (s-chop-prefix "<img src=\"" img)))
         (format "[![badge:%s](%s)](%s)" lbl img url)))))
#+end_src
:End:

#+begin_details Example: Derived Reddit/Github/Twitter social badges

# We now form the specialised link types for social media.

# MA: Should be on when the mode is enabled?

# --------------------------------------------------------------------------------

For example, a super simple ‘badge’ link type
#+begin_src emacs-lisp
(org-make-badge "badge")
#+end_src

--------------------------------------------------------------------------------

A more involved example.
#+begin_src emacs-lisp
;; Since we're invoking a macro, the twitter-excitement is used lazily; i.e.,
;; consulted when needed instead of being evaluated once.
(defvar org-link-twitter-excitement
  "This looks super neat (•̀ᴗ•́)و:"
  "The string prefixing the URL being shared.")

(org-make-badge
 "tweet"
 "twitter/url?=url="
 (format
   "https://twitter.com/intent/tweet?text=%s:&url=%%s"
   org-link-twitter-excitement)
 "<img src=\"https://img.shields.io/twitter/url?url=%s\">"
               )
#+end_src

--------------------------------------------------------------------------------

A few more in one, convoluted, go.
#+begin_src emacs-lisp
;; MA: I don't think this is ideal for long-term maintainability, see ‘:OLD’ below.
(cl-loop for (social url name)
         in '(("reddit/subreddit-subscribers" "https://www.reddit.com/r/%s" "reddit")
             ("github" "https://www.github.com/%s")
             ("github/stars" "https://github.com/%s")      ; Its Star button; /stars is no page
             ("github/watchers" "https://github.com/%s")   ; Its Watch button; /watchers needs a login
             ("github/followers" "https://www.github.com/%s?tab=followers")
             ("github/forks" "https://www.github.com/%s/fork")
             ("twitter/follow" "https://twitter.com/intent/follow?screen_name=%s"))
         for name′ = (or name (s-replace "/" "-" social))
         do (eval `(org-make-badge ,name′ ,social ,url)))
#+end_src
:OLD:
#+begin_src emacs-lisp :tangle no
(org-make-badge
 "twitter-follow"
 "twitter/follow"
 "https://twitter.com/intent/follow?screen_name=%s")


(org-make-badge
 "reddit" "reddit/subreddit-subscribers" "https://www.reddit.com/r/%s")

(org-make-badge
 "github"
 "github"
 "https://www.github.com/%s")

(org-make-badge
 "github-followers"
 "github/followers"
 "https://www.github.com/%s?tab=followers")

(org-make-badge
 "github-stars"
 "github/stars"
 "https://www.github.com/%s/stars")

(org-make-badge
 "github-forks"
 "github/forks"
 "https://www.github.com/%s/fork")

(org-make-badge
 "github-watchers"
 "github/watchers"
 "https://www.github.com/%s/watchers")
#+end_src
:END:
#+end_details

Here are some examples.

+ Things I like:
  reddit:emacs
  reddit:common_lisp
  reddit:coolguides
  reddit:shia
  # reddit-subscribe-to:LispMemes
  # reddit-subscribe-to:ProgrammerHumor

+ Info about my cheatsheets:
  github-stars:alhassy/CheatSheet
  github-watchers:alhassy/CheatSheet
  github-forks:alhassy/CheatSheet
  tweet:https://github.com/alhassy/org-special-block-extras

+ My profile:
  github-followers:alhassy
  twitter-follow:musa314

** Example Colours
   :PROPERTIES:
   :CUSTOM_ID: Example-Colours
   :END:

#+begin_org-demo
+ badge:|red|red badge:|critical|critical
+ badge:|blue|blue badge:|informational|informational
+ badge:|brightgreen|brightgreen badge:|success|success
+ badge:|orange|orange badge:|important|important
+ badge:|lightgrey|lightgrey badge:|inactive|inactive
+ badge:|green|green
+ badge:|yellowgreen|yellowgreen
+ badge:|yellow|yellow
+ badge:|blueviolet|blueviolet
+ badge:|ff69b4|ff69b4
+ badge:|9cf|9cf
+ ...

Consult https://htmlcolorcodes.com/ to see the HEX code of any other colour you
wish to use; e.g., badge:|1d8348|1d8348
#+end_org-demo

** Example Badge Icons
   :PROPERTIES:
   :CUSTOM_ID: Example-Badge-Icons
   :END:

 Here are a few free SVG icons for popular brands from https://simpleicons.org/.

 To use any of the names below, just write, say,
 ~badge:||grey||SVG-NAME-HERE~.

#+macro: showicon badge:||grey||$1  $1

#+begin_parallel 4 :bar t
 + “Fire” ::
   - {{{showicon(Elixir)}}}
   - {{{showicon(tinder)}}}
   - {{{showicon(codeigniter)}}}
   - {{{showicon(prometheus)}}}
   - {{{showicon(sparkpost)}}}

--------------------------------------------------------------------------------

 + “Messaging” ::
    - {{{showicon(quip)}}}
    - {{{showicon(WeChat)}}}
    - {{{showicon(google-hangouts)}}}
    - {{{showicon(hackhands)}}}
    - {{{showicon(google-messages)}}}
    - {{{showicon(Slack)}}}
    # Tor badge:||grey|here|Tor

--------------------------------------------------------------------------------

 + “Emacs” ::
    - {{{showicon(gnu-emacs)}}}
    - {{{showicon(spacemacs)}}}
    - {{{showicon(vim)}}}
    - {{{showicon(neovim)}}}
    - {{{showicon(gnu)}}}
    - {{{showicon(github)}}}
    - {{{showicon(acm)}}}
    - {{{showicon(wikipedia)}}}
    - {{{showicon(microsoft-excel)}}}
    - {{{showicon(microsoft-word)}}}
    - {{{showicon(dropbox)}}}
    - {{{showicon(google-scholar)}}}
    - {{{showicon(google)}}}
    - {{{showicon(google-translate)}}}
    - {{{showicon(ghost)}}}
    - {{{showicon(helm)}}}
    - {{{showicon(apache-openoffice)}}}
    - {{{showicon(buffer)}}}
    - {{{showicon(adobe-fonts)}}}
    - {{{showicon(google-calendar)}}}

--------------------------------------------------------------------------------

 + “Social” ::
    - {{{showicon(google-cast)}}}
    - {{{showicon(youtube)}}}
    - {{{showicon(discord)}}}
    - {{{showicon(facebook)}}}
    - {{{showicon(google-hangouts)}}}
    - {{{showicon(whatsapp)}}}
    - {{{showicon(skype)}}}
      # - {{{showicon(arxive)}}}
    - {{{showicon(reddit)}}}
    - {{{showicon(stack-overflow)}}}
    - {{{showicon(stack-exchange)}}}
    - {{{showicon(linkedin)}}}
    - {{{showicon(twitter)}}}
    - {{{showicon(jabber)}}}

--------------------------------------------------------------------------------

 + “Lightbulb” ::
    - {{{showicon(lighthouse)}}}
    - {{{showicon(google-keep)}}}
    - {{{showicon(minds)}}}

--------------------------------------------------------------------------------

 + “Programming” ::
     - {{{showicon(git)}}}
     - {{{showicon(ruby)}}}
     - {{{showicon(scala)}}}
     - {{{showicon(OCaml)}}}
     - {{{showicon(javascript)}}}
     - {{{showicon(gnu-bash)}}}
     - {{{showicon(powershell)}}}
     - {{{showicon(LaTeX)}}}
     - {{{showicon(java)}}}
     - {{{showicon(kotlin)}}}
     - {{{showicon(haskell)}}}
     - {{{showicon(coffeescript)}}}
     - {{{showicon(purescript)}}}
     - {{{showicon(rust)}}}
     - {{{showicon(typescript)}}}
     - {{{showicon(css3)}}}
     - {{{showicon(python)}}}
     - {{{showicon(c)}}}
     - {{{showicon(clojure)}}}
     - {{{showicon(lua)}}}
     - {{{showicon(adobe-acrobat-reader)}}}
     - {{{showicon(perl)}}}
    # c-+-+              badge:||grey|here|c-+-+
    # c#                 badge:||grey|here|c#

--------------------------------------------------------------------------------

 + “Miscellaneous” ::
     - {{{showicon(read-the-docs)}}}
     - {{{showicon(buy-me-a-coffee)}}}
     - {{{showicon(gimp)}}}
     - {{{showicon(mega)}}}
     - {{{showicon(nintendo-3ds)}}}
     - {{{showicon(paypal)}}}
     - {{{showicon(pinboard)}}}
     - {{{showicon(mocha)}}}
     - {{{showicon(Gitea)}}}
     - {{{showicon(instacart)}}}
     - {{{showicon(openStreetMap)}}}
     - {{{showicon(amazon)}}}
     - {{{showicon(svg)}}}
     - {{{showicon(rss)}}}
     - {{{showicon(swagger)}}}
     - {{{showicon(pastebin)}}}
     - {{{showicon(skyliner)}}}
     - {{{showicon(iTunes)}}}
     - {{{showicon(gulp)}}}
     - {{{showicon(leaflet)}}}
     - {{{showicon(youtube-gaming)}}}
     - {{{showicon(GIMP)}}}
     - {{{showicon(atom)}}}

    # pokemon            badge:||grey|here|pokemon
   #                     badge:||grey|here|1001-track-lists
   #                     badge:||grey|here|auda-city
   #                     badge:||grey|here|dribble
#+end_parallel

** Common Project Badges ---with copyable source
   :PROPERTIES:
   :CUSTOM_ID: Common-Project-Badges
   :END:

#+macro: withsrc  $1 @@html:<details><summary>src</summary>@@ ~$1~ @@html:</details>@@

# +begin_org-demo :style sequential

+ {{{withsrc(badge:Emacs|23/26/28|green|https://www.gnu.org/software/emacs|gnu-emacs)}}}
+ {{{withsrc(badge:Org|9.3.6|blue|https://orgmode.org|gnu)}}}
+ {{{withsrc([[badge:org-special-block-extras|1.0|informational|https://alhassy.com/org-special-block-extras|Gnu-Emacs][org-special-block-extras badge]])}}}
  # + twitter:https://github.com/alhassy/org-special-block-extras
+ {{{withsrc([[badge:melpa|pending|critical|https://github.com/alhassy/emacs.d#use-package-the-start-of-initel|github][melpa badge]])}}}
+ {{{withsrc([[badge:docs|literate|success|https://github.com/alhassy/emacs.d#what-does-literate-programming-look-like|read-the-docs][read-the-docs badge]])}}}
  {{{withsrc(badge:wiki|github|informational|here|wikipedia)}}}
+ {{{withsrc(badge:code_coverage|88%|green|here|codecov)}}}
  {{{withsrc(badge:build|passing|success|here|azure-pipelines)}}}
+ {{{withsrc(badge:author|musa_al-hassy|purple|https://alhassy.github.io/|nintendo-3ds)}}}
+ {{{withsrc(badge:author|musa_al-hassy|purple|https://alhassy.github.io/|gimp)}}}
+ {{{withsrc([[badge:license|GNU_3|informational|https://www.gnu.org/licenses/gpl-3.0.en.html|read-the-docs][gnu 3 license badge]])}}}
+ {{{withsrc(badge:issue_tracking|github|informational|here|github)}}}
+ {{{withsrc(badge:help_forum|discourse|informational|here|discourse)}}}
+ {{{withsrc(badge:social_chat|gitter|informational|https://gitter.im/explore|gitter)}}}
+ {{{withsrc(badge:Maintained?|yes|success)}}}
  {{{withsrc(badge:Maintained?|no|critical)}}}
  {{{withsrc(badge:No_Maintenance_Intended|×|critical|http://unmaintained.tech/)}}}
+ {{{withsrc(badge:website|up|success)}}}
  {{{withsrc(badge:website|down|critical)}}}
+ {{{withsrc(badge:Ask_me|anything|1abc9c)}}}
  {{{withsrc(badge:contributions|welcome|green|https://github.com/alhassy/org-special-block-extras/issues)}}}
+
  # Org macro args are delimited by ‘,’!
  # Wont show correctly: {{{withsrc(badge:Made_with|Python,_LaTeX,_MathJax,_and_Emacs_Org-mode|1f425)}}}
  badge:Made_with|Python,_LaTeX,_MathJax,_and_Emacs_Org-mode|1f425
  @@html: <details><summary>src</summary>@@
  ~badge:Made_with|Python,_LaTeX,_MathJax,_and_Emacs_Org-mode|1f425~
  @@html: </details>@@

# +end_org-demo
** End omitting from LaTeX output                                    :ignore:
   :PROPERTIES:
   :CUSTOM_ID: End-omitting-from-LaTeX-output
   :END:
 #+latex: \fi
** Next Steps
  :PROPERTIES:
  :CUSTOM_ID: Next-Steps-badges
  :END:

Going forward, it would be desirable to provide non-whitespace alternatives for
the LaTeX backend. {{{newline}}} That is why no examples are shown in the PDF It
may be useful to colour the =|=-separated fields of a badge link.
# This would make the interface more welcoming to new users.
* COMMENT Tooltips for Glossaries, Dictionaries, and Documentation
  :PROPERTIES:
  :CUSTOM_ID: Tooltips-for-Glossaries-Dictionaries-and-Documentation
  :END:

# TODO: The main difference between “doc” and “margin” is that the latter admits a block form,
# whereas the former only admits a link form. We can merge the two into a single type.

# Motivation for doc as block-type#
#
#   The ~doc~ link is for explanatory remarks, documentation, or personal glossary that is
#   intended to be used in multiple places.
# 
#   However, sometimes we want a “one-off” remark, containing, say, references or additional
#   explanation and we want it without the ceremony of first defining a glossary term
#   then invoking it. Enter the ~margin~ link. For example:
#       
# The use of ~doc:𝒳~ --- and documentation --- are for explanatory remarks, personal
# documentation, or glossary, that is intended to be used in multiple places.
# However, sometimes we want a “one-off” remark containing, say, references or
# additional explanation; for that we provide margin.


** Intro, motivating examples                                        :ignore:
   :PROPERTIES:
   :CUSTOM_ID: COMMENT-Intro
   :END:

   Sometimes I want to use the same tooltip multiple times, so I write
   the tooltip content once in a documentation block and then
   reference it using the the doc link type.

   # For instance,
   
   #+begin_documentation Category Theory :label "cat"
   A theory of typed composition; e.g., typed monoids, such as matrices and matrix multiplication.
   #+end_documentation

   Now I can reference this documentation entry using its label as in
   doc:cat or using its full entry name, with spaces replaced by
   underscores, as in doc:Category_Theory; finally, we can also use
   descriptions as in graphs + monoids. 

   The ~:label~ is optional; when not provided it defaults to the name of
   the entry with spaces replaced by ‘_’.  For more, see
   doc:org-block/documentation.  Entry names do not need to be unique,
   but labels do!  ( The labels are like the addresses used to look up a
   person's home. )
      
   In this way, I can create a custom glossary.

   An entry may also be a heading ---an Org file as data--- tagged =:documentation:=; its
   title is the name, its =:DOC_KEYS:= property holds space-separated labels, and its own
   text is the entry. Unlike the block, the heading exports as an ordinary section.
   #+begin_example
,* Category Theory                                            :documentation:
:PROPERTIES:
:DOC_KEYS: cat cats
:END:
A theory of typed composition; e.g., typed monoids.
   #+end_example
   Entries are read afresh before each export, so =show:GLOSSARY= lists every citation in a
   single export, wherever it sits; and the files in ~org-docs-libraries~ are read, not
   exported, so loading them is quick.

   My personal documentation library can be seen here:
   badge:Htmlized|Org|green|https://github.com/alhassy/org-special-block-extras/blob/master/documentation.org
   or
   badge:Pretty|HTML|green|https://alhassy.com/personal-glossary

   
   Moreover, the  doc link type lets me reference Emacs-documentation such as
   doc:loop or doc:thread-last, and English-dictionary entries such as
   doc:happiness.

   Finally, *in Emacs*, these links also have tooltips ☺️
   As it stands, Emacs tooltips *only* appear after an export has happened:
   The export updates the dictionary variable which is used for the tooltips
   utility.
   TODO: Make a method docs-update to update the docs database, regardless of
   export. Low priority. THIS EXISTS AS (org-docs-load-libraries) ??

   Notice how hovering over items makes them appear, but to make them disappear you
   should click on them or scroll away.  This is ideal when one wants to have
   multiple ‘definitions’ visible ;-)

--------------------------------------------------------------------------------
   
# LaTeX does not allow figures in minipages, so just ignoring them in Latex
# export
#+latex: \iffalse
#+begin_details Eye-candy ---A gallery of images
#+caption: Tooltips for documentation and glossary items --in the browser!
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_browser.png

#+caption: Tooltips for documentation and glossary items --in Emacs!
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_emacs.png

#+caption: Tooltips for documentation and glossary items --in the PDF!
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_pdf.png

:Hide:
#+caption: Declaring documentation-glossary items
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/tooltips_declaration.png
:End:

#+end_details
#+latex: \fi

# Moreover, a documentation block may have multiple entries ---the =:name:= argument
# must appear first, then the =:label:=, and the remaining text is the
# description-documentation of the given name.
#+end_quote

Below are the entries in my personal glossary ;-)
#+begin_src emacs-lisp :exports results :results replace value :results table pp replace :tangle no
(ignore-errors (--map (concat "doc:" it) (mapcar #'car org--docs-from-libraries)))
#+end_src
# or ...
#+begin_src emacs-lisp :wrap box :exports results :tangle no
(org-docs-load-libraries)
(ignore-errors (s-join "\n" (reverse (--map (concat "doc:" it) (mapcar #'car org--docs-from-libraries)))))
#+end_src

#+begin_box
doc:cat
doc:category_theory
doc:Category_Theory
doc:cat
doc:existential_angst
doc:Existential_Angst
doc:ex-angst
doc:existential_angsty
doc:Existential_Angsty
doc:nil
doc:nil
doc:hussain
doc:Hussain
doc:Karbala
doc:Cosmic_Tragedy
doc:hello
doc:Hello
doc:nil
doc:graph
doc:Graph
doc:nil
doc:expression
doc:Expression
doc:nil
doc:induction
doc:Induction
doc:nil
doc:textual_substitution
doc:Textual_Substitution
doc:nil
doc:inference_rule
doc:Inference_Rule
doc:nil
doc:logic
doc:Logic
doc:nil
doc:theorem
doc:Theorem
doc:nil
doc:metatheorem
doc:Metatheorem
doc:nil
doc:calculus
doc:Calculus
doc:Propositional_Calculus
doc:semantics
doc:Semantics
doc:Axiomatic_Semantics
doc:Operational_Semantics
doc:calculational_proof
doc:Calculational_Proof
doc:nil
doc:programming
doc:Programming
doc:nil
doc:specification
doc:Specification
doc:nil
doc:proving_is_programming
doc:Proving_is_Programming
doc:nil
doc:algorithmic_problem_solving
doc:Algorithmic_Problem_Solving
doc:nil
doc:natural_transformation
doc:Natural_Transformation
doc:nat-trans
doc:polymorphism
doc:category_theory
doc:Category_Theory
doc:associative
doc:Associative
doc:nil
doc:identity
doc:Identity
doc:nil
doc:distributive
doc:Distributive
doc:nil
doc:commutative
doc:Commutative
doc:nil
doc:reflexive
doc:Reflexive
doc:nil
doc:transitive
doc:Transitive
doc:nil
doc:symmetric
doc:Symmetric
doc:nil
doc:antisymmetric
doc:Antisymmetric
doc:nil
doc:asymmetric
doc:Asymmetric
doc:nil
doc:preorder
doc:Preorder
doc:nil
doc:equivalence
doc:Equivalence
doc:nil
doc:linear
doc:Linear
doc:nil
doc:semilinear
doc:Semilinear
doc:nil
doc:univalent
doc:Univalent
doc:nil
doc:total
doc:Total
doc:nil
doc:map
doc:Map
doc:nil
doc:surjective
doc:Surjective
doc:nil
doc:injective
doc:Injective
doc:nil
doc:bijective
doc:Bijective
doc:nil
doc:iso
doc:Iso
doc:nil
doc:difunctional
doc:Difunctional
doc:nil
doc:nil
doc:hussain
doc:Hussain
doc:Karbala
doc:Cosmic_Tragedy
doc:hello
doc:Hello
doc:nil
doc:graph
doc:Graph
doc:nil
doc:expression
doc:Expression
doc:nil
doc:induction
doc:Induction
doc:nil
doc:textual_substitution
doc:Textual_Substitution
doc:nil
doc:inference_rule
doc:Inference_Rule
doc:nil
doc:logic
doc:Logic
doc:nil
doc:theorem
doc:Theorem
doc:nil
doc:metatheorem
doc:Metatheorem
doc:nil
doc:calculus
doc:Calculus
doc:Propositional_Calculus
doc:semantics
doc:Semantics
doc:Axiomatic_Semantics
doc:Operational_Semantics
doc:calculational_proof
doc:Calculational_Proof
doc:nil
doc:programming
doc:Programming
doc:nil
doc:specification
doc:Specification
doc:nil
doc:proving_is_programming
doc:Proving_is_Programming
doc:nil
doc:algorithmic_problem_solving
doc:Algorithmic_Problem_Solving
doc:nil
doc:natural_transformation
doc:Natural_Transformation
doc:nat-trans
doc:polymorphism
doc:category_theory
doc:Category_Theory
doc:cat
doc:associative
doc:Associative
doc:nil
doc:identity
doc:Identity
doc:nil
doc:distributive
doc:Distributive
doc:nil
doc:commutative
doc:Commutative
doc:nil
doc:reflexive
doc:Reflexive
doc:nil
doc:transitive
doc:Transitive
doc:nil
doc:symmetric
doc:Symmetric
doc:nil
doc:antisymmetric
doc:Antisymmetric
doc:nil
doc:asymmetric
doc:Asymmetric
doc:nil
doc:preorder
doc:Preorder
doc:nil
doc:equivalence
doc:Equivalence
doc:nil
doc:linear
doc:Linear
doc:nil
doc:semilinear
doc:Semilinear
doc:nil
doc:univalent
doc:Univalent
doc:nil
doc:total
doc:Total
doc:nil
doc:map
doc:Map
doc:nil
doc:surjective
doc:Surjective
doc:nil
doc:injective
doc:Injective
doc:nil
doc:bijective
doc:Bijective
doc:nil
doc:iso
doc:Iso
doc:nil
doc:difunctional
doc:Difunctional
doc:nil
doc:nil
doc:hussain
doc:Hussain
doc:Karbala
doc:Cosmic_Tragedy
doc:hello
doc:Hello
doc:nil
doc:graph
doc:Graph
doc:nil
doc:expression
doc:Expression
doc:nil
doc:induction
doc:Induction
doc:nil
doc:textual_substitution
doc:Textual_Substitution
doc:nil
doc:inference_rule
doc:Inference_Rule
doc:nil
doc:logic
doc:Logic
doc:nil
doc:theorem
doc:Theorem
doc:nil
doc:metatheorem
doc:Metatheorem
doc:nil
doc:calculus
doc:Calculus
doc:Propositional_Calculus
doc:semantics
doc:Semantics
doc:Axiomatic_Semantics
doc:Operational_Semantics
doc:calculational_proof
doc:Calculational_Proof
doc:nil
doc:programming
doc:Programming
doc:nil
doc:specification
doc:Specification
doc:nil
doc:proving_is_programming
doc:Proving_is_Programming
doc:nil
doc:algorithmic_problem_solving
doc:Algorithmic_Problem_Solving
doc:nil
doc:natural_transformation
doc:Natural_Transformation
doc:nat-trans
doc:polymorphism
doc:category_theory
doc:Category_Theory
doc:cat
doc:associative
doc:Associative
doc:nil
doc:identity
doc:Identity
doc:nil
doc:distributive
doc:Distributive
doc:nil
doc:commutative
doc:Commutative
doc:nil
doc:reflexive
doc:Reflexive
doc:nil
doc:transitive
doc:Transitive
doc:nil
doc:symmetric
doc:Symmetric
doc:nil
doc:antisymmetric
doc:Antisymmetric
doc:nil
doc:asymmetric
doc:Asymmetric
doc:nil
doc:preorder
doc:Preorder
doc:nil
doc:equivalence
doc:Equivalence
doc:nil
doc:linear
doc:Linear
doc:nil
doc:semilinear
doc:Semilinear
doc:nil
doc:univalent
doc:Univalent
doc:nil
doc:total
doc:Total
doc:nil
doc:map
doc:Map
doc:nil
doc:surjective
doc:Surjective
doc:nil
doc:injective
doc:Injective
doc:nil
doc:bijective
doc:Bijective
doc:nil
doc:iso
doc:Iso
doc:nil
doc:difunctional
doc:Difunctional
doc:nil
doc:category_theory
doc:Category_Theory
doc:cat
doc:existential_angst
doc:Existential_Angst
doc:ex-angst
doc:existential_angsty
doc:Existential_Angsty
doc:nil
doc:nil
doc:hussain
doc:Hussain
doc:Karbala
doc:Cosmic_Tragedy
doc:hello
doc:Hello
doc:nil
doc:graph
doc:Graph
doc:nil
doc:expression
doc:Expression
doc:nil
doc:induction
doc:Induction
doc:nil
doc:textual_substitution
doc:Textual_Substitution
doc:nil
doc:inference_rule
doc:Inference_Rule
doc:nil
doc:logic
doc:Logic
doc:nil
doc:theorem
doc:Theorem
doc:nil
doc:metatheorem
doc:Metatheorem
doc:nil
doc:calculus
doc:Calculus
doc:Propositional_Calculus
doc:semantics
doc:Semantics
doc:Axiomatic_Semantics
doc:Operational_Semantics
doc:calculational_proof
doc:Calculational_Proof
doc:nil
doc:programming
doc:Programming
doc:nil
doc:specification
doc:Specification
doc:nil
doc:proving_is_programming
doc:Proving_is_Programming
doc:nil
doc:algorithmic_problem_solving
doc:Algorithmic_Problem_Solving
doc:nil
doc:natural_transformation
doc:Natural_Transformation
doc:nat-trans
doc:polymorphism
doc:category_theory
doc:Category_Theory
doc:cat
doc:associative
doc:Associative
doc:nil
doc:identity
doc:Identity
doc:nil
doc:distributive
doc:Distributive
doc:nil
doc:commutative
doc:Commutative
doc:nil
doc:reflexive
doc:Reflexive
doc:nil
doc:transitive
doc:Transitive
doc:nil
doc:symmetric
doc:Symmetric
doc:nil
doc:antisymmetric
doc:Antisymmetric
doc:nil
doc:asymmetric
doc:Asymmetric
doc:nil
doc:preorder
doc:Preorder
doc:nil
doc:equivalence
doc:Equivalence
doc:nil
doc:linear
doc:Linear
doc:nil
doc:semilinear
doc:Semilinear
doc:nil
doc:univalent
doc:Univalent
doc:nil
doc:total
doc:Total
doc:nil
doc:map
doc:Map
doc:nil
doc:surjective
doc:Surjective
doc:nil
doc:injective
doc:Injective
doc:nil
doc:bijective
doc:Bijective
doc:nil
doc:iso
doc:Iso
doc:nil
doc:difunctional
doc:Difunctional
doc:hussain
doc:Hussain
doc:Karbala
doc:Cosmic_Tragedy
doc:hello
doc:Hello
doc:nil
doc:graph
doc:Graph
doc:nil
doc:expression
doc:Expression
doc:nil
doc:induction
doc:Induction
doc:nil
doc:textual_substitution
doc:Textual_Substitution
doc:nil
doc:inference_rule
doc:Inference_Rule
doc:nil
doc:logic
doc:Logic
doc:nil
doc:theorem
doc:Theorem
doc:nil
doc:metatheorem
doc:Metatheorem
doc:nil
doc:calculus
doc:Calculus
doc:Propositional_Calculus
doc:semantics
doc:Semantics
doc:Axiomatic_Semantics
doc:Operational_Semantics
doc:calculational_proof
doc:Calculational_Proof
doc:nil
doc:programming
doc:Programming
doc:nil
doc:specification
doc:Specification
doc:nil
doc:proving_is_programming
doc:Proving_is_Programming
doc:nil
doc:algorithmic_problem_solving
doc:Algorithmic_Problem_Solving
doc:nil
doc:natural_transformation
doc:Natural_Transformation
doc:nat-trans
doc:polymorphism
doc:category_theory
doc:Category_Theory
doc:cat
doc:associative
doc:Associative
doc:nil
doc:identity
doc:Identity
doc:nil
doc:distributive
doc:Distributive
doc:nil
doc:commutative
doc:Commutative
doc:nil
doc:reflexive
doc:Reflexive
doc:nil
doc:transitive
doc:Transitive
doc:nil
doc:symmetric
doc:Symmetric
doc:nil
doc:antisymmetric
doc:Antisymmetric
doc:nil
doc:asymmetric
doc:Asymmetric
doc:nil
doc:preorder
doc:Preorder
doc:nil
doc:equivalence
doc:Equivalence
doc:nil
doc:linear
doc:Linear
doc:nil
doc:semilinear
doc:Semilinear
doc:nil
doc:univalent
doc:Univalent
doc:nil
doc:total
doc:Total
doc:nil
doc:map
doc:Map
doc:nil
doc:surjective
doc:Surjective
doc:nil
doc:injective
doc:Injective
doc:nil
doc:bijective
doc:Bijective
doc:nil
doc:iso
doc:Iso
doc:nil
doc:difunctional
doc:Difunctional
doc:nil
#+end_box

In the export, it looks like some names are repeated, but in the source one
would notice that we have /labels/ in both upper and lower cases and with underscores ;-)
They just happen to be referring to the same /named/ entry.

#+end_details

#+begin_details Tests
#+begin_src emacs-lisp :tangle tests.el :comments link
(deftest "It gives a tooltip whose title is the Lisp docs of APPLY"
  [doc]
  (⇝ (⟰ "doc:apply")
     "<abbr class=\"tooltip\" title=\""
     (literal (s-replace "\n" "<br>" (documentation #'apply)))
     "\">apply</abbr>"))

(setq angst
      (⟰ "#+begin_documentation Existential Angst :label \"ex-angst\"
                       A negative feeling arising from freedom and responsibility.

                       Also known as
                       1. /Existential Dread/, and
                       2. *Existential Anxiety*.

                       Perhaps a distraction, such as visiting W3Schools, may help ;-)

                       Then again, ~coding~ can be frustrating at times, maybe have
                       a slice of pie with maths by reading “$e^{i×π} + 1 = 0$” as a poem ;-)
                       ,#+end_documentation

                       We now use this as doc:ex-angst."))

(deftest "Documentation blocks are not exported; they produce a new osbe--docs entry"
  [doc documentation o--name&doc]
    (should (org-docs-get "ex-angst")))

;; Upon export, the #+begin_documentation is /not/ present.
;; We have the text outside that block only.
;; Along, with a htmlified tooltip of the new entry.
(deftest "The osbe--docs entry of the documentation block appears within a tooltip"
    [doc documentation o--name&doc]
    (⇝ angst " <p> We now use this as <abbr class=\"tooltip\" title=\""
             (literal (org-osbe-html-export-preserving-whitespace
                       (cl-second (org-docs-get "ex-angst"))))
                    "\">Existential Angst</abbr>.</p> "))
#+end_src
#+end_details

** Implementation Details: =doc= link, ~documentation~ block, and tooltipster
   :PROPERTIES:
   :CUSTOM_ID: The-doc-link-type
   :END:
We begin by making use of a list of documentation-glossary entries
---a lightweight database of information, if you will.

#+begin_box Overview of relevant Lisp
+ doc:org--docs is the global variable that holds the glossary/database for the
  current session. Entries may be inserted with doc:org-docs-set and retrieved
  with doc:org-docs-get.

+ doc:org-docs-fallback is a /fallback method/ for retriving documentation-glossary
  entries from elsewhere besides the current buffer; e.g., using Emacs'
  doc:documentation function or the ~wn~ WordNet command for definitions of
  English words. We use doc:org-docs-load-libraries to load documentation-glossary
  entries from external files.

+ doc:org-docs-insert for interactively inserting links for documented-glossary words.
#+end_box

#+begin_src emacs-lisp
(defvar org--docs nil
  "An alist of (LABEL NAME DESCRIPTION) entries; our glossary.

Example setter:
0. (org-docs-set \"os\" \"Emacs\" \"A place wherein I do all of my computing.\")

Example getters:
0. (org-docs-get LABEL)
1. (-let [(name description) (cdr (assoc LABEL o--docs))] ⋯)

See also `org--docs-from-libraries' and `org-docs-load-libraries'.")

(cl-defun org-docs-set (label name description)
  "Add a new documentation-glossary entry, if it is not already present.

We associate LABEL to have title NAME and glossary value DESCRIPTION.

Example usage:
  (org-docs-set \"cat\"
              \"Category Theory\"
              \"A theory of typed  composition; e.g., typed monoids.\")"
  (add-to-list 'org--docs (list label name description)))

(cl-defun org-docs-get (label)
  "Return the name and documentation-glossary values associated with LABEL.

It returns a list of length 2.

Example uses:

  ;; Get the Lisp documentation of `thread-last'
  (org-docs-get \"thread-last\")

  ;; Get the English definition of ‘computing’
  (org-docs-get \"computing\")

We look for LABEL from within the current buffer first, using `org--docs',
and otherwise look among the loaded libraries, using `org--docs-from-libraries',
and, finally, look for the documentation entry using `org-docs-fallback'."
  (cdr (or (assoc label org--docs)
           (assoc label org--docs-from-libraries)
           (funcall org-docs-fallback label)
           (unless org-export-with-broken-links (error "Error: No documentation-glossary entry for “%s”!" label)))))

(cl-defun org-docs-insert ()
  "Insert a “doc:𝒳” link from user's documentation-glossary database.

It can be tricky to remember what you have, or what documentation entries mention, and so
this command gives a searchable way to insert doc links."
  (interactive)
  (thread-last
      (cl-remove-duplicates (-concat org--docs org--docs-from-libraries)
                            :test (lambda (x y) (cl-equalp (car x) (car y))))
    (--map (format "%s ∷ %s" (car it) (cl-third it)))
    (completing-read "Insert doc link ∷ ")
    (s-split "∷")
    car
    (concat "doc:")
    (insert)))
#+end_src

:Hide_startup_code:
#+name: startup-code
#+begin_src emacs-lisp :tangle no
(org-docs-set
  "cat" "Category Theory" "A theory of typed  composition; e.g., typed monoids.")
#+end_src
:End:

We may wish to use Emacs' doc:documentation (or doc:lf-documentation) command to
retrieve entries ---this is useful for an online article that refers to
unfamiliar Emacs terms ;-) To avoid copy-pasting documentation entries from one
location to another, users may declare a fallback method. Besides Emacs'
doc:documentation, the fallback can be refer to a user's personal ‘global
glossary’ variable ---which may live in their Emacs' init file---, for more see:
doc:org-docs-load-libraries
#+begin_src emacs-lisp
(defvar org-docs-fallback
  (lambda (label) (list
              ;; label
              label
              ;; name
              label
              ;; documentation
              (or
               (ignore-errors (documentation (intern label)))
               (ignore-errors (documentation-property
                               (intern label)
                               'variable-documentation))
               (-let [it (shell-command-to-string
                          (format "wn %s -over -synsn" label))]
                 (if (and (s-blank-p it) (not org-export-with-broken-links))
                     (error "Error: No documentation-glossary entry for “%s”!" label)
                   it)))))

  "The fallback method to retriving documentation or glossary entries.

We try to retrive the Emacs Lisp function documentation of the
given LABEL, if possible, otherwise we try to retrive the Emacs
Lisp variable documentation, and if that fails then we look up
the word in the English dictionary.

The English definition is obtained from the command line tool ‘wn’, WordNet.")
#+end_src

#+begin_details Implementation matter for user libraries
#+begin_src emacs-lisp
(defvar org-docs-libraries nil
  "List of Org files that have ‘#+begin_documentation’ blocks that should be loaded
   for use with the ‘doc:𝒳’ link type.")
#+end_src

In your init, you could do the following. ( See the installation instructions
below, for more! )
#+name: startup-code
#+begin_src emacs-lisp :tangle no
(setq org-docs-libraries
  '("~/org-special-block-extras/documentation.org"))
#+end_src

My personal documentation library can be seen here:
badge:Htmlized|Org|green|https://github.com/alhassy/org-special-block-extras/blob/master/documentation.org
or
badge:Pretty|HTML|green|https://alhassy.com/personal-glossary

#+begin_src emacs-lisp
(cl-defun org-docs-load-libraries
    (&optional (libs org-docs-libraries))
"Load documentation-glossary libraries LIBS.

If no LIBS are provided, simply use those declared
org-docs-libraries.

See `org-docs-from-libraries'."
(interactive)
(cl-loop for lib in libs
      do (with-temp-buffer
           (insert-file-contents lib)
           ;; doc only activates after an export
           (-let [org-export-with-broken-links t] (org-html-export-as-html))
           (kill-buffer)
           (delete-window)
           (setq org--docs-from-libraries (-concat org--docs org--docs-from-libraries))
           (setq org--docs nil))))

(defvar org--docs-from-libraries nil

  "The alist of (label name description) entries loaded from the libraries.

The ‘doc:𝒳’ link will load the libraries, possibly setting this variable to ‘nil’,
then make use of this variable when looking for documentation strings.

Interactively call `org-docs-load-libraries'
to force your documentation libraries to be reloaded.

See also `org-docs-libraries'.")
#+end_src

When the mode is actually enabled, then we load the user's libraries.
#+begin_src emacs-lisp :noweb-ref enable-mode :tangle no
;; Ensure user's documentation libraries have loaded
(unless org--docs-from-libraries
  (org-docs-load-libraries))
#+end_src

#+RESULTS:

#+end_details

Let's keep track of where documentation comes from ---either the current article
or from the fallback--- so that we may process it later on.
#+begin_src emacs-lisp
(defvar org--docs-actually-used nil
  "Which words are actually cited in the current article.

We use this listing to actually print a glossary using
‘show:GLOSSARY’.")
#+end_src

#+RESULTS:
: org--docs-actually-used

Now HTML exporting such links as tooltips and displaying them in Emacs as
tooltips happens in two stages: First we check the documentation, if there is no
entry, we try the fallback ---if that falls, an error is reported at export
time. E.g., upon export =doc:wombo= will produce a no-entry error.

# doc:thread-first

#+begin_details ‘doc’ link implementation
#+name: startup-code
#+begin_src emacs-lisp
(org-deflink doc
 "Export O-LABEL as itself, or as the provided O-DESCRIPTION,
 along with a tooltip that shows the user's
 documentation-glossary for o-LABEL and using that entry's name
 when no O-DESCRIPTION is provided."
 [:let (entry (org-docs-get o-label)
        name (cl-first entry)
        docs (cl-second entry)
        display-name (or o-description name))
  :help-echo (format "[%s] %s :: %s" o-label name docs)
  :face '(custom-button)]
   (add-to-list 'org--docs-actually-used (list o-label name docs))
   (pcase o-backend
     (`html  (format "<abbr class=\"tooltip\" title=\"%s\">%s</abbr>"
                     (org-osbe-html-export-preserving-whitespace docs)
                     display-name))
     ;; Make the current word refer to its glosary entry;
     ;; also declare the location that the glossary should refer back to.
     (`latex (format (concat "\\hyperref"
                             "[o-glossary-%s]{%s}"
                             "\\label{o-glossary"
                             "-declaration-site-%s}")
                     label display-name label))))

;; WHERE ...

(defun org-osbe-html-export-preserving-whitespace (s)
  "Make Org-markup'd string S ready for HTML presentation, preserving whitespace.

This is orthogonal to the  `org-export-string-as' command; i.e.,
(org-export-string-as s 'html :body-only-please) does something
else!  In particular, what this yields is an HTML rendition that
does not account for whitespace, such as indentation and
newlines.
"
  ;; Make it look pretty!
  (thread-last s
    (s-replace-regexp "\\#\\+begin_src [^\n]*\n" "<pre class='tooltip'>")
    (s-replace-regexp "\\( \\)*\\#\\+end_src\n" "</pre>")
    (s-replace-regexp "\\#\\+begin_export [^\n]*\n" "")
    (s-replace-regexp "\\( \\)*\\#\\+end_export" "")
    (s-replace "  " "&emsp;") ; Preserve newlines
    (s-replace "\n" "<br>")   ; Preserve whitespace
    (s-replace-regexp "\\#\\+begin_example<br>" "")
    (s-replace-regexp "\\#\\+end_example<br>" "")
    ; (s-replace-regexp "\\#\\+begin_src \\(.\\)*\\#\\+end_src)" "<pre>\1</pre>")
    ; (s-replace-regexp "\\#\\+begin_src [^<]*<br>" "<pre>")
    ; (s-replace-regexp "<br>\\( \\)*\\#\\+end_src<br>" "<br>\1</pre>")
    ;; Translate Org markup
    ;; Only replace /.*/ by <em>.*<em> when it does not have an alphanum,:,/,< before it.
    (s-replace-regexp "\\([^a-z0-9A-Z:/<]\\)/\\(.+?\\)/" "\\1<em>\\2</em>")
    (s-replace-regexp "\\*\\(.+?\\)\\*" "<strong>\\1</strong>")
    (s-replace-regexp "\\~\\([^ ].*?\\)\\~" "<code>\\1</code>")
    ;; No, sometimes we want equalities.
    ;; (s-replace-regexp "=\\([^ \n].*?\\)=" "<code>\\1</code>")
    (s-replace-regexp "\\$\\(.+?\\)\\$" "<em>\\1</em>")
    (s-replace-regexp "\\[\\[\\(.*\\)\\]\\[\\(.*\\)\\]\\]" "\\2 (\\1)")
    ;; 5+ dashes result in a horizontal line
    (s-replace-regexp "-----+" "<hr>")
    ;; Spacing in math mode
    (s-replace-regexp "\\\\quad" "&#x2000;")
    (s-replace-regexp "\\\\," "&#8194;") ;; en space
    (s-replace-regexp "\\\\;" "&#8195;") ;; em space
    ;; The presence of ‘\"’ in tooltips breaks things, so omit them.
    (s-replace-regexp "\\\"" "''")))
#+end_src

Since tooltips are not clickable and do not support MathJax,
we have manually transpiled what are perhaps the most common
instances of Org-markup: Bold, emphasises, code/verbatim, math, and links.
#+end_details

  # Our mode highlights documented text, with tooltips, as red.
  # #+begin_src emacs-lisp :noweb-ref enable-mode
  # (setq org-html-head-extra
  #       (concat org-html-head-extra
  #               (format "<style> abbr {color: red;} </style>")))
  #     #+end_src

Things look great at the HTML side and on the Emacs side for *consuming*
documented text.  Besides being inconvenient, we cannot with good conscious
force the average user to write Lisp as we did for the ~doc:cat~ entry. We turn to
the problem of *producing* documentation entries with a block type interface...

#+begin_details ‘documentation’ Implementation: An Example of Mandatory Arguments and Using ‘raw-contents’
#+BEGIN_SRC emacs-lisp
(org-defblock documentation
  (name (error "Documentation block: Name must be provided")
       label nil show nil color "green")
  "Register the dictionary entries in CONTENTS to the dictionary variable.

The dictionary variable is ‘org--docs’.

A documentation entry may have its LABEL, its primary identifier,
be:
1. Omitted
2. Given as a single symbol
3. Given as a many aliases '(lbl₀ lbl₁ … lblₙ)

The third case is for when there is no canonical label to refer to
an entry, or it is convenient to use multiple labels for the same
entry.

In all of the above cases, two additional labels are included:
The entry name with spaces replaced by underscores, and again but
all lower case.

Documentation blocks are not shown upon export;
unless SHOW is non-nil, in which case they are shown
using the ‘box’ block, with the provided COLOR passed to it.

In the futture, it may be nice to have an option to render tooltips.
That'd require the ‘doc:𝒳’ link construction be refactored via a ‘defun’."
  (unless (consp label) (setq label (list label)))
  (push (s-replace " " "_" name) label)
  (push (downcase (s-replace " " "_" name)) label)
  (cl-loop for l in label
        do  (add-to-list 'org--docs
                         (mapcar #'s-trim (list (format "%s" l) name (substring-no-properties raw-contents)))))
  ;; Should the special block show something upon export?
  (if show (org--blockcall box name :background-color color raw-contents) ""))
#+END_SRC



:Older_approach:
#+BEGIN_SRC emacs-lisp :tangle no
(defun org--documentation (_ contents)
  "Register the dictionary entries in CONTENTS to the dictionary variable.

The dictionary variable is ‘org--docs’.

Documentation blocks are not shown upon export."
  ;; Strip out any <p> tags
  ;; Musa: Make these three lines part of the core utility?
  (setq contents (substring-no-properties contents))
  (setq contents (s-replace-regexp "<p>" "" contents))
  (setq contents (s-replace-regexp "</p>" "" contents))
  (setq contents (s-trim contents))
  (cl-loop for entry in (cdr (s-split ":name:" contents))
        do   (-let [(contents′ . (&alist 'label 'name))
                    (org--extract-arguments
                     (s-concat ":name:" entry) 'label 'name)]
               (unless (and label name)
                 (error (message-box (concat "#+begin_documentation: "
                           "Ensure the entry has a :name followed by a :label "
                            "\n\n " contents))))
               (add-to-list 'org--docs
                            (mapcar #'s-trim (list label name contents′)))))
  ;; The special block is not shown upon export.
  "")
  #+END_SRC
:End:

#+end_details

# #  Tooltipster ---Fast, Sleek, & Beautiful Tooltips
Thus far, Org entities are converted into HTML tags such as =<i>= for italicised
text. However, HTML's default tooltip utility ---using ~title="⋯"~ in a ~div~---
does not render arbitrary HTML elements. Moreover, the default tooltip utility
is rather slow. As such, we move to using /tooltipster/.  The incantation below
sets up the required magic to make this happen.

#+begin_details "Fast, Sleek, and Beautiful Tooltips: Touching ‘org-html-head-extra’"
#+begin_src emacs-lisp :noweb-ref enable-mode :tangle no
  (defvar org--tooltip-html-setup nil
    "Has the necessary HTML beeen added?")

  (unless org--tooltip-html-setup
    (setq org--tooltip-html-setup t))
  (when org-special-block-add-html-extra
   (setq org-html-head-extra
    (concat org-html-head-extra
     "
  <link rel=\"stylesheet\" type=\"text/css\" href=\"https://alhassy.github.io/org-special-block-extras/tooltipster/dist/css/tooltipster.bundle.min.css\"/>

  <link rel=\"stylesheet\" type=\"text/css\" href=\"https://alhassy.github.io/org-special-block-extras/tooltipster/dist/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-punk.min.css\" />

  <script type=\"text/javascript\">
      if (typeof jQuery == 'undefined') {
          document.write(unescape('%3Cscript src=\"https://code.jquery.com/jquery-1.10.0.min.js\"%3E%3C/script%3E'));
      }
  </script>

   <script type=\"text/javascript\"            src=\"https://alhassy.github.io/org-special-block-extras/tooltipster/dist/js/tooltipster.bundle.min.js\"></script>

    <script>
           $(document).ready(function() {
               $('.tooltip').tooltipster({
                   theme: 'tooltipster-punk',
                   contentAsHTML: true,
                   animation: 'grow',
                   delay: [100,500],
                   // trigger: 'click'
                   trigger: 'custom',
                   triggerOpen: {
                       mouseenter: true
                   },
                   triggerClose: {
                       originClick: true,
                       scroll: true
                   }
   });
           });
       </script>

  <style>
     abbr {color: red;}

     .tooltip { border-bottom: 1px dotted #000;
                color:red;
                text-decoration: none;}
  </style>
  ")))
    #+end_src

Note that we have a conditional in the middle to avoid loading jQuery multiple
times ---e.g., when one uses the =read-the-org= them in combination with this
library. Multiple imports lead to broken features.
#+end_details

** Wait, what about the LaTeX?
   :PROPERTIES:
   :CUSTOM_ID: hola
   :END:

   A PDF is essentially a fancy piece of paper, so tooltips will take on the
   form of glossary entries: Using =doc:𝒳= will result in the word =𝒳= being printed
   as a hyperlink to a glossary entry, which you the user will eventually
   declare using =show:GLOSSARY=; moreover, the glossary entry will also have a
   link back to where the =doc:𝒳= was declared.  E.g., doc:defmacro and
   doc:lambda.

   We make a ~show:𝒳~ link type to print the value of the variable =𝒳=
   as follows, with =GLOSSARY= being a reserved name.
   #+begin_details Implementation of ‘show’
 #+begin_src emacs-lisp
(org-deflink show
  "Yield the value of the expression O-LABEL, with =GLOSSARY= being a reserved name.

Example uses:

    show:user-full-name

    <show: (* 2 (+ 3 4 (- pi))) >


Note that there is `elisp' links with Emacs, out of the box.
However, they only serve to evaluate Lisp expressions; for example,
to make “link buttons” that do useful things, as follows.

   Init

In particular, `elisp' links do not export the value of their expression.
That is what we accomplish with this new `show' link type."
  [:face '(:underline "green")
   :let (o-value (if (equal o-label "GLOSSARY")
                     (pp-to-string (mapcar #'cl-second org--docs-actually-used))
                   (pp-to-string (eval (car (read-from-string o-label)))))
         o-expr (if (equal o-label "GLOSSARY")
                    (concat "GLOSSARY ---i.e., org--docs-actually-used"
                            "\n\nWe erase the glossary not on the first export, but on the second export."
                            "\nThe first export collects all citations, which are used in the second export.")
                  o-label))
  :help-echo (format
              (concat "Upon export, the following will be placed literally"
                      "\n\t%s"
                      "\nWhich is the value of the expression:\n\t%s")
              o-value
              o-expr)]
  (cond ((not (equal o-label "GLOSSARY")) o-value)

       ;; Otherwise O-LABEL is glossary, which we print in HTML & LaTeX
       ((equal 'html o-backend)
          (s-join " "
                  (--map
                   (format "<abbr class=\"tooltip\" title=\"%s\">%s</abbr>"
                           (org-osbe-html-export-preserving-whitespace (cl-third it))
                           (cl-second it))
                   ;; Ignore duplicates; i.e., entries with the same name/title.
                   (cl-remove-duplicates org--docs-actually-used
                                         :test (lambda (x y) (cl-equalp (cl-second x) (cl-second y)))))))
       (:otherwise (s-join "\n\n"
                  (cl-loop for (label name doc)
                           in org--docs-actually-used
                           collect
                           (format
                           (concat "\\vspace{1em}\\phantomsection"
                                   "\\textbf{%s}\\quad"
                                   "\\label{o-glossary-%s}"
                                   "%s See page "
                                   "\\pageref{org-special-block-extras"
                                   "-glossary-declaration-site-%s}")
                           name
                           o-label
                           (when doc
                             (thread-last doc ;; preserve whitespace
                               (s-replace "&" "\\&") ;; Hack!
                               (s-replace "  " " \\quad ")
                               (s-replace "\n" " \\newline{\\color{white}.}")))
                           o-label))))))
 #+end_src
#+end_details

 As an example, we know have generic sentences:
 | =My name is show:user-full-name and I am using Emacs show:emacs-version ^_^=  |
 |----------------------------------------------------------------------------|
 | My name is show:user-full-name and I am using Emacs show:emacs-version ^_^  |

 For example, here is a word whose documentation is obtained from Emacs rather
 than me writing it: doc:thread-last.  If you click on it, in the LaTeX output,
 you will be directed to the glossary at the end of this article ---glossaries
 are not printed in HTML rendering.

 /Neato! The whitespace in the documentation is preserved in the LaTeX output as
 is the case for HTML./

 If we decide to erase a =doc:𝒳=, then it should not longer appear in the
 printed glossary listing. Likewise, a =documentation= block has its Org markup
 exported according to the backend being exported to, hence if we decide to
 switch between different backends then only the first rendition will be used
 /unless/ we erase the database each time after export.
#+begin_src emacs-lisp :noweb-ref enable-mode :tangle no
(defvar org--docs-empty! (list nil t)
  "An indicator of when glossary entries should be erased.

We erase the glossary not on the first export, but on the second export.
The first export collects all citations, which are used in the second export.")
(setcdr (last org--docs-empty!) org--docs-empty!) ;; It's an infinite cyclic list.

;; Actual used glossary entries depends on the buffer; so clean up after each export
(advice-add #'org-export-dispatch
  :after (lambda (&rest _)
  (when (pop org--docs-empty!)
      (setq org--docs-actually-used nil ;; The 𝒳 of each “doc:𝒳” that appears in the current buffer.
            org--docs nil))))           ;; The “#+begin_documentation ⋯ :label 𝒳” of the current buffer.
#+end_src
#
# (-let [sym 'org-export-dispatch]  (advice-mapc (lambda (advice _props) (advice-remove sym advice)) sym))

** Next Steps
  :PROPERTIES:
  :CUSTOM_ID: Next-Steps-tooltips
  :END:

# Going forward,
Going forward, it'd be nice to have URLs work well upon export for =documentation=
block types; whereas they currently break the HTML export.
- If an entry is referenced multiple times, such as doc:cat, then it would be
  nice if the glossary referred to the pages of all such locations rather than
  just the final one.
- The glossary current prints in order of appearance; we may want to have
  the option to print it in a sorted fashion.
- Perhaps use the line activation feature to provide link tooltips
  immediately rather than rely on exportation.
- +The =show= link type could accept an arbitrary Lisp expression as a bracketed
  link.+ It does ;-)
- When one clicks on a =doc= documentation link, it would be nice to ‘jump’
  to its associated =#+begin_documentation= declaration block in the current
  buffer, if possible.

* COMMENT Equational Proofs
  :PROPERTIES:
  :CUSTOM_ID: Equational-Proofs
  :END:

Sometimes you just want to have a quick, yet /detailed/, explanation and so we can
use *green:org-lists as equational proofs* ---thanks to the calc block!
#+begin_details Implementation :title-color pink
  #+begin_src emacs-lisp
(defun org--list-to-calc (lst rel hint-format NL-length color)
  "Get a result from org-list-to-lisp and render it as a calculational proof.

LST is an expression, possibly with a hint and dedicated relation.
The expression may contain multiple lines, as may the hints.

REL is the default relation in the left-most column.

HINT_FORMAT is the formatting string for hints; e.g.,
\"\\color{maroon}{\\langle\\large\\substack{\\text{ %s }}⟩}\"

NL-length is how long the explicit vertical space, \\, should be.
The number refers to the vspace occupied nearly by the height of
a single normal sized letter.

COLOR is the colour of the hints."
  (cond
   ((symbolp lst) "")
   ((symbolp (car lst)) (org--list-to-calc (cadr lst)))
   (:otherwise (-let* (((conclusion₀ children) lst)
              ((expr₀ hint) (s-split "--" conclusion₀))
              ((op₀ expr₁) (cdr (s-match "^\\[\\(.*\\)\\]\\(.*\\)" expr₀)))
              (op (or op₀ rel))
              (expr (or expr₁ expr₀)))
        (if (not children)
            (if hint
                (format
                 "\n %s \\;\\; & \\qquad \\color{%s}{%s} \n \\\\ & \\begin{split}%s\\end{split}"
                 op
                 color
                 ;; the hfill is so that we do not use substack's default
                 ;; centering, but instead left-align justificatiion
                 ;; hints.
                 (format (s-replace "%s" "{\\large\\substack{\\text{ %s } \\hfill\\\\\n}}" hint-format)
                         (s-replace "\n" " } \\hfill\\\\\n\\text{ "
                                    (s-replace "\n\n" (s-repeat (* 6 NL-length) "\n $\\,$") (s-trim hint))))
                 expr)
              (format "\\begin{split}%s\\end{split} \n" expr))
       ;; MA: The following could be improved.
          (format "\n %s \\;\\; & \\qquad \\color{%s}{%s} \n \\\\ & \\begin{split}%s\\end{split}"
                  op color
                  ;; BEGIN similar as above
                  (format (s-replace
                           "%s"
                           "{\\large\\substack{\\text{ %s } \\hfill\\\\ \\begin{split} & %s \n\\end{split}\\hfill\\\\\n}}"
                           hint-format)
                          (s-replace "\n" " } \\hfill\\\\\n\\text{ "
                                     (s-replace "\n\n" (s-repeat (* 6 NL-length) "\n $\\,$") (s-trim hint)))
                          ;; END similar
                          (s-chop-prefix
                           "\\\\" (s-join
                                   "\\\\"
                                   (--map (format "%s" (org--list-to-calc it rel hint-format NL-length color))
                                          children))))
                  expr))))))

(org-defblock calc
  (main-arg nil
  rel "=" hint-format "\\left[ %s \\right." explicit-vspace 2 color "maroon")
  "Render an Org-list as an equational proof.

Sometimes the notation delimiting justification hints may clash
with the domain topic, so we can change the hint format, e.g., to
\"\\left\\langle %s \\right\\rangle\".  Set HINT-FORMAT to the
empty string, \"\", to comment-out all hints in the exported
version.

The hint is the text immediately after a “--”, if there are
multiple such delimiters only the first is shown; this can be
useful if we want to have multiple alternatives, say for extra
details in the source but not so much in the export.

Line breaks are taken literally in the hints, but not in the
math; where one uses \\\\.  For math with multiple lines, use ‘&’
as an alignment marker; otherwise math is right-justified.

For HTML, to use an TeX it must be enclosed in $, since that is
what is required by MathJaX."
  (thread-last (with-temp-buffer
                 (insert raw-contents)
                 (goto-char (point-min))
                 (org-list-to-lisp))
    cdr
    (--map (format "%s" (org--list-to-calc it rel hint-format explicit-vspace color)))
    (s-join "\\\\")
    (format "$$\\begin{align*} & %s \n\\end{align*}$$")))
#+end_src

#+RESULTS:
| :export | (lambda (label description backend) (s-replace-all `((@@ . )) (org--calc backend (or description label) label :o-link? t))) | :help-echo | (lambda (window object position) (save-excursion (goto-char position) (-let* (((&plist :path :format :raw-link :contents-begin :contents-end) (cadr (org-element-context))) (description (when (equal format 'bracket) (copy-region-as-kill contents-begin contents-end) (substring-no-properties (car kill-ring))))) (format %s |


#+end_details
#+begin_box "“Programming Comments  ≈  Proof Hints”" :background-color blue
Let's prove that $x ≤ z$...
#+begin_parallel
*Source:*
#+begin_src org :tangle no
,#+begin_calc :hint-format "\\left\\{ %s\\right."
+     x
+     y -- Explanation of why $x \;=\; y$
  Actually, let me explain:
  ,* x
  ,* x′ -- hint 1
  ,* y  -- hint 2

  No words can appear (in the export) *after* a nested calculation, for now.
+ [≤] z
  --
  Explanation of why $y \;\leq\; z$

  -- explain it more, this is ignored from export ;-)
,#+end_calc
#+end_src
#+html: <p>
*Result:*
#+begin_calc :hint-format "\\left\\{ %s\\right."
+     x
+     y -- Explanation of why $x \;=\; y$
  Actually, let me explain:
  * x
  * x′ -- hint 1
  * y  -- hint 2

  No words can appear (in the export) *after* a nested calculation, for now.
+ [≤] z
  --
  Explanation of why $y \;\leq\; z$

  -- explain it more, this is ignored from export ;-)
#+end_calc
#+end_parallel

Benefits of Org-lists for proofs:
+ Nested proofs can be /folded-away/ with 〔TAB〕.
  - This provides a nice /proof outline!/
+ All Org support for lists active; e.g., 〔M-↑,↓〕 for moving /proof steps/ (list
  items) and 〔M-RET〕 for new /proof steps/.

+ Intentional explanations can make the proof argument more /convincing/, or
  accurate.

Examples below: Rational root equivales perfect power, Handshaking lemma,
calculating train length, and last, but not least, “1 + 1 = 2”.

--------------------------------------------------------------------------------

Align the proof hints with 〔M-x align-regexp RET -- RET〕 ...let's calculate that $a ⊆ e$...

#+begin_parallel
*Source:*
#+begin_src org :tangle no
,#+begin_calc
+     a
+     b  --  reason for the equality
+ [⊆] c  --  reason for the inclusion
+     d  --  reason for the equality
+     e  --  final justification
,#+end_calc
#+end_src

#+html: <br><p><br>
*Result:*
#+begin_calc
+     a
+     b  --  reason for the equality
+ [⊆] c  --  reason for the inclusion
+     d  --  reason for the equality
+     e  --  final justification
#+end_calc
#+end_parallel
#+end_box

#+begin_details Tests
#+begin_src emacs-lisp :tangle tests.el :comments link
(setq calc (⟰ "#+begin_calc :hint-format \"\\\\left\\{ %s\\\\right.\"
                  +     x
                  +     y -- Explanation of why $x \\;=\\; y$
                    Actually, let me explain:
                    ,* x
                    ,* x′ -- hint 1
                    ,* y  -- hint 2

                    No words can appear (in the export) *after* a nested calculation, for now.
                  + [≤] z
                    --
                    Explanation of why $y \\;\\leq\\; z$

                    -- explain it more, this is ignored from export ;-)
                  ,#+end_calc"))

(deftest "It's an align environment, in displayed math mode"
  [calc]
  (⇝ calc "$$\\begin{align*}" (* anything) "\\end{align*}$$"))

(deftest "The calculation has 4 proof steps"
  [calc]
  ;; The number of steps in a calculation is the number of items in each nesting, minus 1 (at each nesting).
  ;; Above we have depth 2 with 3 items in each depth, for a total of (3-1) + (3-1) = 2 + 2 = 4.
  (should (= 4 (s-count-matches (rx (seq "\\" (* whitespace) (any "=" "≤"))) calc))))


(deftest "Of our 4 steps, 3 of them are equalities and one is an inclusion."
  [calc]
  (should (= 3 (s-count-matches (rx "= \\;\\;") calc)))
  (should (= 1 (s-count-matches (rx "≤ \\;\\;") calc))))

(deftest "All of the hints actually appear in the calculational proof"
  [calc]
  (mapc (lambda (hint) (should (s-contains? hint calc)))
        '("Explanation of why $x \\;=\\; y$"
          "Actually, let me explain:"
          "hint 1"
          "hint 2"
          "Explanation of why $y \\;\\leq\\; z$")))
#+end_src
#+end_details

--------------------------------------------------------------------------------

Examples...

#+begin_details ★ "Proof of “1 + 1 = 2” with source"  :title-color orange
link-here:1+1=2
#+begin_calc
+ 1 + 1
+ \suc \zero + \suc \zero
  --
  $\def\suc{\mathsf{suc}\,} \def\zero{\mathsf{zero}}$
  “1” abbreviates “$\suc \zero$”
+ \zero + \suc (\suc \zero) --
  Addition is defined by moving the $\suc$-s from the left argument to the
  right.
  $\def\eqn#1#2{\begin{equation} #2 \tag{#1} \label{#1} \end{equation}}$

  That is, we define $x + y$ by considering the possible $shape$ of $x$,
  which could only be a $\zero$ or a $\suc$-cessor.
  When $x$ is zero, there are no $\suc$-s to move to the right, so we yield the  right.
  $\eqn{Base Case}{\zero + n \; = \; n}$
  When $x$ is a $\suc$, we move the $\suc$ to the right, and continue to try adding.
  $\eqn{Inductive Step}{\suc m \,+\, n \; = \; m \,+\, \suc n}$
  Since we're moving a $\suc$ at each step, eventually we'll hit the
  base case and be done adding.

  For now, we apply the \eqref{Inductive Step}.

+ \suc (\suc \zero)
  -- Using the \eqref{Base Case} definition of addition.
+ 2 -- Switching to ‘conventional’ notation
#+end_calc
--------------------------------------------------------------------------------
*Source:*
#+begin_src org :tangle no
,#+begin_calc
+ 1 + 1
+ \suc \zero + \suc \zero
  --
  $\def\suc{\mathsf{suc}\,} \def\zero{\mathsf{zero}}$
  “1” abbreviates “$\suc \zero$”
+ \zero + \suc (\suc \zero) --
  Addition is defined by moving the $\suc$-s from the left argument to the
  right.
  $\def\eqn#1#2{\begin{equation} #2 \tag{#1} \label{#1} \end{equation}}$

  That is, we define $x + y$ by considering the possible $shape$ of $x$,
  which could only be a $\zero$ or a $\suc$-cessor.
  When $x$ is zero, there are no $\suc$-s to move to the right, so we yield the  right.
  $\eqn{Base Case}{\zero + n \; = \; n}$
  When $x$ is a $\suc$, we move the $\suc$ to the right, and continue to try adding.
  $\eqn{Inductive Step}{\suc m \,+\, n \; = \; m \,+\, \suc n}$
  Since we're moving a $\suc$ at each step, eventually we'll hit the
  base case and be done adding.

  For now, we apply the \eqref{Inductive Step}.

+ \suc (\suc \zero)
  -- Using the \eqref{Base Case} definition of addition.
+ 2 -- Switching to ‘conventional’ notation
,#+end_calc
#+end_src
#+end_details
#+begin_details “Calculating” the length of a train
link-here:calculating-the-length-of-a-train
Let us *green:calculate* the length of a train, that is travelling at a speed of
60 km/hr and, on its way, it crosses a pole in 9 seconds.
# Implicitly assuming that it is going straight, no turns or curves.
#+begin_calc
+ \text{ the length of the train }

+ \text{ the distance from the end of the train to its front }
  -- Express length as a difference of distance

+ & \left(\begin{split} &\text{ difference in time from when the train's front}
     \\ &\text{ crosses the pole until its back crosses the pole } \end{split}\right)
    \;\times\; \text{speed of the train}
  -- distance = time × speed

+ & \text{ how long it takes the train to cross the pole }
    \;\times\; \text{speed of the train}
  -- Rephrase

+ 9 \text{ seconds } \times 60 \text{ km / hr}
  -- $\def\meters{\,\mathsf{meters}\,} \def\seconds{\,\mathsf{seconds}\,}$
  The train crosses the pole in 9 seconds;
  and the train is travelling at the speed of 60km/hr.

+ 9 \seconds \times 60 × (1000 / 60 × 60) \meters / \seconds
  --
  Express things in common units, such as seconds; i.e.,:
  * 1 \text{ km / hr}
  * 1 \text{ km } /\; 1 \text{ hr }      -- Be more explicit
  * 1000 \meters /\, 1 \text{ hr }   -- A kilometre is 1000 meters
  * 1000 \meters /\, (60 × 60) \seconds  -- Express hours in terms of seconds:
    + 1 \text{ hr }
    + 60 \,\mathsf{minutes}              -- Express in minutes
    + 60 \,\times\, 1 \,\mathsf{minutes} -- Be more explicit
    + 60 \,\times\, 60 \,\seconds        -- A minute has 60 seconds
  * (1000 / 60 × 60) \meters / \seconds  -- Collecting like-terms

  Original justification, not shown in export:
  A kilometre is 1000 meters and an hour is 60 minutes, each having 60 seconds:
  $1 \text{ km / hr} \;=\; 1 \text{ km } /\; 1 \text{ hr } =\; 1000 \meters /\, (60 × 60) \seconds \;=\; (1000 / 60 × 60) \meters / \seconds$

+ 9 \seconds \times (1000 / 60) \meters / \seconds
  -- Division cancels multiplication: $b × (a / b) = a$

+ (1000 / 60) × 9 \seconds × (\meters / \seconds)
  -- Collect like-terms; i.e., commutativity of ×

+ (1000 / 60) × 9 \meters
  -- Division cancels multiplication: $b × (a / b) = a$

+ 150 \meters
  -- Arithmetic

#+end_calc
#+end_details
#+begin_details "Euler's Handshaking Lemma"

link-here:handshaking-lemma
/At a party of 7 people, is it possible that everybody knows exactly 3 other
people?/

We could consider all possible cases, which is not particularly enlightening; or
we could /calculate/...

#+begin_calc :hint-format "\\left[ %s \\right]"
+ \text{“Obviously”, the sum of everyone's friendship count is twice the total
  number of friendships}
+ ∑_p f(p) = 2×F                      --  Formalise...

  Let $f(p)$ denote the number of friends that person $p$ has,
  which is 0 if $p$ has no friends.

  Let $F$ be the total number of friendships (between any 2 people).

  Since friendships are always between two people, we have
  that $\sum_p f(p) = 2 × F$: Counting-up the number of friends
  that everyone has will always be twice the total number of relationships
  ---which is always an even number.

  Formally,

  * \text{sum of everyone's friendship count}
  * \sum_p f(p)             -- Formalise, where $p$ ranges over people
  * \sum_p \sum_r 𝑭𝒓_{p, r} -- Definition of $f$:
    Let $𝑭𝒓_{p, r}$ be 1 exactly when $p$ participates in
    friendship/relationship $r$,
    and 0 otherwise, then $f(p) = \sum_r 𝑭𝒓_{p, r}$.
  * \sum_r \sum_p 𝑭𝒓_{p, r} -- Quantifier interchange; i.e., Fubini's Principle
  * \sum_r 2                -- Every relationship $r$ is between 2 people;
    i.e., $\sum_p 𝑭𝒓_{p, r} = 2$
  * 2 × \sum_r 1            -- Factoring
  * 2 × F                   -- The total number of friendships is $F$
+ [⇒] \even{∑_p f(p)} ≡ \even{2 × F}  -- Equals for equals;
  i.e., $if$ those numbers are equal $then$ their parities are equal
  $\def\even#1{\mathsf{even}\,\left(#1\right)}$
  $\def\odd#1{\mathsf{odd}\,\left(#1\right)}$
+ \even{∑_p f(p)}                     -- The right side is clearly true;
  (‘true’ is the identity of ‘≡’)
+ {\LARGE ≡}_p \;\even{f(p)}          --  $\even{-}$ distributes over sums turning them into equivalences ‘≡’
+ \even{ ♯\{p ∣ ¬ \even{f(p)}\} }      -- By definition, a chain of equivalences is true exactly when
  it has an even number of false values
+ \even{ ♯\{p ∣ \odd{f(p)} \} }        -- A non-even number is precisely an odd number
+ \text{an even number of people have an odd number of friends} -- Un-formalise
#+end_calc

Back to the problem: At a party of 7 people, is it possible that everybody knows
exactly 3 other people?

If such a party were possible, the number of people with an odd friend count
must be even, but 7 is not even, and so no such party is possible.  (
Alternatively, if such a party were possible, then by the Handshaking Lemma, $F
= {∑_p f(p) \over 2} = {7 × 3 \over 2} = 10.5$: This is absurd since there
cannot be a ‘.5’ relationship! Hence, no such party is possible. )

+ Likewise, if exactly 5 people in a room each claim to have shaken 3 hands,
  then someone is lying.

( Rephrased: The sum of the degrees of the vertices of a (total) doc:graph is
twice the number of edges of the graph; moreover, an even number of vertices
have an odd degree.

The party problem is then: /Is there a graph of 7 nodes with each node being
connected to exactly 3 other nodes?/ Apparently not, and we didn't need to draw
any graphs at all to prove it.

For more on Graph Theory, here are some lecture notes. )

+ The power of shaking hands has a few non-trivial applications of this lemma.
#+end_details
#+begin_details ★ Rational root equivales perfect power :title-color orange
link-here:rational-root-equivales-perfect-power
#+begin_calc :rel ⇔
+ \sqrt[n]{k} \text{ is a rational number }

+ ∃\, a, b •\; \sqrt[n]{k} = {a \over b} --

  A rational number is the fraction of two integers.
  Let variables $a,\, b$ range over integer numbers.

+ ∃\, a, b •\; k · b ^n = a ^n --
  Use arithmetic to eliminate the $n$-th root operator.

  $\def\exp#1#2{\mathsf{exp}_#1\,#2}$
  $\def\eq{\;=\;}$

+ ∃\, a, b •\; ∀\, p •\; \exp{p}(k · b ^n) \eq \exp{p}(a ^n ) --

  Let $\exp{m} x$ be the number of times that $m$ divides $x$.
  For example, $\exp{2} 48 \eq 4$ and $\exp{2} 49 \eq 0$.

  The numbers $p$ with $∀ m : ℤ⁺ \;•\; \exp{m}p \,≠\, 0 \,≡\, m \,=\, p$
  are called $prime$ numbers. Let variable $p$ range over prime numbers.

  Fundamental theorem of arithmetic: Numbers are determined by their prime powers.
  That is, $\big(∀ \,p\, •\;\; \exp{p} x \eq f(p)\big) \;\;≡\;\; x \eq \big(Π\, p\, •\; p^{f(p)}\big)$ for any $f$.
  As such, every number is the product of its prime powers:
  $\qquad x \eq \big(Π \,p\, •\; p^{\exp{p} x}\big)$.
  And so, any two numbers are the same precisely when they have the same primes:
  $\qquad x \eq y \;\;≡\;\; \big(∀ p \,•\, \exp{p} x \eq \exp{p} y\big)$.

+ ∃\, a, b •\; ∀\, p •\; \exp{p} k + n · \exp{p} b \eq n · \exp{p} a --

  When $p$ is prime, $\exp{p}(x · y) \eq \exp{p} x \,+\, \exp{p} y$.
  Aside: In general, $\exp{p}(Π \,i\, \,•\, x_i) \eq (Σ \,i\, \,•\, \exp{p} x_i)$.

+ ∃\, a, b •\; ∀\, p •\; \exp{p} k \eq  n · \Big(\exp{p} a - \exp{p} b\Big) --
  Use arithmetic to collect similar terms.

+ ∀\, p •\; \exp{p} k \text{ is a multiple of } n  --

  (⇒) is the definition of multiplicity;
  (⇐) take $b \,≔\, 1$ and define $a$ by its prime powers:
  $\qquad ∀\, p \,•\, \exp{p} a \,≔\, {\exp{p} k \,/\, n}$

+ k \text{ is a perfect $n$-th power; i.e., of the shape } x^n  --
  Fundamental theorem of arithmetic and definition of ‘perfect’
#+end_calc
#+end_details

# Not ideal because current design decision favours hard line breaks...
# $\begin{align} \label{hi}\zero \,+\, n  &\;=\; n \\ (\suc m) \,+\, n  &\;=\; \suc (m + n) \end{align}$

# For some reason, I need /some/ math to “activate” MathJax
# ${}$

--------------------------------------------------------------------------------

Possibly Useful links:
+ TeX Commands available in MathJax
+ MathJax crashes if ~\label~ names are not unique ---e.g., for labelled
  equations, see “1 + 1 = 2” example above.

#+begin_details "★ What if I want to do this in LaTeX (e.g., for math.stackexchange.com)?" :title-color orange
link-here:equational-proofs-in-LaTeX
Copy-paste the following...
#+begin_src latex :tangle no :exports code
$
% set up \step command
\def\BEGINstep{ \left\langle }
\def\ENDstep{ \right\rangle }
\newcommand{\step}[2][=]{ \\ #1 \;\; & \qquad \color{maroon}{\BEGINstep\text{ #2 } \ENDstep} \\ & }
% multi-line step with many lines of text
\newcommand{\line}[1]{ \text{#1}\hfill\\ }
\newcommand{\stepmany}[2][=]{ \\ #1 \;\; & \qquad \color{maroon}{\BEGINstep \large\substack{ #2 } \ENDstep} \\ & }
% multi-line step with 4 lines of text
\newcommand{\stepfour}[5][=]{ \stepmany[#1]{\line{#2} \line{#3} \line{#4}
\line{#5}} }
\newenvironment{calc}{\begin{align*} & }{\end{align*}}
$
#+end_src
Then, use it as follows...
#+begin_src latex :tangle no :exports code
\begin{calc}
x
\step{reason for equality}
y
\step[\leq]{reason for inclusion}
z
\end{calc}
#+end_src
#+end_details

* COMMENT How Do I make my own block and link types?
* [#A] COMMENT README improvements

Add images for the “osbe-example” results and link to the html,
since otherwise things don't look as nice in a markdown readme file.

#+caption: Displaying thoughts side-by-side ^_^ Top is browser, then Emacs, then PDF
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/parallel.png



#+caption: Visually hiding, folding away, details
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/details.png


  ( Markdown does not support colour; go look at the HTML or PDF! )
* COMMENT Case Studies
** In doubt, a block's main argument should be enclosed in quotes
:PROPERTIES:
:CUSTOM_ID: In-doubt-a-block's-main-argument-should-be-enclosed-in-quotes
:END:

The following wont work as expected...

#+begin_details SDOF equations are \\(m\\ddot{x}=f(t)\\)
The above is a differential equation with $\ddot{x}$.
#+end_details

But using quotes will fix all the problems...

#+begin_details "SDOF equations are \\(m\\ddot{x}=f(t)\\)"
The above is a differential equation with $\ddot{x}$.
#+end_details


** Example of preventing Org from adding new paragraph line breaks within div-s

In the produced HTML code, a paragraph ~<p> bla bla </p>~ environment is added inside a ~div~; how do we prevent this from
happening?

This is hinted at in the docstrings: ~C-h o RET org-defblock~ yields
~...In, hopefully, rare circumstances, one may refer to RAW-CONTENTS to look at the fully unparsed contents....~
# TODO: The docstring should also mention “org-parse” and its use with “raw-contents”?


--------------------------------------------------------------------------------

The following style ensures that the ~<p>~ tags produced by Org have their line feeds disabled
/only while/ in a ~<div class="theorem">~.
#+html: <style> .theorem p { display:inline; } </style>

With that in-hand, let's define our theorem block.
#+begin_src emacs-lisp
(setq my/theorem-counter 0)

(org-defblock theorem (title)
  "Show block contents prefixed with “Theorem 𝒏”, where the 𝒏umbering automatically increments."
  (format "<div class=\"theorem\"><b>Theorem %s%s.</b>&nbsp;%s</div>"
          (cl-incf my/theorem-counter)
          (if title (format " [“%s”]" title) "")
          (org-parse raw-contents)))
#+end_src

To enable MathJax to load, we need some inline math, such as $x = x$. With that
out of the way, we can look at some example uses of our “theorem” block.

#+begin_theorem Russel & Whitehead
After 372 pages, it was shown that $1 + 1 = 2$
#+end_theorem

#+begin_theorem
It is said that $e^{i \cdot \pi} + 1 = 0$ is the truth.
#+end_theorem

* [#A] COMMENT Summary
  :PROPERTIES:
  :CUSTOM_ID: Summary
  :END:

#+begin_quote
The full article may be read as a PDF or as HTML ---or visit the repo.
#+end_quote

link-here:summary
Let =𝒞= be any of the following: =black=, =blue=, =brown=, =cyan=, =darkgray=, =gray=, =green=,
=lightgray=, =lime=, =magenta=, =olive orange=, =pink=, =purple=, =red=, =teal=, =violet=, =white=,
=yellow=.

| Idea                   | Documentation                                                    | Link only?          |
|------------------------+------------------------------------------------------------------+---------------------|
| Colours                | =𝒞=, math, color                                      |                     |
| Parallel               | parallel                             |                     |
| Editorial Comments     | remark                                 |                     |
| Folded Details         | details ,  box |                     |
| Keystrokes             |                                                                  | ~kbd~                 |
| OctoIcons & Link Here  |                                                                  | ~octoicon~, ~link-here~ |
| Documentation-Glossary | documentation                   | ~doc~               |
| Marginal remarks       | margin                                 |                     |
| Badges                 | badge                                    |                     |
| Equational proofs      | calc                                     |                     |

Other fun stuff: solution, org-demo, stutter, rename, spoiler, tree :grin:

There are also the social badge links:
=reddit-subscribe-to=, =github-followers=, =github-forks=, =github-stars, github-watchers=, =twitter-follow=, and =tweet=.

# Going forward, it'd be nice to a centralised ‘user manual’ which may be
# consulted rather than reading the literate implementation above.

** Installation Instructions
   :PROPERTIES:
   :CUSTOM_ID: Installation-Instructions
   :END:

Manually or using quelpa:
#+BEGIN_SRC emacs-lisp :tangle no
;; ⟨0⟩ Download the org-special-block-extras.el file manually or using quelpa
(quelpa '(org-special-block-extras :fetcher github :repo
"alhassy/org-special-block-extras"))

;; ⟨1⟩ Have this always active in Org buffers
(add-hook #'org-mode-hook #'org-special-block-extras-mode)

;; ⟨1′⟩ Or use: “M-x org-special-block-extras-mode” to turn it on/off
#+END_SRC

Our links work as soon as the package is loaded, yet our blocks need the mode on: sans it, a
=#+begin_rremark= exports as Org's own special block ---so Emacs warns, naming the block.

*Or* with use-package:
#+BEGIN_SRC emacs-lisp :tangle no
(use-package org-special-block-extras
  :ensure t
  :hook (org-mode . org-special-block-extras-mode)
  :custom
    ;; The places where I keep my ‘#+documentation’
    (org-docs-libraries
     '("~/org-special-block-extras/documentation.org"))
    ;; Details heading “flash pink” whenever the user hovers over them?
    (org-html-head-extra (concat org-html-head-extra "<style>  summary:hover {background:pink;} </style>"))
    ;; For the “doc:𝒳” link type
    ;;;; Nearly instantaneous display of tooltips.
    (setq tooltip-delay 0)
    ;;;;; Give user 30 seconds before tooltip automatically disappears.
    (setq tooltip-hide-delay 300)
    ;; The message prefixing a ‘tweet:url’ badge
    (org-link-twitter-excitement
     "This looks super neat (•̀ᴗ•́)و:")
    :config
    ;; fortune: link type moved to https://github.com/alhassy/fortune-of-the-day
    )
#+END_SRC

Then, provide support for a new type of special block, say re-using the ~src~
blocks that, say, folds up all such blocks in HTML export, by declaring the
following.
#+BEGIN_SRC emacs-lisp :tangle no
(org-defblock src (lang nil title nil exports nil file nil)
  "Fold-away all ‘src’ blocks as ‘<details>’ HTML export.
If a block has a ‘:title’, use that to title the ‘<details>’."
  (format "<details> <summary> %s </summary> <pre> %s </pre></details>"
          (or title (concat "Details; " lang))
          raw-contents))
#+END_SRC

:Links_from_tdehaeze_reddit:
14 days ago
I have made some research, and I could find nice resources:

- https://emacs.stackexchange.com/questions/44958/can-i-insert-a-prefix-to-org-babel-source-code-lines-on-export

- https://stackoverflow.com/questions/38857751/show-tangled-file-name-in-org-mode-code-block-export

- http://kitchingroup.cheme.cmu.edu/blog/2014/09/22/Showing-what-data-went-into-a-code-block-on-export/

- https://lists.gnu.org/archive/html/emacs-orgmode/2016-10/msg00282.html

- https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html#org306eaa4



Especially the last link were this seems to have been implemented. However it does not use "hooks" but rather define a new export back-end.

I'll let you know if I can combine different thing I can find to make something that works.

Cheers

--------------------------------------------------------------------------------

Context: https://www.reddit.com/r/emacs/comments/k2whsy/declaring_new_special_blocks_with_arguments/gevyoml/?context=3
:End:

** Minimal working example
   :PROPERTIES:
   :CUSTOM_ID: Minimal-working-example
   :END:

The following example showcases the prominent features of this library.

#+begin_example org
,#+begin_parallel
[[color:orange][Are you excited to learn some Lisp?]] [[blue:Yes!]]

Pop-quiz: How does doc:apply work?
,#+end_parallel

,#+begin_details Answer
link-here:solution
Syntactically, ~(apply f '(x0 ... xN)) = (f x0 ... xN)~.

[[remark:Musa][Ain't that cool?]]

,#+begin_spoiler aqua
That is, [[color:magenta][we can ((apply)) a function to a list of arguments!]]
,#+end_spoiler

,#+end_details

#+html: <br>
,#+begin_box
octoicon:report Note that kbd:C-x_C-e evaluates a Lisp form!
,#+end_box

/Allah[[margin:][The God of Abraham; known as Elohim in the Bible]] does
not burden a soul beyond what it can bear./ --- Quran 2:286

#+LATEX_HEADER: \usepackage{multicol}
#+LATEX_HEADER: \usepackage{tcolorbox}
#+latex: In the LaTeX output, we have a glossary.

show:GLOSSARY

badge:Thanks|for_reading
tweet:https://github.com/alhassy/org-special-block-extras
badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee
#+end_example

Here is what it looks like as HTML (left) and LaTeX (right):
#+attr_html: :width 800px
#+attr_latex: :width 100px
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/minimal-working-example.png

#+begin_details Tests
#+BEGIN_SRC emacs-lisp :tangle tests.el :comments link
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Run all MWE tests
;; (ert "mwe")

;; TODO: This should just be the text of mwe.org
(setq mwe (⟰
 "
,#+begin_parallel
Are you excited to learn some Lisp? blue:Yes!

Pop-quiz: How does doc:apply work?
,#+end_parallel

,#+begin_details Answer
link-here:solution
Syntactically, ~(apply f '(x0 ... xN)) = (f x0 ... xN)~.

Ain't that cool?

,#+begin_spoiler aqua
That is, we can ((apply)) a function to a list of arguments!
,#+end_spoiler

,#+end_details

,#+html: <br>
,#+begin_box
octoicon:report Note that 〔C-x C-e〕 evaluates a Lisp form!
,#+end_box

/Allah [[margin:][The God of Abraham; known as Elohim in the Bible]] does not burden a soul
beyond what it can bear./ --- Quran 2:286

,#+LATEX_HEADER: \\usepackage{multicol}
,#+LATEX_HEADER: \\usepackage{tcolorbox}
,#+latex: In the LaTeX output, we have a glossary.

show:GLOSSARY

badge:Thanks|for_reading
tweet:https://github.com/alhassy/org-special-block-extras
badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee
"))

(deftest "It exports to HTML without any problems"
  [mwe html-export]
  (find-file "tests/mwe.org")
  (should (org-html-export-to-html)))

(deftest "It starts with a 2-column div for ‘parallel’"
  [mwe parallel]
  (⇝ mwe "<div style=\"column-rule-style: none nil;column-count: 2;\">"
         (* anything)
         "</div>"))

(deftest "Its initial question is in ‘orange’, with answer in ‘blue’"
  [mwe color orange blue]
  (⇝ mwe "<span style=\"color:orange;\">Are you excited to learn some Lisp?</span>"
         (* anything)
         "<span style=\"color:blue;\">Yes!</span>"))

(deftest "Its second question, about ‘apply’, has a tooltip"
  [mwe doc]
  (⇝ mwe
     "Pop-quiz: How does "
     "<abbr class=\"tooltip\" title=\"Call FUNCTION with our remaining args, "
     "using our last arg as list of args.<br>Then return the value FUNCTION returns."
     "<br>With a single argument, call the argument’s first element using the"
     "<br>other elements as args.<br>Thus, (apply '+ 1 2 '(3 4)) returns 10."
     "<br><br>(fn FUNCTION &rest ARGUMENTS)\">apply</abbr> work?"))

(deftest "Its ‘details’ block is titled “Answer”, in green"
  [mwe details]
  (⇝ mwe
     "<details"
     (* anything) ;; styling
     "<summary>"
     (* anything) ;; styling
     "<font face=\"Courier\" size=\"3\" color=\"green\">"
     (* anything)
     "Answer"))

(deftest "Its details block begins with an SVG anchor identified as ‘solution’"
  [mwe link-here]
  (⇝ mwe "<details"
         (* anything) ;; styling
         "<a class=\"anchor\""
         (* anything)
         "href=\"#solution\">" ;; link-here:solution
         "<svg"
         (* anything)
         "</svg></a>"
         (* anything)
         "Syntactically, <code>(apply f '(x0 ... xN)) = (f x0 ... xN)</code>."))

(deftest "Its top-level remark is my name in a box, then the text, then a closing box delimiter"
  [mwe remark]
  (⇝ mwe "<details"
         (* anything)
         "<p style=\"color: black;\">"
         "<span style=\"border-width:1px;border-style:solid;padding:5px\">"
         "<strong>[Musa:</strong>"
         "</span>"
         " Ain't that cool?  "
         "<span style=\"border-width:1px;border-style:solid;padding:5px\"><strong>]</strong></span>"
         ))

(deftest "The aqua-coloured ‘spoiler’ appears within a magenta coloured piece of text"
  [mwe spoiler color magenta gensym]

  (⇝ mwe "<details"
         (* anything)
         ;; The local spoiler style is declared
         "<style>"
         (* anything) ;; A random id; e.g., #g289
         "{color: aqua; background-color:aqua;}"
         (* anything)
         ":hover {color: black; background-color:white;} "
         "</style>"
         (* anything)
         ;; Then it is used
         "That is, <span style=\"color:magenta;\">"
         "we can <span id="
         (* anything) ;; our random id is used here
         "> apply </span>" ;; Here is the spoiler!
         " a function to a list of arguments!</span>"
         (* anything)
         "</details>"))

(deftest "It has a title-less green box starting with an octoicon & kbd links have tooltips"
  [mwe box octoicon kbd]
  :expected-result :failed ;; FIXME The MWE has been updated, and more tests need to be written.
  (⇝ mwe
     "<div style=\"padding: 1em;"
     (* anything)
     "<h3></h3>"
     (* anything)
     "<svg" ;; octoicon:report
     (* anything)
     "Note that <abbr class=\"tooltip\""
     (* anything)
     "title=\"C-x C-e ∷ eval-last-sexp<br>Evaluate sexp before point; print value in the echo area."
     (* anything)
     "<kbd style=\"border-color: red\">C-x C-e</kbd></abbr> evaluates a Lisp form!"
     (* anything)
     "</div>"))

(deftest "Its Quranic quote has the user requested tooltip indicated by a small raised circle"
  [mwe margin]
  (⇝ mwe
     "Allah <abbr class=\"tooltip\""
     " title=\"The God of Abraham; known as Elohim in the Bible\">°</abbr>&emsp13;" ;; ∘ !
     " does not burden a soul beyond what it can bear."
     (* anything)
     "Quran 2:286"))

(deftest "It concludes with three beautiful badges"
  [mwe badge]
  ;; badge:Thanks|for_reading
  ;; tweet:https://github.com/alhassy/org-special-block-extras
  ;; badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee
  (⇝ mwe
     "<img src=\"https://img.shields.io/badge/Thanks-for_reading-nil?logo=nil\">"
     (* anything)
     "<img src=\"https://img.shields.io/twitter/url?url=https://github.com/alhassy/org-special-block-extras\">"
     (* anything)
     "<img src=\"https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee\">"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#+END_SRC
#+end_details

Other cool stuff...
#+attr_html: :width 800px
#+attr_latex: :width 100px
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/inference-rules.png

#+attr_html: :width 800px
#+attr_latex: :width 100px
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/calculational_proofs.png

#+attr_html: :width 800px
#+attr_latex: :width 100px
https://raw.githubusercontent.com/alhassy/org-special-block-extras/master/images/marginal_remarks.png

** COMMENT Live MWE                                                  :ignore:
   :PROPERTIES:
   :CUSTOM_ID: Live-MWE
   :END:

#+begin_parallel
Are you excited to learn some Lisp? blue:Yes!

Pop-quiz: How does doc:apply work?
#+end_parallel

#+begin_details Answer
link-here:solution
Syntactically, ~(apply f '(x0 ... xN)) = (f x0 ... xN)~.

Ain't that cool?

#+begin_spoiler aqua
That is, we can ((apply)) a function to a list of arguments!
#+end_spoiler

#+end_details

#+html: <br>
#+begin_box
octoicon:report Note that 〔C-x C-e〕 evaluates a Lisp form!
#+end_box

/Allah[[margin:][The God of Abraham; known as Elohim in the Bible]] does
not burden a soul beyond what it can bear./ --- Quran 2:286

#+LATEX_HEADER: \usepackage{multicol}
#+LATEX_HEADER: \usepackage{tcolorbox}
#+latex: In the LaTeX output, we have a glossary.

show:GLOSSARY

badge:Thanks|for_reading
tweet:https://github.com/alhassy/org-special-block-extras
badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee

** Bye!
   :PROPERTIES:
   :CUSTOM_ID: Bye
   :END:

badge:thanks|for_reading
tweet:https://github.com/alhassy/org-special-block-extras
badge:|buy_me_a coffee|gray|https://www.buymeacoffee.com/alhassy|buy-me-a-coffee

* Lisp Postamble                                                   :noexport:
  :PROPERTIES:
  :CUSTOM_ID: Postamble
  :END:
#+BEGIN_SRC emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(provide 'org-special-block-extras)

;;; org-special-block-extras.el ends here
#+END_SRC
* COMMENT MELPA Checks
  :PROPERTIES:
  :CUSTOM_ID: COMMENT-MELPA-Checks
  :END:
https://github.com/riscy/melpazoid

1. In Github repo: Create new file ⇒ License.txt ⇒ Select template ⇒ GNU 3
2. Ensure first line ends with: -*- lexical-binding: t; -*-
3. Include appropriate standard keywords;
   #+begin_src emacs-lisp
(pp finder-known-keywords)
   #+end_src

   #+RESULTS:
   #+begin_example
   ((abbrev . "abbreviation handling, typing shortcuts, and macros")
    (bib . "bibliography processors")
    (c . "C and related programming languages")
    (calendar . "calendar and time management tools")
    (comm . "communications, networking, and remote file access")
    (convenience . "convenience features for faster editing")
    (data . "editing data (non-text) files")
    (docs . "Emacs documentation facilities")
    (emulations . "emulations of other editors")
    (extensions . "Emacs Lisp language extensions")
    (faces . "fonts and colors for text")
    (files . "file editing and manipulation")
    (frames . "Emacs frames and window systems")
    (games . "games, jokes and amusements")
    (hardware . "interfacing with system hardware")
    (help . "Emacs help systems")
    (hypermedia . "links between text or other media types")
    (i18n . "internationalization and character-set support")
    (internal . "code for Emacs internals, build process, defaults")
    (languages . "specialized modes for editing programming languages")
    (lisp . "Lisp support, including Emacs Lisp")
    (local . "code local to your site")
    (maint . "Emacs development tools and aids")
    (mail . "email reading and posting")
    (matching . "searching, matching, and sorting")
    (mouse . "mouse support")
    (multimedia . "images and sound")
    (news . "USENET news reading and posting")
    (outlines . "hierarchical outlining and note taking")
    (processes . "processes, subshells, and compilation")
    (terminals . "text terminals (ttys)")
    (tex . "the TeX document formatter")
    (tools . "programming tools")
    (unix . "UNIX feature interfaces and emulators")
    (vc . "version control")
    (wp . "word processing"))
   #+end_example
4. Use #' instead of ' for function symbols
5. Use ‘-’ as a separator, not ‘/’.
6. Consider reading:
   https://github.com/bbatsov/emacs-lisp-style-guide#the-emacs-lisp-style-guide
7. Use cl-loop, cl-first, cl-second, cl-third instead of loop, first, second, third
8. byte-compile and address any concerns
9. =M-x checkdoc= on the lisp file to ensure it passes expected style issues.
   - Symbols =nil, t= should not appear in single quotes.
10. Ensure it byte-compiles without any problems.
11. Ensure that package-linter raises no issues; i.e., the following has no result.
     #+BEGIN_SRC emacs-lisp
 (use-package package-lint)
 (-let [it "lisp/org-special-block-extras.el"]
  (ignore-errors (kill-buffer it))
  (find-file-other-window it)
  (package-lint-buffer it))
 #+END_SRC
12. Create a recipe file by invoking: M-x package-build-create-recipe
    - Place it in: melpa/recipes/
    - The name of the file should be the name of the package, no extension.

       #+BEGIN_SRC emacs-lisp :tangle ~/melpa/recipes/org-special-block-extras
    (org-special-block-extras :fetcher github :repo "alhassy/org-special-block-extras")
    #+END_SRC
13. Commit and push everything in your project's repo!
14. Ensure the recipe builds successfully:
    #+BEGIN_SRC shell
    cd ~/melpa; rm ~/melpa/packages/o-*; make recipes/org-special-block-extras
    #+END_SRC

    #+RESULTS:
    : • Building package org-special-block-extras ...

15. Ensure the package installs properly from within Emacs:

      #+BEGIN_SRC emacs-lisp
(package-install-file "~/melpa/packages/o-20200417.238.el")
#+END_SRC

13. [@13] Produce a dedicated pull request branch

    #+begin_src emacs-lisp
    (magit-status "~/melpa")
    #+end_src

    + Now =b c= to checkout a new branch.
    + Push this branch on your melpa fork.
    + Go to the https://github.com/melpa/ repo and
      there'll be a big green PR button ^_^
* COMMENT Making ~README.org~
  :PROPERTIES:
  :CUSTOM_ID: COMMENT-Making-README-org
  :END:

  Evaluate the following source block with ~C-c C-c~ to produce a ~README~ file.

#+NAME: make-readme
#+BEGIN_SRC emacs-lisp
(with-temp-buffer
    (insert "
,#+EXPORT_FILE_NAME: README.md
#+HTML: <h1> A unified interface for Emacs' Org-mode block & link types (•̀ᴗ•́)و </h1>
#+HTML: <h2> Which is used to obtain 46 new custom blocks and 56 link types ¯\\_(ツ)_/¯ </h2>
,#+OPTIONS: toc:nil d:nil broken-links:t
,#+html: <div align=\"center\">
,#+INCLUDE: ~/org-special-block-extras/org-special-block-extras.org::#Abstract :only-contents t
,#+html: </div>
# +TOC: headlines 2
,* Installation Instructions
,#+INCLUDE: ~/org-special-block-extras/org-special-block-extras.org::#Installation-Instructions :only-contents t
,* Minimal working example
,#+INCLUDE: ~/org-special-block-extras/org-special-block-extras.org::#Minimal-working-example :only-contents t
,* Bye!
,#+INCLUDE: ~/org-special-block-extras/org-special-block-extras.org::#Bye :only-contents t
")
    (let ((org-export-use-babel nil) (org-export-with-broken-links t))
      (org-mode)
      (org-md-export-to-markdown)))
#+END_SRC

#+RESULTS: make-readme
: README.md

*Then* use =grip= to see that this looks reasonable.

* COMMENT Glossary                                                   :ignore:
  :PROPERTIES:
  :CUSTOM_ID: Glossary
  :END:

#+latex: \section*{Glossary}
#+latex: \addcontentsline{toc}{section}{Glossary}

 show:GLOSSARY
* Footnotes
  :PROPERTIES:
  :CUSTOM_ID: Footnotes
  :END:

[fn:1] See /A tutorial on the universality and expressiveness of fold/ and
/Unifying Structured Recursion Schemes/