Skip to content

Instantly share code, notes, and snippets.

@include-yy
Created February 5, 2023 07:13
Show Gist options
  • Save include-yy/2dec9f7fa5aeb0089858e1a01d84096d to your computer and use it in GitHub Desktop.
Save include-yy/2dec9f7fa5aeb0089858e1a01d84096d to your computer and use it in GitHub Desktop.
simple org html export config

对 ox-html 的一些 advice

记得打开 org-html-prefer-user-labels

(defun yynt|org-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."
(unless (org-element-property :footnote-section-p headline)
(let* ((numberedp (org-export-numbered-headline-p headline info))
(numbers (org-export-get-headline-number headline info))
(level (+ (org-export-get-relative-level headline info)
(1- (plist-get info :html-toplevel-hlevel))))
(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)))
(text (org-export-data (org-element-property :title headline) info))
(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))
(contents (or contents ""))
(id (org-html--reference headline info))
(formatted-text
(if (plist-get info :html-self-link-headlines)
(format "<a href=\"#%s\">%s</a>" id full-text)
full-text)))
(if (org-export-low-level-p headline info)
;; This is a deep sub-tree: export it as a list item.
(let* ((html-type (if numberedp "ol" "ul")))
(concat
(and (org-export-first-sibling-p headline info)
(apply #'format "<%s class=\"org-%s\">\n"
(make-list 2 html-type)))
(org-html-format-list-item
contents (if numberedp 'ordered 'unordered)
nil info nil
(concat (org-html--anchor id nil nil info) formatted-text)) "\n"
(and (org-export-last-sibling-p headline info)
(format "</%s>\n" html-type))))
;; Standard headline. Export it as a section.
(let ((extra-class
(org-element-property :HTML_CONTAINER_CLASS headline))
(headline-class
(org-element-property :HTML_HEADLINE_CLASS headline))
(first-content (car (org-element-contents headline))))
(format "<%s class=\"%s\">%s%s</%s>\n"
(org-html--container headline info)
(concat (format "outline-%d" level)
(and extra-class " ")
extra-class)
(format "\n<h%d id=\"%s\"%s>%s</h%d>\n"
level
id
(if (not headline-class) ""
(format " class=\"%s\"" headline-class))
(concat
(and numberedp
(format
"<span class=\"section-number-%d\">%s</span> "
level
(concat (mapconcat #'number-to-string numbers ".") ".")))
formatted-text)
level)
;; When there is no section, pretend there is an
;; empty one to get the correct <div
;; class="outline-...> which is needed by
;; `org-info.js'.
(if (eq (org-element-type first-content) 'section) contents
(concat (org-html-section first-content "" info) contents))
(org-html--container headline info)))))))
(defun yynt|org-html-section (section contents info)
"Transcode a SECTION element from Org to HTML.
CONTENTS holds the contents of the section. INFO is a plist
holding contextual information."
(let ((parent (org-export-get-parent-headline section)))
;; Before first headline: no container, just return CONTENTS.
(if (not parent) contents
;; Get div's class and id references.
(let* ((class-num (+ (org-export-get-relative-level parent info)
(1- (plist-get info :html-toplevel-hlevel))))
(section-number
(and (org-export-numbered-headline-p parent info)
(mapconcat
#'number-to-string
(org-export-get-headline-number parent info) "-"))))
;; Build return value.
(format "<div class=\"outline-text-%d\">\n%s</div>\n"
class-num
(or contents ""))))))
(advice-add 'org-html-headline :override 'yynt|org-html-headline)
(advice-add 'org-html-section :override 'yynt|org-html-section)
(defun yynt|org-html--reference (datum info &optional named-only)
"Return an appropriate reference for DATUM.
DATUM is an element or a `target' type object. INFO is the
current export state, as a plist.
When NAMED-ONLY is non-nil and DATUM has no NAME keyword, return
nil. This doesn't apply to headlines, inline tasks, radio
targets and targets."
(let* ((type (org-element-type datum))
(user-label
(org-element-property
(pcase type
((or `headline `inlinetask) :CUSTOM_ID)
((or `radio-target `target) :value)
(_ :name))
datum)))
(when (eq type 'headline)
(unless user-label
(let ((numbers (org-export-get-headline-number datum info)))
(setq user-label (concat "org-h-" (mapconcat #'number-to-string numbers "-"))))))
(when (org-html-standalone-image-p datum info)
(unless user-label (setq user-label "")))
(when (eq type 'special-block)
(unless user-label
(setq user-label nil)
(setq named-only t)))
(cond
((and user-label
(or (plist-get info :html-prefer-user-labels)
;; Used CUSTOM_ID property unconditionally.
(memq type '(headline inlinetask))))
user-label)
((and named-only
(not (memq type '(headline inlinetask radio-target target)))
(not user-label))
nil)
(t
(org-export-get-reference datum info)))))
(advice-add 'org-html--reference :override 'yynt|org-html--reference)
(defun yynt|org-html--wrap-image (contents info &optional caption label)
"Wrap CONTENTS string within an appropriate environment for images.
INFO is a plist used as a communication channel. When optional
arguments CAPTION and LABEL are given, use them for caption and
\"id\" attribute."
(let ((html5-fancy (org-html--html5-fancy-p info)))
(format (if html5-fancy "\n<figure%s>\n%s%s</figure>" ;;去掉了最后一个 \n
"\n<div%s class=\"figure\">\n%s%s\n</div>")
;; ID.
(if (org-string-nw-p label) (format " id=\"%s\"" label) "")
;; Contents.
(if html5-fancy contents (format "<p>%s</p>" contents))
;; Caption.
(if (not (org-string-nw-p caption)) ""
(format (if html5-fancy "<figcaption>%s</figcaption>\n" ;; 去掉和加上 \n
"\n<p>%s</p>")
caption)))))
(advice-add 'org-html--wrap-image :override 'yynt|org-html--wrap-image)
;;(advice-remove 'org-html--wrap-image 'yynt|org-html--wrap-image)
(defun yynt|org-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'.
(cond
((and (plist-get info :html-link-org-files-as-html)
(string= ".org"
(downcase (file-name-extension raw-path "."))))
(concat (file-name-sans-extension raw-path) dot html-ext))
(t raw-path))))
(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
((member type '("http" "https" "ftp" "mailto" "news"))
(url-encode-url (concat type ":" raw-path)))
((string= "file" 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)
(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 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-export-get-parent-element link))
(link (let ((container (org-export-get-parent link)))
(if (and (eq 'link (org-element-type container))
(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)))
;; 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= 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)
(org-html--reference destination info)
attributes
desc))))
;; Links pointing to a headline: Find destination and build
;; appropriate referencing command.
((member type '("custom-id" "fuzzy" "id"))
(let ((destination (if (string= 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 "ID-" 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>"
(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))
(eq 'latex-environment (org-element-type destination))
(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))
(org-html-standalone-image-predicate
#'org-html--has-caption-p)
(counter-predicate
(if (eq 'latex-environment (org-element-type destination))
#'org-html--math-environment-p
#'org-html--has-caption-p))
(number
(cond
(desc nil)
((org-html-standalone-image-p destination info)
(org-export-get-ordinal
(org-element-map destination 'link #'identity info t)
info 'link 'org-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= type "coderef")
(let ((fragment (concat "coderef-" (org-html-encode-plain-text 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 path desc)
(org-export-resolve-coderef 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. Try to do something useful.
(t
(format "<i>%s</i>" desc)))))
(advice-add 'org-html-link :override 'yynt|org-html-link)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment