*** org-mode/lisp/ox-html.el 2024-08-05 17:15:57.628595589 +0200 --- org-mode-multipage/lisp/ox-html.el 2024-08-05 17:11:54.979585435 +0200 *************** *** 4,9 **** --- 4,11 ---- ;; Author: Carsten Dominik ;; Jambunathan K + ;; multipage export by Orm Finnendahl + ;; ;; Maintainer: TEC ;; Keywords: outlines, hypermedia, calendar, text *************** *** 82,88 **** --- 84,94 ---- (latex-fragment . org-html-latex-fragment) (line-break . org-html-line-break) (link . org-html-link) + (multipage-inner-template . org-html-multipage-inner-template) + (multipage-template . org-html-multipage-template) (node-property . org-html-node-property) + (org-data . org-html-transcode-org-data) + ;;; (org-page . org-html-transcode-org-page) (paragraph . org-html-paragraph) (plain-list . org-html-plain-list) (plain-text . org-html-plain-text) *************** *** 108,118 **** --- 114,126 ---- (verse-block . org-html-verse-block)) :filters-alist '((:filter-options . org-html-infojs-install-script) (:filter-parse-tree . org-html-image-link-filter) + (:multipage-split . org-html-multipage-split) (:filter-final-output . org-html-final-function)) :menu-entry '(?h "Export to HTML" ((?H "As HTML buffer" org-html-export-as-html) (?h "As HTML file" org-html-export-to-html) + (?m "As HTML Multipage files" org-html-export-to-multipage) (?o "As HTML file and open" (lambda (a s v b) (if a (org-html-export-to-html t s v b) *************** *** 134,141 **** (:html-head "HTML_HEAD" nil org-html-head newline) (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) (:subtitle "SUBTITLE" nil nil parse) ! (:html-head-include-default-style ! nil "html-style" org-html-head-include-default-style) (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts) (:html-allow-name-attribute-in-anchors nil nil org-html-allow-name-attribute-in-anchors) --- 142,148 ---- (:html-head "HTML_HEAD" nil org-html-head newline) (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline) (:subtitle "SUBTITLE" nil nil parse) ! (:html-head-include-default-style nil "html-style" org-html-head-include-default-style) (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts) (:html-allow-name-attribute-in-anchors nil nil org-html-allow-name-attribute-in-anchors) *************** *** 158,163 **** --- 165,190 ---- (:html-mathjax-options nil nil org-html-mathjax-options) (:html-mathjax-template nil nil org-html-mathjax-template) (:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format) + (:html-multipage-clear-export-directory nil "html-multipage-clear-export-directory" + org-html-multipage-clear-export-directory) + (:html-multipage-export-directory + nil "html-multipage-export-directory" org-html-multipage-export-directory) + (:html-multipage-head-include-default-style + nil "html-multipage-include-default-style" org-html-multipage-head-include-default-style) + (:html-multipage-join-empty-bodies + nil "html-multipage-join-empty-bodies" org-html-multipage-join-empty-bodies) + (:html-multipage-nav-format nil nil org-html-multipage-nav-format) + (:html-multipage-numbered-filenames nil "html-multipage-numbered-filenames" + org-html-multipage-numbered-filenames) + (:html-multipage-open nil "html-multipage-open" org-html-multipage-open) + (:html-multipage-postamble-position + nil "html-multipage-postamble-position" org-html-multipage-postamble-position) + (:html-multipage-preamble-position + nil "html-multipage-preamble-position" org-html-multipage-preamble-position) + (:html-multipage-split-hooks nil nil org-html-multipage-split-hooks) + (:html-multipage-split-level nil "html-multipage-split-level" org-html-multipage-split-level) + (:html-multipage-toc-to-top nil "html-multipage-toc-to-top" org-html-multipage-toc-to-top) + (:html-numbered-link-format nil nil org-html-numbered-link-format) (:html-postamble-format nil nil org-html-postamble-format) (:html-preamble-format nil nil org-html-preamble-format) (:html-prefer-user-labels nil nil org-html-prefer-user-labels) *************** *** 171,179 **** nil nil org-html-table-use-header-tags-for-first-column) (:html-tag-class-prefix nil nil org-html-tag-class-prefix) (:html-text-markup-alist nil nil org-html-text-markup-alist) (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix) (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel) ! (:html-use-infojs nil nil org-html-use-infojs) (:html-validation-link nil nil org-html-validation-link) (:html-viewport nil nil org-html-viewport) (:html-inline-images nil nil org-html-inline-images) --- 198,207 ---- nil nil org-html-table-use-header-tags-for-first-column) (:html-tag-class-prefix nil nil org-html-tag-class-prefix) (:html-text-markup-alist nil nil org-html-text-markup-alist) + (:html-toc-title nil "html-toc-title" org-html-toc-title) (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix) (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel) ! (:html-use-infojs nil nil org-export-html-use-infojs) (:html-validation-link nil nil org-html-validation-link) (:html-viewport nil nil org-html-viewport) (:html-inline-images nil nil org-html-inline-images) *************** *** 186,191 **** --- 214,221 ---- (:html-klipse-css nil nil org-html-klipse-css) (:html-klipse-js nil nil org-html-klipse-js) (:html-klipse-selection-script nil nil org-html-klipse-selection-script) + ;;; (:multipage-split nil nil org-html-multipage-split) + ;;; (:multipage nil nil org-html-multipage) (:infojs-opt "INFOJS_OPT" nil nil) ;; Redefine regular options. (:creator "CREATOR" nil org-html-creator-string) *************** *** 462,467 **** --- 492,720 ---- :package-version '(Org . "9.5") :type 'string) + (defcustom org-html-multipage-style-default + "" + "The default style specification for exported HTML files. + You can use `org-html-head' and `org-html-head-extra' to add to + this style. If you don't want to include this default style, + customize `org-html-head-include-default-style'." + :group 'org-export-html + :package-version '(Org . "9.8") + :type 'string) ;;; User Configuration Variables *************** *** 486,492 **** (home LINK_HOME :html-link-home)) "JavaScript options, long form for script, default values.") ! (defcustom org-html-use-infojs 'when-configured "Non-nil when Sebastian Rose's Java Script org-info.js should be active. This option can be nil or t to never or always use the script. It can also be the symbol `when-configured', meaning that the --- 739,745 ---- (home LINK_HOME :html-link-home)) "JavaScript options, long form for script, default values.") ! (defcustom org-export-html-use-infojs 'when-configured "Non-nil when Sebastian Rose's Java Script org-info.js should be active. This option can be nil or t to never or always use the script. It can also be the symbol `when-configured', meaning that the *************** *** 501,506 **** --- 754,766 ---- (const :tag "When configured in buffer" when-configured) (const :tag "Always" t))) + ;; (defcustom org-html-multipage nil + ;; "Boolean indicating multipage export." + ;; :group 'org-export-html + ;; :version "29.4" + ;; :package-version '(Org . "9.8") + ;; :type 'boolean) + (defcustom org-html-infojs-options (mapcar (lambda (x) (cons (car x) (nth 2 x))) org-html-infojs-opts-table) "Options settings for the INFOJS JavaScript. *************** *** 849,854 **** --- 1109,1129 ---- :group 'org-export-html :type 'boolean) + (defcustom org-html-numbered-link-format + '("Chapter %s" + "Section %s" + "Fig. %s") + "Format for the labels of numbered links. + + The first string is used for links to Chapters, the second for + links to Sections and the third for links to Figures. %s will be + replaced by the number of the reference. The strings get + translated using org-html--translate." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + ;;;; Links :: Inline images (defcustom org-html-inline-images t *************** *** 1384,1389 **** --- 1659,1673 ---- (list (string :tag "Language") (string :tag "Format string")))) + (defcustom org-html-toc-title "Table of Contents" + "The string tp be used for the title of the table of contents. It + will be passed to org-html-translate." + :group 'org-export-html + :package-version '(Org . "9.8") + :version "29.4" + :type 'string + :safe #'stringp) + (defcustom org-html-validation-link "Validate" "Link to HTML validation service." *************** *** 1522,1529 **** --- 1806,1954 ---- :version "24.4" :package-version '(Org . "8.0") :type 'boolean) + + (defcustom org-html-multipage-clear-export-directory t + "Boolean. If non-nil remove all .html files from the export + directory before exporting." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-export-directory "html" + "The default directory for exported HTML files." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'string) + + (defcustom org-html-multipage-head-include-default-style t + "Non-nil means include the default style in exported HTML files. + The actual style is defined in `org-html-style-default' and + should not be modified. Use `org-html-head' to use your own + style information." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-join-empty-bodies t + "Recursively join subheadlines, if a headline doesn't contain any + text before its Subheadline. + + Example: + + * Headline 1 + ** Subheadline 1.1 + *** Subsubheadline 1.1.1 + Text of Subsubheadline 1.1.1 + + will be put on the same HTML page if this option is set, + otherwise Headline 1 And Subheadline 1.1 will be put on a + separate HTML page with empty content. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-nav-format + '("
%s
" + "Next: %s , " + "Previous: %s , " + "Up: %s , " + "Home: %s ") + "Snippets used to insert the NEXT, PREV, HOME and UP links in + multipage output. The list contains format strings for the HTML + div and the navigation elements. The %s in the HTML div will + receive a concatenated string of the navigation elements. The + first %s in the navigation elements will receive the link, + the second the title" + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + + (defcustom org-html-multipage-numbered-filenames t + "Boolean indicating whether filenames in multipage export should + get their headline-numbering prepended. Note: This option is + independent of the num: option and the backend guarantees that + filenames are unique in any case." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + + (defcustom org-html-multipage-open 'nil + "If and where to open the top page of the multipage html after + export." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const browser) (const buffer) (const nil))) + + (defcustom org-html-multipage-postamble-position 'bottom + "The position of the postamble in the html output. + + bottom - at the bottom of the page, directly before + + text-content - at the bottom of the text-content. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const bottom) (const text-content))) + + (defcustom org-html-multipage-preamble-position 'top + "If and where to open the top page of the multipage html after + export. + + top - at the top of the page, directly after + + text-content - at the top of the text-content. + + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const top) (const text-content))) + + (defcustom org-html-multipage-split-hooks nil + "list of additional custom functions to be called during the + export after multipage splitting has taken place and before + transcoding with info as input. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'list) + + (defcustom org-html-multipage-split-level 'toc + "How to split the ORG file into multiple HTML pages. + + toc - split each entry of the toc into a separate page. + + number - a number indicating the maximum headline-level for + splitting. + " + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type '(choice (const toc) (number :tag "Headline Level" 3))) + + (defcustom org-html-multipage-toc-to-top t + "If t links in the TOC will always point to the top of the page, + otherwise it will link directly to the referenced headline + element." + :group 'org-export-html + :version "29.4" + :package-version '(Org . "9.8") + :type 'boolean) + ;;;###autoload (put 'org-html-head-include-default-style 'safe-local-variable 'booleanp) + (put 'org-html-multipage-head-include-default-style 'safe-local-variable 'booleanp) + (put 'org-html-multipage-join-empty-bodies 'safe-local-variable 'booleanp) (defcustom org-html-head "" "Org-wide head definitions for exported HTML files. *************** *** 1873,1890 **** (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." ! (pcase (org-export-collect-footnote-definitions info) (`nil nil) (definitions - (format - (plist-get info :html-footnotes-section) - (org-html--translate "Footnotes" info) (format ! "\n%s\n" ! (mapconcat ! (lambda (definition) ! (pcase definition ! (`(,n ,label ,def) ;; Do not assign number labels as they appear in Org mode ;; - the footnotes are re-numbered by ;; `org-export-get-footnote-number'. If the label is not --- 2298,2315 ---- (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." ! (pcase (org-export-collect-footnote-definitions info (plist-get info :tl-headline)) (`nil nil) (definitions (format ! (plist-get info :html-footnotes-section) ! (org-html--translate "Footnotes" info) ! (format ! "\n%s\n" ! (mapconcat ! (lambda (definition) ! (pcase definition ! (`(,n ,label ,def) ;; Do not assign number labels as they appear in Org mode ;; - the footnotes are re-numbered by ;; `org-export-get-footnote-number'. If the label is not *************** *** 1911,1918 **** (if (not inline?) contents (format "

%s

" contents)))))))) ! definitions ! "\n")))))) ;;; Template --- 2336,2343 ---- (if (not inline?) contents (format "

%s

" contents)))))))) ! definitions ! "\n")))))) ;;; Template *************** *** 2018,2025 **** INFO is a plist used as a communication channel." (org-element-normalize-string (concat ! (when (plist-get info :html-head-include-default-style) ! (org-element-normalize-string org-html-style-default)) (org-html-normalize-string-or-function (plist-get info :html-head) info) (org-html-normalize-string-or-function (plist-get info :html-head-extra) info) --- 2443,2453 ---- INFO is a plist used as a communication channel." (org-element-normalize-string (concat ! (if (plist-get info :multipage) ! (when (plist-get info :html-multipage-head-include-default-style) ! (org-element-normalize-string org-html-multipage-style-default)) ! (when (plist-get info :html-head-include-default-style) ! (org-element-normalize-string org-html-style-default))) (org-html-normalize-string-or-function (plist-get info :html-head) info) (org-html-normalize-string-or-function (plist-get info :html-head-extra) info) *************** *** 2206,2212 **** holding export options." (concat ;; Table of contents. ! (let ((depth (plist-get info :with-toc))) (when depth (org-html-toc depth info))) ;; Document contents. contents --- 2634,2644 ---- holding export options." (concat ;; Table of contents. ! (let* ((with-toc (plist-get info :with-toc)) ! (depth (if with-toc ! (if (numberp with-toc) ! with-toc ! (plist-get info :headline-levels))))) (when depth (org-html-toc depth info))) ;; Document contents. contents *************** *** 2477,2484 **** of contents as a string, or nil if it is empty." (let ((toc-entries (mapcar (lambda (headline) ! (cons (org-html--format-toc-headline headline info) ! (org-export-get-relative-level headline info))) (org-export-collect-headlines info depth scope)))) (when toc-entries (let* ((toc-id-counter (plist-get info :org-html--toc-counter)) --- 2909,2918 ---- of contents as a string, or nil if it is empty." (let ((toc-entries (mapcar (lambda (headline) ! (cl-list* ! (org-html--format-toc-headline headline info) ! nil ;;; no hidden attribute ! (org-export-get-relative-level headline info))) (org-export-collect-headlines info depth scope)))) (when toc-entries (let* ((toc-id-counter (plist-get info :org-html--toc-counter)) *************** *** 2497,2503 **** (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level ! (org-html--translate "Table of Contents" info) top-level)) toc (format "\n" outer-tag)))))))) --- 2931,2940 ---- (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level ! (org-html--translate ! (or (plist-get info :html-toc-title) ! org-html-toc-title) ! info) top-level)) toc (format "\n" outer-tag)))))))) *************** *** 2505,2527 **** (defun org-html--toc-text (toc-entries) "Return innards of a table of contents, as a string. TOC-ENTRIES is an alist where key is an entry title, as a string, ! and value is its relative level, as an integer." ! (let* ((prev-level (1- (cdar toc-entries))) (start-level prev-level)) (concat (mapconcat (lambda (entry) (let ((headline (car entry)) ! (level (cdr entry))) (concat ! (let* ((cnt (- level prev-level)) ! (times (if (> cnt 0) (1- cnt) (- cnt)))) ! (setq prev-level level) ! (concat ! (org-html--make-string ! times (cond ((> cnt 0) "\n
    \n
  • ") ! ((< cnt 0) "
  • \n
\n"))) ! (if (> cnt 0) "\n
    \n
  • " "
  • \n
  • "))) headline))) toc-entries "") (org-html--make-string (- prev-level start-level) "
  • \n
\n")))) --- 2942,2974 ---- (defun org-html--toc-text (toc-entries) "Return innards of a table of contents, as a string. TOC-ENTRIES is an alist where key is an entry title, as a string, ! second element a flag whether the entry gets a ! class=\"toc-hidden\" attribute and the third element is its ! relative level, as an integer." ! (let* ((prev-level (1- (cddar toc-entries))) (start-level prev-level)) (concat (mapconcat (lambda (entry) (let ((headline (car entry)) ! (hidden (cadr entry)) ! (level (cddr entry))) (concat ! (format ! (let* ((cnt (- level prev-level)) ! (times (if (> cnt 0) (1- cnt) (- cnt)))) ! (setq prev-level level) ! (concat ! (org-html--make-string ! times (cond ((> cnt 0) (format "\n
    \n
  • " level)) ! ((< cnt 0) "
  • \n
\n"))) ! (if (> cnt 0) ! (concat "\n\n") ! "\n"))) ! (if hidden (format " class=\"toc-hidden toc-level-%d\"" level) ! (format " class=\"toc-level-%d\"" level))) headline))) toc-entries "") (org-html--make-string (- prev-level start-level) "\n\n")))) *************** *** 2572,2578 **** (org-html--translate "Listing %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) --- 3019,3025 ---- (org-html--translate "Listing %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--full-reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) *************** *** 2610,2616 **** (org-html--translate "Table %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) --- 3057,3063 ---- (org-html--translate "Table %d:" info)))) (mapconcat (lambda (entry) ! (let ((label (org-html--full-reference entry info t)) (title (org-trim (org-export-data (or (org-export-get-caption entry t) *************** *** 2759,2765 **** (let ((prev (org-export-get-previous-element footnote-reference info))) (when (org-element-type-p prev 'footnote-reference) (plist-get info :html-footnote-separator))) ! (let* ((n (org-export-get-footnote-number footnote-reference info)) (label (org-element-property :label footnote-reference)) ;; Do not assign number labels as they appear in Org mode - ;; the footnotes are re-numbered by --- 3206,3215 ---- (let ((prev (org-export-get-previous-element footnote-reference info))) (when (org-element-type-p prev 'footnote-reference) (plist-get info :html-footnote-separator))) ! (let* ((n (org-export-get-footnote-number ! footnote-reference info ! (if (plist-get info :multipage) ! (org-html-get-multipage-tl-headline footnote-reference info)))) (label (org-element-property :label footnote-reference)) ;; Do not assign number labels as they appear in Org mode - ;; the footnotes are re-numbered by *************** *** 2795,2801 **** 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)))) --- 3245,3253 ---- CONTENTS holds the contents of the headline. INFO is a plist holding contextual information." (unless (org-element-property :footnote-section-p headline) ! (let* ((numberedp (if (plist-get info :multipage) ! (plist-get info :section-numbers) ! (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)))) *************** *** 3023,3028 **** --- 3475,3481 ---- ((string= key "HTML") value) ((string= key "TOC") (let ((case-fold-search t)) + (setq global-key keyword) (cond ((string-match "\\" value) (let ((depth (and (string-match "\\<[0-9]+\\>" value) *************** *** 3033,3039 **** (org-export-resolve-link (org-strip-quotes (match-string 1 value)) info)) ((string-match-p "\\" value) keyword)))) ;local ! (org-html-toc depth info scope))) ((string= "listings" value) (org-html-list-of-listings info)) ((string= "tables" value) (org-html-list-of-tables info)))))))) --- 3486,3496 ---- (org-export-resolve-link (org-strip-quotes (match-string 1 value)) info)) ((string-match-p "\\" value) keyword)))) ;local ! (if (plist-get info :multipage) ! (progn ! (setq global-key keyword) ! (org-html-multipage-toc depth (cl-list* :full-toc t info) scope)) ! (org-html-toc depth info scope)))) ((string= "listings" value) (org-html-list-of-listings info)) ((string= "tables" value) (org-html-list-of-tables info)))))))) *************** *** 3187,3193 **** (defun org-html-image-link-filter (data _backend info) "Process image links that are inside descriptions. ! DATA is the parse tree. INFO is and info plist. See `org-export-insert-image-links' for more details." (org-export-insert-image-links data info org-html-inline-image-rules)) --- 3644,3650 ---- (defun org-html-image-link-filter (data _backend info) "Process image links that are inside descriptions. ! DATA is the parse tree. INFO is an info plist. See `org-export-insert-image-links' for more details." (org-export-insert-image-links data info org-html-inline-image-rules)) *************** *** 3367,3389 **** (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 "%s" href attributes desc))) ;; Fuzzy link points to a target or an element. (_ (if (and destination --- 3824,3860 ---- (org-element-property :raw-link link) info)))) ;; Link points to a headline. (`headline ! (let ((href ! (org-html--full-reference ! (if (plist-get info :multipage) ! (alist-get destination ! (plist-get info :stripped-hl-to-parse-tree-hl)) ! 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)) ! (let ((headline-number (org-export-get-headline-number ! destination info))) ! (if (> (length headline-number) 1) ! (format ! (org-html--translate (nth 1 org-html-numbered-link-format) info) ! (mapconcat #'number-to-string ! headline-number ".")) ! (format ! (org-html--translate (nth 0 org-html-numbered-link-format) info) ! (mapconcat #'number-to-string ! headline-number ".")))) ;; 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 "%s" href attributes desc))) ;; Fuzzy link points to a target or an element. (_ (if (and destination *************** *** 3394,3422 **** ;; 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 (org-element-type-p destination 'latex-environment) #'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 "%s" ref attributes desc))))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") --- 3865,3895 ---- ;; 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--full-reference destination info)) ! (let* ((ref (org-html--full-reference destination info)) (org-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)) ! (numbered-ref (cond (desc nil) ((org-html-standalone-image-p destination info) ! (format (org-html--translate (nth 2 org-html-numbered-link-format) 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 numbered-ref) "No description for this link") ! ((numberp numbered-ref) (number-to-string number)) ! ((stringp numbered-ref) numbered-ref) (t (mapconcat #'number-to-string number "."))))) ! (format "%s" ref attributes desc))))))) ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") *************** *** 3924,3930 **** "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." ! (let ((ref (org-html--reference target info))) (org-html--anchor ref nil nil info))) ;;;; Timestamp --- 4397,4403 ---- "Transcode a TARGET object from Org to HTML. CONTENTS is nil. INFO is a plist holding contextual information." ! (let ((ref (org-html--full-reference target info))) (org-html--anchor ref nil nil info))) ;;;; Timestamp *************** *** 3984,3990 **** (delay-mode-hooks (set-auto-mode t)) (when (plist-get info :html-indent) (indent-region (point-min) (point-max))) ! (buffer-substring-no-properties (point-min) (point-max)))) ;;; End-user functions --- 4457,4470 ---- (delay-mode-hooks (set-auto-mode t)) (when (plist-get info :html-indent) (indent-region (point-min) (point-max))) ! (if (plist-get info :multipage) ! (let ((output-file (get-text-property ! 0 :output-file ! (buffer-substring (point-min) (point-max))))) ! (put-text-property ! 0 1 :output-file output-file ! (buffer-substring-no-properties (point-min) (point-max)))) ! (buffer-substring-no-properties (point-min) (point-max))))) ;;; End-user functions *************** *** 4092,4097 **** --- 4572,5482 ---- "html")) plist pub-dir)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;; + ;;; Code specific to the multipage backend + ;;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (defun org-html-reverse-assoc-list (assoc-list) + (mapcar (lambda (entry) (cons (cdr entry) (car entry))) assoc-list)) + + (defun org-html-element-title (element) + (org-element-property :raw-value element)) + + (defun org-html-increment-string-idx (string) + (if (string-match "\\([0-9]+\\)$" string) + (replace-match (format "%s" (1+ (read (match-string 0 string)))) nil nil string) + (format "%s-1" string))) + + (defun org-html-unique-filename (string filenames) + "return a unique filename by appending - to the string with + starting from 1 and incrementing until the string is + unique in filenames." + (if (member string filenames) + (org-html-unique-filename + (org-html-increment-string-idx string) filenames) + string)) + + (defun org-html-replace-chars-with-dash (chars string) + (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "-" accum)) + chars + :initial-value string)) + + (defun org-html-remove-chars (chars string) + (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "" accum)) + chars + :initial-value string)) + + (defun org-html-string-to-filename (string) + (replace-regexp-in-string + "-+" "-" + (org-html-remove-chars + '("(" ")" "*" "," ";" "{" "}" "'" "\\" "?") + (org-html-replace-chars-with-dash + '(" " "_" ":" "/") + (replace-regexp-in-string + "\\\\ast{}" "*" + (downcase (string-trim string))))))) + + (defun org-html-string-prepend-section-numbering (string levels maxlevel) + "Prepend the chapter outline numbers given in levels to + string. Truncate levels to maxlevel or pad with zeroes if + required." + (cl-loop + for i from (1- maxlevel) downto 0 + with result = string + do (setq result (format "%02d_%s" (or (nth i levels) 0) result)) + finally (return result))) + + (defun org-html--get-multipage-page-url (element info) + "Return the url of the page containing ELEMENT." + (alist-get + (org-html-get-multipage-tl-headline element info) + (plist-get info :tl-url-lookup))) + + (defun org-html--full-reference (destination info &optional page-only) + "Return an appropriate reference for DESTINATION. Like + org-html--reference, but generating an extended cross-page + reference for multipage. + + DESTINATION is an element or a `target' type object. INFO is the + current export state, as a plist. + + When PAGE-ONLY is non-nil just return the page reference." + (if (plist-get info :multipage) + (concat (org-html--get-multipage-page-url destination info) + (if page-only "" + (format "#%s" (org-export-get-reference destination info)))) + (format "#%s" (org-export-get-reference destination info)))) + + (defun org-html-multipage-toc (depth info &optional scope) + "Build a table of contents for a page in multipage + export. `:tl-headline-number' and `:tl-headline' refer to the + current page and have to be supplied in INFO. + + DEPTH is an integer specifying the depth of the table. INFO is a + plist used as a communication channel. Optional argument SCOPE + is an element defining the scope of the table. Return the table + of contents as a string, or nil if it is empty." + (let* ((tl-headline-number (plist-get info :tl-headline-number)) + (tl-headline (unless (plist-get info :full-toc) (plist-get info :tl-headline))) + (curr-number-ref tl-headline-number) + (toc-entries + (cl-loop + for (entry . props) in (plist-get info :multipage-toc-lookup) + if (<= (length (plist-get props :toc-hl-number)) depth) + collect (let* ((tl-hl (plist-get props :tl-hl)) + (page-headline-number (plist-get props :page-hl-number))) + (if (eq tl-hl tl-headline) + (setf curr-number-ref page-headline-number)) + (cl-list* + (org-html--format-mp-toc-headline + (plist-get props :href) + (plist-get props :toc-body) + (equal (plist-get props :tl-hl) tl-headline) + (plist-get info :full-toc)) + (unless (plist-get info :full-toc) + (org-html--hidden-in-toc? page-headline-number + curr-number-ref)) + (plist-get props :relative-level)))))) + (when toc-entries + (let ((toc (concat "
" + (org-html--toc-text toc-entries) + "
\n"))) + (if scope toc + (let ((outer-tag (if (org-html--html5-fancy-p info) + "nav" + "div"))) + (concat (format "<%s id=\"table-of-contents\" role=\"doc-toc\">\n" outer-tag) + (let ((top-level (plist-get info :html-toplevel-hlevel))) + (format "%s\n" + top-level + (org-html--translate + (or (plist-get info :html-toc-title) + org-html-toc-title) + info) + top-level)) + toc + (format "\n" outer-tag)))))))) + + (defun org-html--get-toc-body (headline info) + "Return the body of the toc entry of HEADLINE. INFO is a plist + used as a communication channel." + (let* ((headline-number (org-html-get-multipage-headline-number 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))) + (text (org-export-data-with-backend + (org-export-get-alt-title headline info) + (org-export-toc-entry-backend 'html) + info)) + (tags (and (eq (plist-get info :with-tags) t) + (org-export-get-tags headline info)))) + ;; Body. + (concat + (and (not (org-export-low-level-p headline info)) + (plist-get info :section-numbers) + (concat + (mapconcat #'number-to-string headline-number ".") + "  ")) + (apply (plist-get info :html-format-headline-function) + todo todo-type priority text tags :section-number nil)))) + + (defun org-html--format-mp-toc-headline (href body active full-toc) + "Return a table of contents entry for multipage output." + (format "%s" + ;; Target + (format "href=\"%s\"%s" + href + (concat + "class=\"" + (if full-toc "inline-toc-entry" + "toc-entry") + (if active + " toc-active" "") + "\"")) + + ;; Body. + body)) + + (defun org-html-multipage-ensure-export-dir (dir) + "get the full pathname of dir and ensure it exists." + (when (symbolp dir) (setq dir (format "%s" dir))) + (unless (= (aref dir 0) 47) + (setq dir (concat (file-name-directory (buffer-file-name)) dir))) + (unless (file-directory-p dir) + (make-directory dir :parents)) + dir) + + (defun org-html-multipage-split-tree (info) + (let ((split-ref (plist-get info :html-multipage-split-level)) + (headline-numbering (plist-get info :headline-numbering))) + (cond + ((eq split-ref 'toc) + (let ((maxdepth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)))) + (plist-put info :export-depth maxdepth) + (org-html-page-headlines + (cl-remove-if (lambda (hl-num) (> (length hl-num) maxdepth)) + headline-numbering :key 'cdr) + info))) + ((numberp split-ref) + (plist-put info :export-depth split-ref) + (org-html-page-headlines + (cl-remove-if (lambda (hl-num) (> (length hl-num) split-ref)) + headline-numbering :key 'cdr) + info))))) + + (defun org-html-transcode-multipage (info &optional body-only) + "Central routine transcoding to multipage output called by + `org-html-transcode-org-data' called from `org-export-as'. + + The pages to be exported are in the :multipage-org-pages property + of info as a list of org-page pseudo elements. This function + transcodes the org-pages and returns a list of the transcoded + output strings with their filename as :output-file Text Property + to be further processed by the function calling `org-export-as'. + + INFO is the communication channel. + " + (let ((async (plist-get info :async)) + (post-process (plist-get info :post-process))) + (declare (indent 2)) + (setq global-output + (cl-loop + for org-page in (plist-get info :multipage-org-pages) + collect (let ((file (org-element-property :output-file org-page))) + (message "transcoding: %s" file) + (let ((output (org-html-transcode-org-page org-page info))) + (put-text-property 0 1 :output-file file output) + output)))))) + + (defun org-html-multipage-split (data _backend info) + "Filter routine to collect all properties relevant to multipage + output. It is called in the context of calling all + :filter-parse-tree alist functions in `org-export-annotate-info' + after the parse-tree is completed and its properties + collected. The function takes care of splitting the parse-tree + into the subtrees for each page, creating org-page pseudo + elements, adding them in a list in the :multipage-org-pages + property of info. In addition lookup alists for the stripped + pages, for the page-urls, the navigation elements, the toc, + etc. are added to info, which are needed by the html transcoders. + + DATA is the completed parse-tree of the document. + + INFO is the communication channel. + " + (if (plist-get info :multipage) + (let ((dir (plist-get info :verified-export-directory)) + (async (plist-get info :async)) + (post-process (plist-get info :post-process))) + (declare (indent 2)) + (plist-put info :headline-numbering + (org-export--collect-headline-numbering + (plist-get info :parse-tree) + (cl-list* :section-numbers t info))) + (if (not (file-writable-p dir)) (error "Output dir not writable") + (let* ((encoding (or org-export-coding-system buffer-file-coding-system)) + (headline-numbering (plist-get info :headline-numbering)) + ;; each entry in exported-headline-numbering will become a + ;; single page in multipage output. + (exported-headline-numbering + (let ((tmp (org-html-multipage-split-tree info))) + (plist-put info :exported-headline-numbering tmp) + tmp)) + (max-toc-depth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels))) + ;; section-trees is a list of all sections which get + ;; exported to a single page + (section-trees + (cl-loop + for section-entry in exported-headline-numbering + for keep-first-subhls = (plist-get info :keep-first-subhls) then (cdr keep-first-subhls) + collect + (let* ((section-number (cdr section-entry))) + (if (< (length section-number) max-toc-depth) + (org-html-element-remove-subheadlines + (car section-entry) + (car keep-first-subhls) + max-toc-depth) + (org-html-element-copy-element (car section-entry)))))) + ;; stripped-section-headline-numbering is the equivalent of + ;; headline-numbering but replacing the car of its elements + ;; with the stripped version of the headlines. + (stripped-section-headline-numbering + (cl-mapcar 'cons + (cl-loop for section in section-trees + ;; collect all subheadlines to match + ;; headline-numbering: + append (org-element-map section 'headline + 'identity)) + (mapcar 'cdr headline-numbering))) + ;; lookup from all toc headline-numbers to the tl-headline. + ) + ;; add stripped-section-headline-numbering to + ;; :headline-numbering, to make their headline-numbering + ;; accessible when generating the body of the individual + ;; pages. + (plist-put info :headline-numbering + (append + headline-numbering + stripped-section-headline-numbering)) + (plist-put info :section-trees section-trees) + (plist-put info :stripped-section-headline-numbering + stripped-section-headline-numbering) + ;; tl-url-lookup associates the stripped section headlines + ;; with the names of the joined pages to export. + (plist-put info :tl-url-lookup (org-html--generate-tl-url-lookup info)) + ;; lookup for the navigation elements of each page. + (plist-put info :section-nav-lookup + (org-html--make-section-nav-lookup info)) + (let ((section-filenames + (mapcar + (lambda (hl) (alist-get hl (plist-get info :tl-url-lookup))) + section-trees))) + (plist-put info :section-filenames section-filenames) + ;; bidirectional lookup tables to map between the + ;; stripped-section headlines and their global + ;; parse-tree equvialent. + (plist-put + info :stripped-hl-to-parse-tree-hl + (append + (cl-mapcar 'cons + (mapcar 'car stripped-section-headline-numbering) + (mapcar 'car headline-numbering)) + (cl-mapcar 'cons + (mapcar 'car headline-numbering) + (mapcar 'car stripped-section-headline-numbering)))) + ;; collect the toc information to avoid repeated + ;; recalculation in the toc transcoder for the + ;; individual pages. + (plist-put info :multipage-toc-lookup + (org-html--make-multipage-toc-lookup info)) + ;; The url for the "top" link on each page. + (plist-put info :html-top-url + (alist-get + (car (plist-get info :section-trees)) + (plist-get info :tl-url-lookup))) + ;; The title for the "top" link on each page. + (plist-put info :html-top-title + (org-html-element-title + (car (plist-get info :section-trees)))) + ;; collect all org-pages to be exported. + (plist-put info :multipage-org-pages + (cl-loop + for file in section-filenames + for tl-headline in section-trees + collect + (list 'org-page + (list :output-file (format "%s/%s" dir file) + :tl-headline tl-headline + :tl-headline-number + (alist-get + tl-headline + stripped-section-headline-numbering)) + nil)))))))) + data) + + (defun org-html--generate-tl-url-lookup (info) + "Return an assoc list for all headlines appearing in the toc + and the url names of the page they're on." + (let ((extension (plist-get info :html-extension)) + (stripped-section-headline-numbering + (plist-get info :stripped-section-headline-numbering)) + filenames) + (mapcar + (lambda (entry) + (let* ((tl-elem (org-html-element-get-top-level entry)) + (title (org-html-element-title tl-elem))) + (cons + entry + (format "%s.%s" + (car (push + (org-html-unique-filename + (if (plist-get info :html-multipage-numbered-filenames) + (org-html-string-prepend-section-numbering + (org-html-string-to-filename title) + (cdr (assoc + tl-elem + stripped-section-headline-numbering)) + org-export-headline-levels) + (org-html-string-to-filename title)) + filenames) + filenames)) + extension)))) + (plist-get info :section-trees)))) + + (defun org-html--make-section-nav-lookup (info) + "Return an assoc-list for the headlines of all + exported pages with a plist containing titles and urls for the + section and its navigation." + (let* ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering)) + ;;; first collect navigation-info once for each page only + (nav (mapcar (lambda (hl) + (let* ((hl-number (alist-get hl stripped-section-headline-numbering)) + (up (car (rassoc (butlast hl-number) stripped-section-headline-numbering)))) + (list hl + (org-html-element-title hl) + (org-html--full-reference hl info t) + (org-html-element-title up) + (and up (org-html--full-reference up info t))))) + (plist-get info :section-trees)))) + ;;; collect the info for prev, curr, next and up navigation for + ;;; each page by cdr-ing over nav. + (cl-labels ((inner (prev-entry curr-entry) + (let ((prev (car prev-entry)) + (curr (car curr-entry)) + (next (cadr curr-entry))) + (if curr + (cons (list (car curr) + :prev-title (nth 1 prev) + :curr-title (nth 1 curr) + :next-title (nth 1 next) + :up-title (nth 3 curr) + :prev-url (nth 2 prev) + :curr-url (nth 2 curr) + :next-url (nth 2 next) + :up-url (nth 4 curr)) + (inner (cdr prev-entry) (cdr curr-entry))))))) + (inner (cons nil nav) nav)))) + + (defun org-html--make-multipage-toc-lookup (info) + "Return an assoc-list containing info for the headlines of all toc entries." + (mapcar + (lambda (hl) + (let* ((tl-hl (org-html-element-get-top-level hl))) + (list hl + :href (org-html--full-reference hl info (plist-get info :html-multipage-toc-to-top)) + :tl-hl tl-hl + :relative-level (org-export-get-relative-level hl info) + :toc-body (org-html--get-toc-body hl info) + :toc-hl-number (alist-get hl (plist-get info :headline-numbering)) + :page-hl-number (org-html-get-multipage-headline-number hl info)))) + (org-html-collect-local-headlines info nil))) + + (defun org-html-get-multipage-tl-headline (element info) + "return the headline of the page containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (let* ((elem element) + (parent (org-element-property :parent elem))) + (while parent + (setf elem parent) + (setf parent (org-element-property :parent elem))) + elem)) + + (defun org-html-get-multipage-headline-numbering (element info) + "return the headline of the section containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (let* ((elem element) + (parent (org-element-property :parent elem)) + (hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering)))) + (while (not hl-numbering) + (setf elem parent) + (setf parent (org-element-property :parent elem)) + (setf hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering)))) + hl-numbering)) + + (defun org-html-get-multipage-headline-number (element info) + "return the headline-number of the section containing + element. This requires that :headline-numbering has already been + added to info (done in org-export--collect-tree-properties)." + (cdr (org-html-get-multipage-headline-numbering element info))) + + (defun org-html-element-get-top-level (element) + "Return the top-level element of ELEMENT by traversing the parse + tree upwards until the parent of element is nil." + (let ((elem element) + (parent (org-element-property :parent element))) + (while parent + (setq elem parent) + (setq parent (org-element-property :parent elem))) + elem)) + + (defun org-html-element-copy-element (org-node &optional keep-parent) + "copy ORG-NODE to a new org-node with elements not copied, + but referenced." + (let* (headline + (props (copy-sequence (nth 1 org-node))) + (new (list (car org-node) props))) + (unless keep-parent (setf (org-element-property :parent new) nil)) + (apply 'org-element-adopt-elements new (org-element-contents org-node)))) + + (defun org-html-element-remove-subheadlines (org-node &optional + keep-first-subheadlines max-toc-depth keep-parent) + "remove all elements starting with and including the first headline + in the children of ORG-NODE if JOIN_EMPTY_BODIES is nil. Returns a + new ast with all elements starting at START-CHILD-IDX copied into + it with the :parent property optionally removed in the top node." + (let* ((num-subheadlines 0) + contents-end + headline + (props (copy-sequence (nth 1 org-node))) + (new (list (car org-node) props)) + (new-children (cl-loop + for x in (org-element-contents org-node) + with exit = nil + do (if (and + (consp x) + (eq (org-element-type x) 'headline)) + (if (and (car keep-first-subheadlines) (zerop num-subheadlines)) + (progn + (setf num-subheadlines (1+ num-subheadlines)) + (if (< (org-element-property :level x) max-toc-depth) + (setq x (org-html-element-remove-subheadlines + x (cdr keep-first-subheadlines) max-toc-depth)))) + (progn + (setq contents-end (org-element-property :begin x)) + (setq exit t)))) + until exit + collect x))) + (unless keep-parent (setf (org-element-property :parent new) nil)) + (apply 'org-element-adopt-elements new new-children))) + + (defun org-html-find-headline (headline-number headline-numbering) + "return the headline in headline numbering for a given + headline-number." + (cond + ((null headline-numbering) nil) + ((equal headline-number (cdar headline-numbering)) + (caar headline-numbering)) + (t (org-html-find-headline headline-number (cdr headline-numbering))))) + + (defun org-html-element-body-text (element info) + "check if transcoding of the contents of element until the next + subheadline returns an empty string." + (let ((strings + (cl-loop + for elem in (org-element-contents element) + while (not (eq 'headline (org-element-type elem))) + collect (org-export-data elem info)))) + (string-trim + (apply 'concat + (with-temp-buffer + (mapcar 'insert strings) + (dom-strings (libxml-parse-html-region (point-min) (point-max)))))))) + + (defun org-html-element-body-text? (element info) + "check if transcoded element produces any text." + (not (eq "" (org-html-element-body-text element info)))) + + (defun org-html-page-headlines (headlines info) + "collect the headlines of all pages to export. In case of + html-multipage-join-empty-bodies don't collect the headlines to + be joined and keep track by collecting them for each page + headline in :keep-first-subhls. + `org-html-element-remove-subheadlines'" + (if (plist-get info :html-multipage-join-empty-bodies) + (cl-loop for (prev curr-headline) on (cons nil headlines) + with collect-hl = nil + with tmp = nil + with keep-shl = nil + while curr-headline + do (progn + (setf + collect-hl + (or ;; collect curr-headline either + (not prev) ;; when it is the first headline + (<= (length (cdr curr-headline)) + (length (cdr prev))) ;; when it is not a subheadline of prev. + ;; or when the previous headline contains body text + (org-html-element-body-text? (car prev) info))) + (if collect-hl + (progn (push (reverse tmp) keep-shl) + (setf tmp nil)) + (push t tmp))) + if collect-hl collect curr-headline + finally (progn (push tmp keep-shl) + (plist-put info :keep-first-subhls (cdr (reverse keep-shl))))) + headlines)) + + (defun org-html-transcode-org-page (page info) + "transcode the headline tree in the contents of the org-page + pseudo element PAGE into a string according to the backend and + return the string. + + INFO is used as communication channel." + (let* ((body-only (org-element-property :body-only page)) + (headline (org-element-property :tl-headline page)) + (info (cl-list* + :tl-headline headline + :tl-headline-number (org-element-property :tl-headline-number page) + info)) + (body (org-element-normalize-string + (or (org-export-data headline info) + ""))) + (inner-template (if (plist-get info :multipage) + (alist-get 'multipage-inner-template + (plist-get info :translate-alist)) + (alist-get 'inner-template + (plist-get info :translate-alist)))) + (full-body (org-export-filter-apply-functions + (plist-get info :filter-body) + (if (not (functionp inner-template)) body + (funcall inner-template body info)) + info)) + (template (if (plist-get info :multipage) + (cdr (assq 'multipage-template + (plist-get info :translate-alist))) + (cdr (assq 'template + (plist-get info :translate-alist))))) + (output + (if (or (not (functionp template)) body-only) full-body + (funcall template full-body info)))) + ;; Call citation export finalizer. + (setq output (org-cite-finalize-export output info)) + ;; Remove all text properties since they cannot be + ;; retrieved from an external process. Finally call + ;; final-output filter and return result. + (org-no-properties + (org-export-filter-apply-functions + (plist-get info :filter-final-output) + output info)))) + + (defun org-html-export-to-multipage + (&optional async subtreep visible-only body-only ext-plist post-process) + "Export current buffer to multipage HTML files. + + If narrowing is active in the current buffer, only export its + narrowed part. + + If a region is active, export that region. + + A non-nil optional argument ASYNC means the process should happen + asynchronously. The resulting files should be accessible through + the `org-export-stack' interface. + + When optional argument SUBTREEP is non-nil, export the sub-tree + at point, extracting information from the headline properties + first. + + When optional argument VISIBLE-ONLY is non-nil, don't export + contents of hidden elements. + + When optional argument BODY-ONLY is non-nil, only write code + between \"\" and \"\" tags. + + EXT-PLIST, when provided, is a property list with external + parameters overriding Org default settings, but still inferior to + file-local settings. + + Return output directory's name." + (interactive) + (let* ((extension (concat + (when (> (length org-html-extension) 0) ".") + (or (plist-get ext-plist :html-extension) + org-html-extension + "html"))) + (backend 'html) + (encoding (or org-export-coding-system buffer-file-coding-system)) + (org-export-coding-system org-html-coding-system) + (environment (org-export-get-environment 'html nil nil)) + (dir (org-html-multipage-ensure-export-dir + (plist-get environment :html-multipage-export-directory)))) + (if (not (file-writable-p dir)) (error "Output dir not writable") + (progn + (message "collecting multipage output...") + (let ((output + (org-export-as backend subtreep visible-only body-only + (cl-list* + :async async + :multipage t + :verified-export-directory dir + ext-plist)))) + (when (plist-get environment :html-multipage-clear-export-directory) + (message "clearing export-directory.") + (dolist + (file (directory-files dir nil ".html$")) + (delete-file (format "%s/%s" dir file)))) + (dolist (out output) + (if async + (org-export-async-start + (lambda (file) + (org-export-add-to-stack (expand-file-name file) backend)) + `(let ((file (get-text-property 0 :ouput-file out))) + (setq file (org-export--write-output output ',encoding)) + (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f)))) + (if (listp file) (mapcar post file) (funcall post file))))) + (let (file) + (setq file (org-export--write-output out encoding)) + (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) + (org-kill-new output)) + ;; Get proper return value. + (let ((post (lambda (f) + (or (and (functionp post-process) + (funcall post-process f)) + f)))) + (if (listp file) (mapcar post file) (funcall post file)))))) + (if (member system-type '(darwin gnu/linux gnu)) + (shell-command (format "ln -s %s %s/index.html" (get-text-property 0 :output-file (car output)) dir))) + (message "done!\n") + (cl-case (plist-get environment :html-multipage-open) + ('browser (org-open-file (format "%s" (get-text-property 0 :output-file (car output))))) + ('buffer (find-file (format "%s" (get-text-property 0 :output-file (car output))))))))))) + + (defun org-html--hidden-in-toc? (headline-number tl-headline-number) + "Check if the entry of HEADLINE-NUMBER should be hidden in the + toc of the page containing TL-HEADLINE-NUMBER." + (and + (> (length headline-number) 1) + (let ((l1 (length headline-number)) + (l2 (length tl-headline-number))) + (cond + ((= l1 l2) (not (equal (butlast headline-number) + (butlast tl-headline-number)))) + ((> l1 l2) (not (equal tl-headline-number + (butlast headline-number)))) + (t (not (equal (butlast headline-number) + (butlast (butlast tl-headline-number))))))))) + + (defun org-html-collect-local-headlines (info scope) + "Collect all headlines of headline-numbering from their local + tl-headlines counterparts." + (let ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering)) + (headline-numbering (plist-get info :headline-numbering))) + (mapcar + (lambda (global-headline) + (car + (rassoc (cdr (assoc global-headline headline-numbering)) + stripped-section-headline-numbering))) + (org-export-collect-headlines + info + (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)) + scope)))) + + (defun org-html-nav-left (nav-lookup) + "Return nav string for multipage Navigation in page-main-body. + + INFO is a plist used as a communication channel. + " + (let* ((prev-url (plist-get nav-lookup :prev-url)) + (prev-title (plist-get nav-lookup :prev-title))) + (if prev-url + (format "" + prev-url) + (format "" + "")))) + + (defun org-html-nav-right (nav-lookup) + "Return nav string for multipage Navigation in page-main-body. + + INFO is a plist used as a communication channel. + " + (let* ((next-url (plist-get nav-lookup :next-url)) + (next-title (plist-get nav-lookup :next-title))) + (if next-url + (format "" + next-url) + (format "" + "")))) + + (defun org-html-multipage-nav (info) + "Return the string for the multipage navigation anchors. + + INFO is a plist used as a communication channel. + " + (let ((section-nav-lookup + (alist-get + (plist-get info :tl-headline) + (plist-get info :section-nav-lookup))) + (nav-format (plist-get info :html-multipage-nav-format))) + (format (car nav-format) + (concat + (when (plist-get section-nav-lookup :next-url) + (format (cadr nav-format) + (plist-get section-nav-lookup :next-url) + (plist-get section-nav-lookup :next-title))) + (when (plist-get section-nav-lookup :prev-url) + (format (caddr nav-format) + (plist-get section-nav-lookup :prev-url) + (plist-get section-nav-lookup :prev-title))) + (when (plist-get section-nav-lookup :up-url) + (format (cadddr nav-format) + (plist-get section-nav-lookup :up-url) + (plist-get section-nav-lookup :up-title))) + (when (plist-get info :html-top-url) + (format (nth 4 nav-format) + (plist-get info :html-top-url) + (plist-get info :html-top-title))))))) + + (defun org-html-multipage-template (contents info) + "Return complete document string after HTML conversion. + CONTENTS is the transcoded contents string. INFO is a plist + holding export options." + (concat + (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info)) + (let* ((xml-declaration (plist-get info :html-xml-declaration)) + (decl (or (and (stringp xml-declaration) xml-declaration) + (cdr (assoc (plist-get info :html-extension) + xml-declaration)) + (cdr (assoc "html" xml-declaration)) + ""))) + (when (not (or (not decl) (string= "" decl))) + (format "%s\n" + (format decl + (or (and org-html-coding-system + ;; FIXME: Use Emacs 22 style here, see `coding-system-get'. + (coding-system-get org-html-coding-system 'mime-charset)) + "iso-8859-1")))))) + (org-html-doctype info) + "\n" + (concat "\n") + "\n" + (org-html--build-meta-info info) + (org-html--build-head info) + (org-html--build-mathjax-config info) + "\n" + "\n" + (when (eq org-html-multipage-preamble-position 'top) + (org-html--build-pre/postamble 'preamble info)) + (org-html-multipage-nav info) + ;; Preamble. + (unless (eq org-html-multipage-preamble-position 'top) + (org-html--build-pre/postamble 'preamble info)) + ;; Document contents. + (let ((div (assq 'content (plist-get info :html-divs)))) + (format "<%s id=\"%s\" class=\"%s\">\n" + (nth 1 div) + (nth 2 div) + (plist-get info :html-content-class))) + ;; Table of contents. + (let ((depth (if (numberp (plist-get info :with-toc)) + (plist-get info :with-toc) + (plist-get info :headline-levels)))) + (when depth (org-html-multipage-toc depth info))) + ;; Document title. + (when (plist-get info :with-title) + (let ((title (and (plist-get info :with-title) + (plist-get info :title))) + (subtitle (plist-get info :subtitle)) + (html5-fancy (org-html--html5-fancy-p info))) + (when title + (format + (if html5-fancy + "
\n

%s

\n%s
" + "

%s%s

\n") + (org-export-data title info) + (if subtitle + (format + (if html5-fancy + "

%s

\n" + (concat "\n" (org-html-close-tag "br" nil info) "\n" + "%s\n")) + (org-export-data subtitle info)) + ""))))) + contents + (format "\n" (nth 1 (assq 'content (plist-get info :html-divs)))) + ;; Possibly use the Klipse library live code blocks. + (when (plist-get info :html-klipsify-src) + (concat "")) + (when (eq org-html-multipage-postamble-position 'bottom) + (org-html--build-pre/postamble 'postamble info)) + ;; Closing document. + "\n")) + + (defun org-html-multipage-inner-template (contents info) + "Return body of document string after HTML conversion. + CONTENTS is the transcoded contents string. INFO is a plist + holding export options. + + DATA contains the subtree of the parse tree of the section to be + exported for multipage export. + " + ;; Navigation + (let* ((data (plist-get info :tl-headline)) + (section-nav-lookup + (alist-get + data + (plist-get info :section-nav-lookup)))) + (format "
%s\n
%s
%s
" + (org-html-nav-left section-nav-lookup) + (concat + ;; Document contents. + contents + ;; Footnotes section. + (or (org-html-footnote-section info) "") + ;; Postamble. + (unless (eq org-html-multipage-postamble-position 'bottom) + (org-html--build-pre/postamble 'postamble info))) + (org-html-nav-right section-nav-lookup)))) + + (defun org-html-transcode-org-data (data content info) + "Transcode the top org-data node of the org file to export. + + It is called by `org-export-as' after all necessary information + has been added to info and the final parse-tree has been + generated. Multipage information has already been collected by + calling `org-html-multipage-filter' in `org-export-annotate-info' + using the :multipage-split property. + + INFO is a plist used as a communication channel." + (message "transcoding data!") + (if (plist-get info :multipage) + ;;; for multipage output we don't need data and content as all + ;;; information is already collected in info. + (org-html-transcode-multipage info) + (org-export-transcode-org-data data content info))) (provide 'ox-html) *************** *** 4100,4102 **** --- 5485,5489 ---- ;; End: ;;; ox-html.el ends here + +