diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el
index 9475a9fa8..7fbd16bb0 100644
--- a/contrib/lisp/ox-groff.el
+++ b/contrib/lisp/ox-groff.el
@@ -56,6 +56,7 @@
(dynamic-block . org-groff-dynamic-block)
(entity . org-groff-entity)
(example-block . org-groff-example-block)
+ (export-block . org-groff-export-block)
(export-snippet . org-groff-export-snippet)
(fixed-width . org-groff-fixed-width)
(footnote-definition . org-groff-footnote-definition)
@@ -882,6 +883,14 @@ information."
(format ".DS L\n%s\n.DE"
(org-export-format-code-default example-block info))))
+;;; Export Block
+
+(defun org-groff-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to Groff.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "GROFF")
+ (org-remove-indentation (org-element-property :value export-block))))
+
;;; Export Snippet
(defun org-groff-export-snippet (export-snippet contents info)
@@ -1469,10 +1478,10 @@ holding contextual information."
"Transcode a SPECIAL-BLOCK element from Org to Groff.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- (let ((type (downcase (org-element-property :type special-block))))
- (org-groff--wrap-label special-block (format "%s\n" contents)))))
+ (let ((type (downcase (org-element-property :type special-block))))
+ (org-groff--wrap-label
+ special-block
+ (format "%s\n" contents))))
;;; Src Block
diff --git a/contrib/lisp/ox-koma-letter.el b/contrib/lisp/ox-koma-letter.el
index d3aa335fb..32dd1999b 100644
--- a/contrib/lisp/ox-koma-letter.el
+++ b/contrib/lisp/ox-koma-letter.el
@@ -518,6 +518,15 @@ are present return the preferred one as determined by
;;; Transcode Functions
+;;;; Export Block
+
+(defun org-koma-letter-export-block (export-block contents info)
+ "Transcode an EXPORT-BLOCK element into KOMA Scrlttr2 code.
+CONTENTS is nil. INFO is a plist used as a communication
+channel."
+ (when (member (org-element-property :type export-block) '("KOMA-LETTER" "LATEX"))
+ (org-remove-indentation (org-element-property :value export-block))))
+
;;;; Export Snippet
(defun org-koma-letter-export-snippet (export-snippet contents info)
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index a17979895..0bae014d3 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -13,43 +13,6 @@ Please send Org bug reports to emacs-orgmode@gnu.org.
*** No default title is provided when =TITLE= keyword is missing
Skipping =TITLE= keyword no longer provides the current file name, or
buffer name, as the title. Instead, simply ignore the title.
-*** Remove ~export-block~ element type
-For export back-end developers.
-
-So called "Export blocks" are now raw "Special blocks". As
-a consequence ~export-block~ type doesn't exist anymore in parser, and
-should not have a translator associated in an export back-end.
-
-In order to tell the difference between a special block and a former
-export block, a new predicate, ~org-export-raw-special-block-p~ is
-implemented.
-
-To put it simply, two steps may be needed to update a back-end
-defining export blocks.
-
-1. Remove any ~org-BACKEND-export-block~ function, associated filter
- and remove ~export-block~ entry from back-end definition. This
- step can be omitted if you want to preserve backward-compatibility
- with Org 8.2. In this case, the function and filter will be used
- in Org 8.2 but ignored in Org 8.3.
-
-2. If there is a translator for special blocks, e.g.,
- ~org-BACKEND-special-block~, first check if the current block is an
- export block using the predicate and, if that is true, simply
- insert raw value, obtained through block's ~:raw-value~
- property. E.g.,
-
- #+BEGIN_SRC emacs-lisp
- (defun org-latex-special-block (special-block contents info)
- (if (org-export-raw-special-block-p special-block info)
- (org-element-property :raw-value special-block)
- ;; Usual handling for special blocks goes here.
- ))
- #+END_SRC
-
- Note that If BACKEND is a derived back-end and doesn't implement
- its own special block translator already, there is nothing to
- change. The parent back-end will take care of such blocks.
*** Signature changes
The following functions require an additional argument. See their
docstring for more information.
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 4b3df91d1..f175fbc50 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -45,11 +45,11 @@
;; and `special-block'.
;;
;; Other element types are: `babel-call', `clock', `comment',
-;; `comment-block', `diary-sexp', `example-block', `fixed-width',
-;; `horizontal-rule', `keyword', `latex-environment', `node-property',
-;; `paragraph', `planning', `src-block', `table', `table-row' and
-;; `verse-block'. Among them, `paragraph' and `verse-block' types can
-;; contain Org objects and plain text.
+;; `comment-block', `diary-sexp', `example-block', `export-block',
+;; `fixed-width', `horizontal-rule', `keyword', `latex-environment',
+;; `node-property', `paragraph', `planning', `src-block', `table',
+;; `table-row' and `verse-block'. Among them, `paragraph' and
+;; `verse-block' types can contain Org objects and plain text.
;;
;; Objects are related to document's contents. Some of them are
;; recursive. Associated types are of the following: `bold', `code',
@@ -169,11 +169,11 @@ is not sufficient to know if point is at a paragraph ending. See
(defconst org-element-all-elements
'(babel-call center-block clock comment comment-block diary-sexp drawer
- dynamic-block example-block fixed-width footnote-definition
- headline horizontal-rule inlinetask item keyword
- latex-environment node-property paragraph plain-list
- planning property-drawer quote-block section special-block
- src-block table table-row verse-block)
+ dynamic-block example-block export-block fixed-width
+ footnote-definition headline horizontal-rule inlinetask item
+ keyword latex-environment node-property paragraph plain-list
+ planning property-drawer quote-block section
+ special-block src-block table table-row verse-block)
"Complete list of element types.")
(defconst org-element-greater-elements
@@ -194,7 +194,7 @@ is not sufficient to know if point is at a paragraph ending. See
superscript table-cell underline)
"List of recursive object types.")
-(defconst org-element-block-name-alist
+(defvar org-element-block-name-alist
'(("CENTER" . org-element-center-block-parser)
("COMMENT" . org-element-comment-block-parser)
("EXAMPLE" . org-element-example-block-parser)
@@ -1520,9 +1520,8 @@ keyword and CDR is a plist of affiliated keywords along with
their value.
Return a list whose CAR is `special-block' and CDR is a plist
-containing `:type', `:raw-value', `:begin', `:end',
-`:contents-begin', `:contents-end', `:post-blank' and
-`:post-affiliated' keywords.
+containing `:type', `:begin', `:end', `:contents-begin',
+`:contents-end', `:post-blank' and `:post-affiliated' keywords.
Assume point is at the beginning of the block."
(let* ((case-fold-search t)
@@ -1551,10 +1550,6 @@ Assume point is at the beginning of the block."
(list 'special-block
(nconc
(list :type type
- :raw-value
- (and contents-begin
- (buffer-substring-no-properties
- contents-begin contents-end))
:begin begin
:end end
:contents-begin contents-begin
@@ -1905,6 +1900,60 @@ CONTENTS is nil."
"#+END_EXAMPLE")))
+;;;; Export Block
+
+(defun org-element-export-block-parser (limit affiliated)
+ "Parse an export block.
+
+LIMIT bounds the search. AFFILIATED is a list of which CAR is
+the buffer position at the beginning of the first affiliated
+keyword and CDR is a plist of affiliated keywords along with
+their value.
+
+Return a list whose CAR is `export-block' and CDR is a plist
+containing `:begin', `:end', `:type', `:value', `:post-blank' and
+`:post-affiliated' keywords.
+
+Assume point is at export-block beginning."
+ (let* ((case-fold-search t)
+ (type (progn (looking-at "[ \t]*#\\+BEGIN_\\(\\S-+\\)")
+ (upcase (org-match-string-no-properties 1)))))
+ (if (not (save-excursion
+ (re-search-forward
+ (format "^[ \t]*#\\+END_%s[ \t]*$" type) limit t)))
+ ;; Incomplete block: parse it as a paragraph.
+ (org-element-paragraph-parser limit affiliated)
+ (let ((contents-end (match-beginning 0)))
+ (save-excursion
+ (let* ((begin (car affiliated))
+ (post-affiliated (point))
+ (contents-begin (progn (forward-line) (point)))
+ (pos-before-blank (progn (goto-char contents-end)
+ (forward-line)
+ (point)))
+ (end (progn (skip-chars-forward " \r\t\n" limit)
+ (if (eobp) (point) (line-beginning-position))))
+ (value (buffer-substring-no-properties contents-begin
+ contents-end)))
+ (list 'export-block
+ (nconc
+ (list :begin begin
+ :end end
+ :type type
+ :value value
+ :post-blank (count-lines pos-before-blank end)
+ :post-affiliated post-affiliated)
+ (cdr affiliated)))))))))
+
+(defun org-element-export-block-interpreter (export-block contents)
+ "Interpret EXPORT-BLOCK element as Org syntax.
+CONTENTS is nil."
+ (let ((type (org-element-property :type export-block)))
+ (concat (format "#+BEGIN_%s\n" type)
+ (org-element-property :value export-block)
+ (format "#+END_%s" type))))
+
+
;;;; Fixed-width
(defun org-element-fixed-width-parser (limit affiliated)
diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el
index 60ec4ac14..feef86077 100644
--- a/lisp/ox-ascii.el
+++ b/lisp/ox-ascii.el
@@ -55,6 +55,7 @@
(dynamic-block . org-ascii-dynamic-block)
(entity . org-ascii-entity)
(example-block . org-ascii-example-block)
+ (export-block . org-ascii-export-block)
(export-snippet . org-ascii-export-snippet)
(fixed-width . org-ascii-fixed-width)
(footnote-reference . org-ascii-footnote-reference)
@@ -1197,6 +1198,16 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(org-element-property :value export-snippet)))
+;;;; Export Block
+
+(defun org-ascii-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to ASCII.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "ASCII")
+ (org-ascii--justify-element
+ (org-element-property :value export-block) export-block info)))
+
+
;;;; Fixed Width
(defun org-ascii-fixed-width (fixed-width contents info)
@@ -1654,13 +1665,10 @@ contextual information."
"Transcode a SPECIAL-BLOCK element from Org to ASCII.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-ascii--justify-element
- (org-element-property :raw-value special-block) special-block info)
- ;; "JUSTIFYLEFT" and "JUSTFYRIGHT" have already been taken care of
- ;; at a lower level. There is no other special block type to
- ;; handle.
- contents))
+ ;; "JUSTIFYLEFT" and "JUSTFYRIGHT" have already been taken care of
+ ;; at a lower level. There is no other special block type to
+ ;; handle.
+ contents)
;;;; Src Block
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index 768e5bb1f..f2c001230 100644
--- a/lisp/ox-beamer.el
+++ b/lisp/ox-beamer.el
@@ -245,6 +245,7 @@ Return overlay specification, as a string, or nil."
(:beamer-outline-frame-options nil nil org-beamer-outline-frame-options)
(:beamer-outline-frame-title nil nil org-beamer-outline-frame-title))
:translate-alist '((bold . org-beamer-bold)
+ (export-block . org-beamer-export-block)
(export-snippet . org-beamer-export-snippet)
(headline . org-beamer-headline)
(item . org-beamer-item)
@@ -270,6 +271,16 @@ a communication channel."
contents))
+;;;; Export Block
+
+(defun org-beamer-export-block (export-block contents info)
+ "Transcode an EXPORT-BLOCK element into Beamer code.
+CONTENTS is nil. INFO is a plist used as a communication
+channel."
+ (when (member (org-element-property :type export-block) '("BEAMER" "LATEX"))
+ (org-remove-indentation (org-element-property :value export-block))))
+
+
;;;; Export Snippet
(defun org-beamer-export-snippet (export-snippet contents info)
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index 9e642055b..132c34f13 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -55,6 +55,7 @@
(dynamic-block . org-html-dynamic-block)
(entity . org-html-entity)
(example-block . org-html-example-block)
+ (export-block . org-html-export-block)
(export-snippet . org-html-export-snippet)
(fixed-width . org-html-fixed-width)
(footnote-definition . org-html-footnote-definition)
@@ -2271,6 +2272,14 @@ information."
(when (eq (org-export-snippet-backend export-snippet) 'html)
(org-element-property :value export-snippet)))
+;;;; Export Block
+
+(defun org-html-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to HTML.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "HTML")
+ (org-remove-indentation (org-element-property :value export-block))))
+
;;;; Fixed Width
(defun org-html-fixed-width (fixed-width contents info)
@@ -3090,25 +3099,25 @@ contextual information."
"Transcode a SPECIAL-BLOCK element from Org to HTML.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- (let* ((block-type (downcase (org-element-property :type special-block)))
- (contents (or contents ""))
- (html5-fancy (and (org-html-html5-p info)
- (plist-get info :html-html5-fancy)
- (member block-type org-html-html5-elements)))
- (attributes (org-export-read-attribute :attr_html special-block)))
- (unless html5-fancy
- (let ((class (plist-get attributes :class)))
- (setq attributes (plist-put attributes :class
- (if class (concat class " " block-type)
- block-type)))))
- (setq attributes (org-html--make-attribute-string attributes))
- (when (not (equal attributes ""))
- (setq attributes (concat " " attributes)))
- (if html5-fancy
- (format "<%s%s>\n%s%s>" block-type attributes contents block-type)
- (format "
\n%s\n
" attributes contents)))))
+ (let* ((block-type (downcase
+ (org-element-property :type special-block)))
+ (contents (or contents ""))
+ (html5-fancy (and (org-html-html5-p info)
+ (plist-get info :html-html5-fancy)
+ (member block-type org-html-html5-elements)))
+ (attributes (org-export-read-attribute :attr_html special-block)))
+ (unless html5-fancy
+ (let ((class (plist-get attributes :class)))
+ (setq attributes (plist-put attributes :class
+ (if class (concat class " " block-type)
+ block-type)))))
+ (setq attributes (org-html--make-attribute-string attributes))
+ (when (not (equal attributes ""))
+ (setq attributes (concat " " attributes)))
+ (if html5-fancy
+ (format "<%s%s>\n%s%s>" block-type attributes
+ contents block-type)
+ (format "\n%s\n
" attributes contents))))
;;;; Src Block
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 478d5d405..b3f8f2c12 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -49,6 +49,7 @@
(dynamic-block . org-latex-dynamic-block)
(entity . org-latex-entity)
(example-block . org-latex-example-block)
+ (export-block . org-latex-export-block)
(export-snippet . org-latex-export-snippet)
(fixed-width . org-latex-fixed-width)
(footnote-definition . org-latex-footnote-definition)
@@ -1355,6 +1356,15 @@ information."
(org-export-format-code-default example-block info)))))
+;;;; Export Block
+
+(defun org-latex-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to LaTeX.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (member (org-element-property :type export-block) '("LATEX" "TEX"))
+ (org-remove-indentation (org-element-property :value export-block))))
+
+
;;;; Export Snippet
(defun org-latex-export-snippet (export-snippet contents info)
@@ -2232,17 +2242,15 @@ holding contextual information."
"Transcode a SPECIAL-BLOCK element from Org to LaTeX.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- (let ((type (downcase (org-element-property :type special-block)))
- (opt (org-export-read-attribute :attr_latex special-block :options)))
- (concat (format "\\begin{%s}%s\n" type (or opt ""))
- ;; Insert any label or caption within the block
- ;; (otherwise, a reference pointing to that element will
- ;; count the section instead).
- (org-latex--caption/label-string special-block info)
- contents
- (format "\\end{%s}" type)))))
+ (let ((type (downcase (org-element-property :type special-block)))
+ (opt (org-export-read-attribute :attr_latex special-block :options)))
+ (concat (format "\\begin{%s}%s\n" type (or opt ""))
+ ;; Insert any label or caption within the block
+ ;; (otherwise, a reference pointing to that element will
+ ;; count the section instead).
+ (org-latex--caption/label-string special-block info)
+ contents
+ (format "\\end{%s}" type))))
;;;; Src Block
diff --git a/lisp/ox-man.el b/lisp/ox-man.el
index 4b27ab6c3..c8c999857 100644
--- a/lisp/ox-man.el
+++ b/lisp/ox-man.el
@@ -61,6 +61,7 @@
(dynamic-block . org-man-dynamic-block)
(entity . org-man-entity)
(example-block . org-man-example-block)
+ (export-block . org-man-export-block)
(export-snippet . org-man-export-snippet)
(fixed-width . org-man-fixed-width)
(footnote-definition . org-man-footnote-definition)
@@ -431,6 +432,15 @@ information."
(org-export-format-code-default example-block info))))
+;;; Export Block
+
+(defun org-man-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to Man.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "MAN")
+ (org-remove-indentation (org-element-property :value export-block))))
+
+
;;; Export Snippet
(defun org-man-export-snippet (export-snippet contents info)
@@ -765,10 +775,10 @@ holding contextual information."
"Transcode a SPECIAL-BLOCK element from Org to Man.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- (let ((type (downcase (org-element-property :type special-block))))
- (org-man--wrap-label special-block (format "%s\n" contents)))))
+ (let ((type (downcase (org-element-property :type special-block))))
+ (org-man--wrap-label
+ special-block
+ (format "%s\n" contents))))
;;; Src Block
diff --git a/lisp/ox-md.el b/lisp/ox-md.el
index 1a891dc01..695fb6106 100644
--- a/lisp/ox-md.el
+++ b/lisp/ox-md.el
@@ -71,6 +71,7 @@ This variable can be set to either `atx' or `setext'."
(comment . (lambda (&rest args) ""))
(comment-block . (lambda (&rest args) ""))
(example-block . org-md-example-block)
+ (export-block . org-md-export-block)
(fixed-width . org-md-example-block)
(footnote-definition . ignore)
(footnote-reference . ignore)
@@ -157,7 +158,7 @@ channel."
value)))
-;;;; Example Block and Src Block
+;;;; Example Block, Src Block and export Block
(defun org-md-example-block (example-block contents info)
"Transcode EXAMPLE-BLOCK element into Markdown format.
@@ -168,6 +169,14 @@ channel."
(org-remove-indentation
(org-export-format-code-default example-block info))))
+(defun org-md-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to Markdown.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (if (member (org-element-property :type export-block) '("MARKDOWN" "MD"))
+ (org-remove-indentation (org-element-property :value export-block))
+ ;; Also include HTML export blocks.
+ (org-export-with-backend 'html export-block contents info)))
+
;;;; Headline
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 26ed8725d..205712ace 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -43,6 +43,7 @@
(dynamic-block . org-odt-dynamic-block)
(entity . org-odt-entity)
(example-block . org-odt-example-block)
+ (export-block . org-odt-export-block)
(export-snippet . org-odt-export-snippet)
(fixed-width . org-odt-fixed-width)
(footnote-definition . org-odt-footnote-definition)
@@ -1676,6 +1677,15 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(org-element-property :value export-snippet)))
+;;;; Export Block
+
+(defun org-odt-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to ODT.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "ODT")
+ (org-remove-indentation (org-element-property :value export-block))))
+
+
;;;; Fixed Width
(defun org-odt-fixed-width (fixed-width contents info)
@@ -3049,40 +3059,37 @@ contextual information."
"Transcode a SPECIAL-BLOCK element from Org to ODT.
CONTENTS holds the contents of the block. INFO is a plist
holding contextual information."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- (let ((type (downcase (org-element-property :type special-block)))
- (attributes (org-export-read-attribute :attr_odt special-block)))
- (cond
- ;; Annotation.
- ((string= type "annotation")
- (let* ((author (or (plist-get attributes :author)
- (let ((author (plist-get info :author)))
- (and author (org-export-data author info)))))
- (date (or (plist-get attributes :date)
- ;; FIXME: Is `car' right thing to do below?
- (car (plist-get info :date)))))
- (format "\n%s"
- (format "\n%s\n"
- (concat
- (and author
- (format "%s" author))
- (and date
- (format "%s"
- (org-odt--format-timestamp
- date nil 'iso-date)))
- contents)))))
- ;; Textbox.
- ((string= type "textbox")
- (let ((width (plist-get attributes :width))
- (height (plist-get attributes :height))
- (style (plist-get attributes :style))
- (extra (plist-get attributes :extra))
- (anchor (plist-get attributes :anchor)))
- (format "\n%s"
- "Text_20_body" (org-odt--textbox contents width height
+ (let ((type (downcase (org-element-property :type special-block)))
+ (attributes (org-export-read-attribute :attr_odt special-block)))
+ (cond
+ ;; Annotation.
+ ((string= type "annotation")
+ (let* ((author (or (plist-get attributes :author)
+ (let ((author (plist-get info :author)))
+ (and author (org-export-data author info)))))
+ (date (or (plist-get attributes :date)
+ ;; FIXME: Is `car' right thing to do below?
+ (car (plist-get info :date)))))
+ (format "\n%s"
+ (format "\n%s\n"
+ (concat
+ (and author
+ (format "%s" author))
+ (and date
+ (format "%s"
+ (org-odt--format-timestamp date nil 'iso-date)))
+ contents)))))
+ ;; Textbox.
+ ((string= type "textbox")
+ (let ((width (plist-get attributes :width))
+ (height (plist-get attributes :height))
+ (style (plist-get attributes :style))
+ (extra (plist-get attributes :extra))
+ (anchor (plist-get attributes :anchor)))
+ (format "\n%s"
+ "Text_20_body" (org-odt--textbox contents width height
style extra anchor))))
- (t contents)))))
+ (t contents))))
;;;; Src Block
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 5927b3a04..fa0298816 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -45,6 +45,7 @@
(dynamic-block . org-texinfo-dynamic-block)
(entity . org-texinfo-entity)
(example-block . org-texinfo-example-block)
+ (export-block . org-texinfo-export-block)
(export-snippet . org-texinfo-export-snippet)
(fixed-width . org-texinfo-fixed-width)
(footnote-definition . org-texinfo-footnote-definition)
@@ -694,7 +695,15 @@ information."
(format "@verbatim\n%s@end verbatim"
(org-export-format-code-default example-block info)))
-;;;; Export Snippet
+;;; Export Block
+
+(defun org-texinfo-export-block (export-block contents info)
+ "Transcode a EXPORT-BLOCK element from Org to Texinfo.
+CONTENTS is nil. INFO is a plist holding contextual information."
+ (when (string= (org-element-property :type export-block) "TEXINFO")
+ (org-remove-indentation (org-element-property :value export-block))))
+
+;;; Export Snippet
(defun org-texinfo-export-snippet (export-snippet contents info)
"Transcode a EXPORT-SNIPPET object from Org to Texinfo.
@@ -1226,9 +1235,7 @@ holding contextual information."
"Transcode a SPECIAL-BLOCK element from Org to Texinfo.
CONTENTS holds the contents of the block. INFO is a plist used
as a communication channel."
- (if (org-export-raw-special-block-p special-block info)
- (org-remove-indentation (org-element-property :raw-value special-block))
- contents))
+ contents)
;;;; Src Block
diff --git a/lisp/ox.el b/lisp/ox.el
index 235b0abac..f01f951f5 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -189,6 +189,7 @@ way they are handled must be hard-coded into
(:filter-dynamic-block . org-export-filter-dynamic-block-functions)
(:filter-entity . org-export-filter-entity-functions)
(:filter-example-block . org-export-filter-example-block-functions)
+ (:filter-export-block . org-export-filter-export-block-functions)
(:filter-export-snippet . org-export-filter-export-snippet-functions)
(:filter-final-output . org-export-filter-final-output-functions)
(:filter-fixed-width . org-export-filter-fixed-width-functions)
@@ -935,6 +936,10 @@ BACKEND is a structure with `org-export-backend' type."
(let ((parent (org-export-backend-parent backend)))
(when (and parent (not (org-export-get-backend parent)))
(error "Cannot use unknown \"%s\" back-end as a parent" parent)))
+ ;; Register dedicated export blocks in the parser.
+ (dolist (name (org-export-backend-blocks backend))
+ (add-to-list 'org-element-block-name-alist
+ (cons name 'org-element-export-block-parser)))
;; If a back-end with the same name as BACKEND is already
;; registered, replace it with BACKEND. Otherwise, simply add
;; BACKEND to the list of registered back-ends.
@@ -1066,7 +1071,7 @@ keywords are understood:
String, or list of strings, representing block names that
will not be parsed. This is used to specify blocks that will
contain raw code specific to the back-end. These blocks
- still have to be handled by the `special-block' type
+ still have to be handled by the relative `export-block' type
translator.
:filters-alist
@@ -1171,7 +1176,7 @@ keywords are understood:
String, or list of strings, representing block names that
will not be parsed. This is used to specify blocks that will
contain raw code specific to the back-end. These blocks
- still have to be handled by the `special-block' type
+ still have to be handled by the relative `export-block' type
translator.
:filters-alist
@@ -2596,6 +2601,12 @@ Each filter is called with three arguments: the transcoded data,
as a string, the back-end, as a symbol, and the communication
channel, as a plist. It must return a string or nil.")
+(defvar org-export-filter-export-block-functions nil
+ "List of functions applied to a transcoded export-block.
+Each filter is called with three arguments: the transcoded data,
+as a string, the back-end, as a symbol, and the communication
+channel, as a plist. It must return a string or nil.")
+
(defvar org-export-filter-fixed-width-functions nil
"List of functions applied to a transcoded fixed-width.
Each filter is called with three arguments: the transcoded data,
@@ -4231,29 +4242,8 @@ objects of the same type."
((funcall predicate el info) (incf counter) nil)))
info 'first-match)))))
-;;;; For Special Blocks
-;;
-;; `org-export-raw-special-block-p' check if current special block is
-;; an "export block", i.e., a block whose contents should be inserted
-;; as-is in the output. This should generally be the first check to
-;; do when handling special blocks in the export back-end.
-(defun org-export-raw-special-block-p (element info &optional no-inheritance)
- "Non-nil if ELEMENT is an export block relatively to current back-end.
-An export block is a special block whose contents should be
-included as-is in the final output. Such blocks are defined
-through :export-block property in `org-export-define-backend',
-which see."
- (and (eq (org-element-type element) 'special-block)
- (let ((type (org-element-property :type element))
- (b (plist-get info :back-end)))
- (if no-inheritance (member type (org-export-backend-blocks b))
- (while (and b (not (member type (org-export-backend-blocks b))))
- (setq b (org-export-get-backend (org-export-backend-parent b))))
- b))))
-
-
-;;;; For Src Blocks
+;;;; For Src-Blocks
;;
;; `org-export-get-loc' counts number of code lines accumulated in
;; src-block or example-block elements with a "+n" switch until
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 9b1ca7711..f463b051c 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -777,6 +777,39 @@ Some other text
(org-element-property :label-fmt (org-element-at-point)))))))
+;;;; Export Block
+
+(ert-deftest test-org-element/export-block-parser ()
+ "Test `export-block' parser."
+ ;; Standard test.
+ (should
+ (org-test-with-temp-text "#+BEGIN_LATEX\nText\n#+END_LATEX"
+ (org-element-map
+ (let ((org-element-block-name-alist
+ '(("LATEX" . org-element-export-block-parser))))
+ (org-element-parse-buffer))
+ 'export-block 'identity)))
+ ;; Ignore case.
+ (should
+ (let ((org-element-block-name-alist
+ '(("LATEX" . org-element-export-block-parser))))
+ (org-test-with-temp-text "#+begin_latex\nText\n#+end_latex"
+ (org-element-map (org-element-parse-buffer) 'export-block 'identity))))
+ ;; Ignore incomplete block.
+ (should-not
+ (let ((org-element-block-name-alist
+ '(("LATEX" . org-element-export-block-parser))))
+ (org-test-with-temp-text "#+BEGIN_LATEX"
+ (org-element-map (org-element-parse-buffer) 'export-block
+ 'identity nil t))))
+ ;; Handle non-empty blank line at the end of buffer.
+ (should
+ (let ((org-element-block-name-alist
+ '(("LATEX" . org-element-export-block-parser))))
+ (org-test-with-temp-text "#+BEGIN_LATEX\nC\n#+END_LATEX\n "
+ (= (org-element-property :end (org-element-at-point)) (point-max))))))
+
+
;;;; Export Snippet
(ert-deftest test-org-element/export-snippet-parser ()
@@ -2443,6 +2476,12 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"))))
"#+BEGIN_EXAMPLE\nTest\n#+END_EXAMPLE\n"
(org-element-interpret-data '(example-block (:value "Test"))))))
+(ert-deftest test-org-element/export-block-interpreter ()
+ "Test export block interpreter."
+ (should (equal (org-test-parse-and-interpret
+ "#+BEGIN_HTML\nTest\n#+END_HTML")
+ "#+BEGIN_HTML\nTest\n#+END_HTML\n")))
+
(ert-deftest test-org-element/fixed-width-interpreter ()
"Test fixed width interpreter."
;; Standard test.
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 1e92afe5c..4af35101e 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -1126,7 +1126,15 @@ Footnotes[fn:1], [fn:test] and [fn:inline:anonymous footnote].
(org-export-define-backend 'test
'((headline . my-headline-test))
:menu-entry '(?k "Test Export" test))
- (org-export-backend-menu (org-export-get-backend 'test))))))
+ (org-export-backend-menu (org-export-get-backend 'test)))))
+ ;; Export Blocks.
+ (should
+ (equal '(("TEST" . org-element-export-block-parser))
+ (let (org-export--registered-backends org-element-block-name-alist)
+ (org-export-define-backend 'test
+ '((headline . my-headline-test))
+ :export-block '("test"))
+ org-element-block-name-alist))))
(ert-deftest test-org-export/define-derived-backend ()
"Test `org-export-define-derived-backend' specifications."
@@ -2162,68 +2170,6 @@ Another text. (ref:text)
(lambda (link) (org-export-resolve-radio-link link info)) info t)))))
-
-;;; Special blocks
-
-(ert-deftest test-org-export/raw-special-block-p ()
- "Test `org-export-raw-special-block-p' specifications."
- ;; Standard test.
- (should
- (org-test-with-parsed-data "#+BEGIN_FOO\nContents\n#+END_FOO"
- (let ((info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :blocks '("FOO"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info))))
- (should-not
- (org-test-with-parsed-data "#+BEGIN_BAR\nContents\n#+END_BAR"
- (let ((info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :blocks '("FOO"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info))))
- ;; Check is not case-sensitive.
- (should
- (org-test-with-parsed-data "#+begin_foo\nContents\n#+end_foo"
- (let ((info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :blocks '("FOO"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info))))
- ;; Test inheritance.
- (should
- (org-test-with-parsed-data "#+BEGIN_FOO\nContents\n#+END_FOO"
- (let* ((org-export--registered-backends
- (list (org-export-create-backend :name 'b1 :blocks '("FOO"))))
- (info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :parent 'b1
- :blocks '("BAR"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info))))
- (should-not
- (org-test-with-parsed-data "#+BEGIN_BAZ\nContents\n#+END_BAZ"
- (let* ((org-export--registered-backends
- (list (org-export-create-backend :name 'b1 :blocks '("FOO"))))
- (info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :parent 'b1
- :blocks '("BAR"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info))))
- ;; With optional argument, ignore inheritance.
- (should-not
- (org-test-with-parsed-data "#+BEGIN_FOO\nContents\n#+END_FOO"
- (let* ((org-export--registered-backends
- (list (org-export-create-backend :name 'b1 :blocks '("FOO"))))
- (info (org-combine-plists
- info (list :back-end
- (org-export-create-backend :parent 'b1
- :blocks '("BAR"))))))
- (org-export-raw-special-block-p
- (org-element-map tree 'special-block #'identity info t) info t)))))
-
-
;;; Src-block and example-block