Browse Source

org-export: Add function to change elements in parse tree

* contrib/lisp/org-export.el (org-export-get-buffer-attributes):
  Ensure initial accumulator in non-nil.
(org-export-set-element): New function.
* testing/lisp/test-org-export.el: Add test.
Nicolas Goaziou 13 years ago
parent
commit
e23f506d98
2 changed files with 51 additions and 5 deletions
  1. 34 4
      contrib/lisp/org-export.el
  2. 17 1
      testing/lisp/test-org-export.el

+ 34 - 4
contrib/lisp/org-export.el

@@ -1282,10 +1282,9 @@ Assume buffer is in Org mode.  Narrowing, if any, is ignored."
 			    ;; Like `org-element-parse-buffer', but
 			    ;; makes sure the definition doesn't start
 			    ;; with a section element.
-			    (nconc
-			     (list 'org-data nil)
-			     (org-element-parse-elements
-			      (point-min) (point-max) nil nil nil nil nil))))
+			    (org-element-parse-elements
+			     (point-min) (point-max) nil nil nil nil
+			     (list 'org-data nil))))
 		    alist))))
 	alist))
      :id-alist
@@ -2153,6 +2152,21 @@ 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.")
 
+
+;;;; Filters Tools
+;;
+;; Internal function `org-export-install-filters' installs filters
+;; hard-coded in back-ends (developer filters) and filters from global
+;; variables (user filters) in the communication channel.
+;;
+;; Internal function `org-export-filter-apply-functions' takes care
+;; about applying each filter in order to a given data.  It stops
+;; whenever a filter returns a nil value.
+;;
+;; User-oriented function `org-export-set-element' replaces one
+;; element or object in the parse tree with another one.  It is meant
+;; to be used as a tool for parse tree filters.
+
 (defun org-export-filter-apply-functions (filters value info)
   "Call every function in FILTERS.
 Functions are called with arguments VALUE, current export
@@ -2191,6 +2205,22 @@ Return the updated communication channel."
     ;; Return new communication channel.
     (org-combine-plists info plist)))
 
+(defun org-export-set-element (old new)
+  "Replace element or object OLD with element or object NEW.
+The function takes care of setting `:parent' property for NEW."
+  ;; OLD can belong to the contents of PARENT or to its secondary
+  ;; string.
+  (let* ((parent (org-element-property :parent old))
+	 (sec-loc (cdr (assq (org-element-type parent)
+			     org-element-secondary-value-alist)))
+	 (sec-value (and sec-loc (org-element-property sec-loc parent)))
+	 (place (or (member old sec-value) (member old parent))))
+    ;; Ensure NEW has correct parent.  Then replace OLD with NEW.
+    (let ((props (nth 1 new)))
+      (if props (plist-put props :parent parent)
+	(setcar (cdr new) `(:parent ,parent))))
+    (setcar place new)))
+
 
 
 ;;; Core functions

+ 17 - 1
testing/lisp/test-org-export.el

@@ -369,6 +369,22 @@ body\n")))
 		    (delete-region (point) (progn (forward-line) (point)))))))))
 	(should (equal (org-export-as 'test) "Body 1\nBody 2\n"))))))
 
+(ert-deftest test-org-export/set-element ()
+  "Test `org-export-set-element' property."
+  (org-test-with-parsed-data "* Headline\n*a*"
+    (org-export-set-element
+     (org-element-map tree 'bold 'identity nil t)
+     '(italic nil "b"))
+    ;; Check if object is correctly replaced.
+    (should (org-element-map tree 'italic 'identity))
+    (should-not (org-element-map tree 'bold 'identity))
+    ;; Check if new object's parent is correctly set.
+    (should
+     (equal
+      (org-element-property :parent
+			    (org-element-map tree 'italic 'identity nil t))
+      (org-element-map tree 'paragraph 'identity nil t)))))
+
 
 
 ;;; Footnotes
@@ -758,7 +774,7 @@ Another text. (ref:text)
 	("6")
 	:macro-seven
 	("1 + " (macro (:key "six" :value "{{{six}}}" :args nil :begin 5 :end 14
-			     :post-blank 0))))))))
+			     :post-blank 0 :parent nil))))))))
 
 (ert-deftest test-org-export/expand-macro ()
   "Test `org-export-expand-macro' specifications."