aboutsummaryrefslogtreecommitdiff
path: root/seam-html.el
diff options
context:
space:
mode:
authorSpencer Williams <spnw@plexwave.org>2025-04-07 17:16:05 -0400
committerSpencer Williams <spnw@plexwave.org>2025-04-07 17:16:05 -0400
commit41e4bce247ad81945aa92b6fd66b1a6d107988aa (patch)
tree0aa6c2938034c43f3dcf34754381553a2b6b753a /seam-html.el
parent5c283f920cca7421737c57e85ce3c9a645c7f2b1 (diff)
Move code to lisp/ subdirectory
Diffstat (limited to 'seam-html.el')
-rw-r--r--seam-html.el366
1 files changed, 0 insertions, 366 deletions
diff --git a/seam-html.el b/seam-html.el
deleted file mode 100644
index 018e56f..0000000
--- a/seam-html.el
+++ /dev/null
@@ -1,366 +0,0 @@
-;;; seam-html.el --- Seam HTML exporter -*- lexical-binding: t -*-
-
-;; Copyright (C) 2025 Spencer Williams
-
-;; Author: Spencer Williams <spnw@plexwave.org>
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is not part of GNU Emacs.
-
-;; 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 <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Seam's HTML exporter.
-;;
-;; This was blithely hacked together using large chunks of code lifted
-;; straight from ox-html.el, and could do with much improvement.
-;;
-;; Original ox-html code is licensed under GPL v3+. Copyright (c)
-;; 2011-2025 Free Software Foundation, Inc. Original authors: Carsten
-;; Dominik <carsten.dominik@gmail.com> and Jambunathan K <kjambunathan
-;; at gmail dot com>.
-
-;;; Code:
-
-(require 'ox-html)
-
-;;; NOTE: This function does not respect `:headline-levels' or
-;;; `:html-self-link-headlines'.
-(defun seam-html-headline (headline contents info)
- "Transcode a HEADLINE element from Org to HTML.
-CONTENTS holds the contents of the headline. INFO is a plist
-holding contextual information."
- (cond
- ((org-element-property :SEAM-TITLE-P headline)
- contents)
- ((org-element-property :footnote-section-p headline)
- nil)
- (t
- (let* ((level (+ (org-export-get-relative-level headline info)
- (1- (plist-get info :html-toplevel-hlevel))))
- (text (org-export-data (org-element-property :title headline) info))
- (contents (or contents ""))
- (id (org-html--reference headline info))
- (todo (and (plist-get info :with-todo-keywords)
- (let ((todo (org-element-property :todo-keyword headline)))
- (and todo (org-export-data todo info)))))
- (todo-type (and todo (org-element-property :todo-type headline)))
- (priority (and (plist-get info :with-priority)
- (org-element-property :priority headline)))
- (tags (and (plist-get info :with-tags)
- (org-export-get-tags headline info)))
- (full-text (funcall (plist-get info :html-format-headline-function)
- todo todo-type priority text tags info)))
- (let ((headline-class
- (org-element-property :HTML_HEADLINE_CLASS headline)))
- (format "%s%s\n"
- (format "<h%d id=\"%s\"%s>%s</h%d>\n"
- level
- id
- (if (not headline-class) ""
- (format " class=\"%s\"" headline-class))
- full-text
- level)
- contents))))))
-
-(defun seam-html-section (_section contents _info)
- "Transcode a SECTION element from Org to HTML.
-CONTENTS holds the contents of the section."
- contents)
-
-(defvar seam-html-standalone-image-predicate)
-(defun seam-html-standalone-image-p (element info)
- "Non-nil if ELEMENT is a standalone image.
-
-INFO is a plist holding contextual information.
-
-An element or object is a standalone image when
-
- - its type is `paragraph' and its sole content, save for white
- spaces, is a link that qualifies as an inline image;
-
- - its type is `link' and its containing paragraph has no other
- content save white spaces.
-
-Bind `seam-html-standalone-image-predicate' to constrain paragraph
-further. For example, to check for only captioned standalone
-images, set it to:
-
- (lambda (paragraph) (org-element-property :caption paragraph))"
- (let ((paragraph (pcase (org-element-type element)
- (`paragraph element)
- (`link (org-element-parent element)))))
- (and (org-element-type-p paragraph 'paragraph)
- (or (not (and (boundp 'seam-html-standalone-image-predicate)
- (fboundp seam-html-standalone-image-predicate)))
- (funcall seam-html-standalone-image-predicate paragraph))
- (catch 'exit
- (let ((link-count 0))
- (org-element-map (org-element-contents paragraph)
- (cons 'plain-text org-element-all-objects)
- (lambda (obj)
- (when (pcase (org-element-type obj)
- (`plain-text (org-string-nw-p obj))
- (`link (or (> (cl-incf link-count) 1)
- (not (org-html-inline-image-p obj info))))
- (_ t))
- (throw 'exit nil)))
- info nil 'link)
- (= link-count 1))))))
-
-(defun seam-html-link (link desc info)
- "Transcode a LINK object from Org to HTML.
-DESC is the description part of the link, or the empty string.
-INFO is a plist holding contextual information. See
-`org-export-data'."
- (let* ((html-ext (plist-get info :html-extension))
- (dot (when (> (length html-ext) 0) "."))
- (link-org-files-as-html-maybe
- (lambda (raw-path info)
- ;; Treat links to `file.org' as links to `file.html', if
- ;; needed. See `org-html-link-org-files-as-html'.
- (save-match-data
- (cond
- ((and (plist-get info :html-link-org-files-as-html)
- (let ((case-fold-search t))
- (string-match "\\(.+\\)\\.org\\(?:\\.gpg\\)?$" raw-path)))
- (concat (match-string 1 raw-path) dot html-ext))
- (t raw-path)))))
- (link-type (org-element-property :type link))
- (raw-path (org-element-property :path link))
- ;; Ensure DESC really exists, or set it to nil.
- (desc (org-string-nw-p desc))
- (path
- (cond
- ((string= "seam" link-type)
- (let ((slug raw-path))
- (when-let ((file (seam-lookup-slug slug)))
- (let ((type (seam-get-note-type file)))
- (when (and (member type seam-export--types)
- (file-exists-p (seam-make-file-name slug type)))
- (concat seam-export--root-path
- slug
- (if seam-export--no-extension "" ".html")))))))
- ((string= "file" link-type)
- ;; During publishing, turn absolute file names belonging
- ;; to base directory into relative file names. Otherwise,
- ;; append "file" protocol to absolute file name.
- (setq raw-path
- (org-export-file-uri
- (org-publish-file-relative-name raw-path info)))
- ;; Possibly append `:html-link-home' to relative file
- ;; name.
- (let ((home (and (plist-get info :html-link-home)
- (org-trim (plist-get info :html-link-home)))))
- (when (and home
- (plist-get info :html-link-use-abs-url)
- (not (file-name-absolute-p raw-path)))
- (setq raw-path (concat (file-name-as-directory home) raw-path))))
- ;; Maybe turn ".org" into ".html".
- (setq raw-path (funcall link-org-files-as-html-maybe raw-path info))
- ;; Add search option, if any. A search option can be
- ;; relative to a custom-id, a headline title, a name or
- ;; a target.
- (let ((option (org-element-property :search-option link)))
- (if (not option) raw-path
- (let ((path (org-element-property :path link)))
- (concat raw-path
- "#"
- (org-publish-resolve-external-link option path t))))))
- (t (url-encode-url (concat link-type ":" raw-path)))))
- (attributes-plist
- (org-combine-plists
- ;; Extract attributes from parent's paragraph. HACK: Only
- ;; do this for the first link in parent (inner image link
- ;; for inline images). This is needed as long as
- ;; attributes cannot be set on a per link basis.
- (let* ((parent (org-element-parent-element link))
- (link (let ((container (org-element-parent link)))
- (if (and (org-element-type-p container 'link)
- (org-html-inline-image-p link info))
- container
- link))))
- (and (eq link (org-element-map parent 'link #'identity info t))
- (org-export-read-attribute :attr_html parent)))
- ;; Add Seam internal link class if appropriate.
- (when (and seam-export--internal-link-class (string= "seam" link-type))
- (list :class seam-export--internal-link-class))
- ;; Also add attributes from link itself. Currently, those
- ;; need to be added programmatically before `org-html-link'
- ;; is invoked, for example, by backends building upon HTML
- ;; export.
- (org-export-read-attribute :attr_html link)))
- (attributes
- (let ((attr (org-html--make-attribute-string attributes-plist)))
- (if (org-string-nw-p attr) (concat " " attr) ""))))
- (cond
- ;; Link type is handled by a special function.
- ((org-export-custom-protocol-maybe link desc 'html info))
- ;; Image file.
- ((and (plist-get info :html-inline-images)
- (org-export-inline-image-p
- link (plist-get info :html-inline-image-rules)))
- (org-html--format-image path attributes-plist info))
- ;; Radio target: Transcode target's contents and use them as
- ;; link's description.
- ((string= link-type "radio")
- (let ((destination (org-export-resolve-radio-link link info)))
- (if (not destination) desc
- (format "<a href=\"#%s\"%s>%s</a>"
- (org-export-get-reference destination info)
- attributes
- desc))))
- ;; Links pointing to a headline: Find destination and build
- ;; appropriate referencing command.
- ((member link-type '("custom-id" "fuzzy" "id"))
- (let ((destination (if (string= link-type "fuzzy")
- (org-export-resolve-fuzzy-link link info)
- (org-export-resolve-id-link link info))))
- (pcase (org-element-type destination)
- ;; ID link points to an external file.
- (`plain-text
- (let ((fragment (concat org-html--id-attr-prefix raw-path))
- ;; Treat links to ".org" files as ".html", if needed.
- (path (funcall link-org-files-as-html-maybe
- destination info)))
- (format "<a href=\"%s#%s\"%s>%s</a>"
- path fragment attributes (or desc destination))))
- ;; Fuzzy link points nowhere.
- (`nil
- (;; format "<i>%s</i>"
- identity
- (or desc
- (org-export-data
- (org-element-property :raw-link link) info))))
- ;; Link points to a headline.
- (`headline
- (let ((href (org-html--reference destination info))
- ;; What description to use?
- (desc
- ;; Case 1: Headline is numbered and LINK has no
- ;; description. Display section number.
- (if (and (org-export-numbered-headline-p destination info)
- (not desc))
- (mapconcat #'number-to-string
- (org-export-get-headline-number
- destination info) ".")
- ;; Case 2: Either the headline is un-numbered or
- ;; LINK has a custom description. Display LINK's
- ;; description or headline's title.
- (or desc
- (org-export-data
- (org-element-property :title destination) info)))))
- (format "<a href=\"#%s\"%s>%s</a>" href attributes desc)))
- ;; Fuzzy link points to a target or an element.
- (_
- (if (and destination
- (memq (plist-get info :with-latex) '(mathjax t))
- (org-element-type-p destination 'latex-environment)
- (eq 'math (org-latex--environment-type destination)))
- ;; Caption and labels are introduced within LaTeX
- ;; environment. Use "ref" or "eqref" macro, depending on user
- ;; preference to refer to those in the document.
- (format (plist-get info :html-equation-reference-format)
- (org-html--reference destination info))
- (let* ((ref (org-html--reference destination info))
- (seam-html-standalone-image-predicate
- #'org-html--has-caption-p)
- (counter-predicate
- (if (org-element-type-p destination 'latex-environment)
- #'org-html--math-environment-p
- #'org-html--has-caption-p))
- (number
- (cond
- (desc nil)
- ((seam-html-standalone-image-p destination info)
- (org-export-get-ordinal
- (org-element-map destination 'link #'identity info t)
- info '(link) 'seam-html-standalone-image-p))
- (t (org-export-get-ordinal
- destination info nil counter-predicate))))
- (desc
- (cond (desc)
- ((not number) "No description for this link")
- ((numberp number) (number-to-string number))
- (t (mapconcat #'number-to-string number ".")))))
- (format "<a href=\"#%s\"%s>%s</a>" ref attributes desc)))))))
- ;; Coderef: replace link with the reference name or the
- ;; equivalent line number.
- ((string= link-type "coderef")
- (let ((fragment (concat "coderef-" (org-html-encode-plain-text raw-path))))
- (format "<a href=\"#%s\" %s%s>%s</a>"
- fragment
- (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \
-'%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
- fragment fragment)
- attributes
- (format (org-export-get-coderef-format raw-path desc)
- (org-export-resolve-coderef raw-path info)))))
- ;; External link with a description part.
- ((and path desc)
- (format "<a href=\"%s\"%s>%s</a>"
- (org-html-encode-plain-text path)
- attributes
- desc))
- ;; External link without a description part.
- (path
- (let ((path (org-html-encode-plain-text path)))
- (format "<a href=\"%s\"%s>%s</a>" path attributes path)))
- ;; No path, only description.
- (t desc))))
-
-
-(defun seam-html-src-block (src-block _contents info)
- "Transcode a SRC-BLOCK element from Org to HTML.
-CONTENTS holds the contents of the item. INFO is a plist holding
-contextual information."
- (if (org-export-read-attribute :attr_html src-block :textarea)
- (org-html--textarea-block src-block)
- (let* ((lang (org-element-property :language src-block))
- (code (org-html-format-code src-block info))
- (label (let ((lbl (org-html--reference src-block info t)))
- (if lbl (format " id=\"%s\"" lbl) ""))))
- (format "<pre>%s%s</pre>"
- ;; Build caption.
- (let ((caption (org-export-get-caption src-block)))
- (if (not caption) ""
- (let ((listing-number
- (format
- "<span class=\"listing-number\">%s </span>"
- (format
- (org-html--translate "Listing %d:" info)
- (org-export-get-ordinal
- src-block info nil #'org-html--has-caption-p)))))
- (format "<label class=\"org-src-name\">%s%s</label>"
- listing-number
- (org-trim (org-export-data caption info))))))
- ;; Contents.
- (format "<code class=\"src src-%s\"%s>%s</code>"
- ;; Lang being nil is OK.
- lang label code)))))
-
-(org-export-define-derived-backend
- 'seam
- 'html
- :translate-alist
- `((headline . seam-html-headline)
- (link . seam-html-link)
- (section . seam-html-section)
- (src-block . seam-html-src-block)))
-
-(provide 'seam-html)
-
-;;; seam-html.el ends here