Jelajahi Sumber

Revert "Merge export and special blocks within back-ends"

This reverts commit fbc7097ffa30225ace2b80e9f7466ee387491c44.

Conflicts:
	lisp/ox-texinfo.el
Nicolas Goaziou 10 tahun lalu
induk
melakukan
e3369c07f0

+ 13 - 4
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
 

+ 9 - 0
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)

+ 67 - 18
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)

+ 15 - 7
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

+ 11 - 0
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)

+ 28 - 19
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 "<div%s>\n%s\n</div>" 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 "<div%s>\n%s\n</div>" attributes contents))))
 
 ;;;; Src Block
 

+ 19 - 11
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

+ 14 - 4
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

+ 10 - 1
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
 

+ 40 - 33
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<text:p>%s</text:p>"
-		  (format "<office:annotation>\n%s\n</office:annotation>"
-			  (concat
-			   (and author
-				(format "<dc:creator>%s</dc:creator>" author))
-			   (and date
-				(format "<dc:date>%s</dc:date>"
-					(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<text:p text:style-name=\"%s\">%s</text:p>"
-		  "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<text:p>%s</text:p>"
+		(format "<office:annotation>\n%s\n</office:annotation>"
+			(concat
+			 (and author
+			      (format "<dc:creator>%s</dc:creator>" author))
+			 (and date
+			      (format "<dc:date>%s</dc:date>"
+				      (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<text:p text:style-name=\"%s\">%s</text:p>"
+		"Text_20_body" (org-odt--textbox contents width height
 						   style extra anchor))))
-       (t contents)))))
+     (t contents))))
 
 
 ;;;; Src Block

+ 11 - 4
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
 

+ 13 - 2
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,

+ 39 - 0
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.

+ 9 - 1
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."