소스 검색

Modified export engines for lists

* lisp/org-exp.el (org-export-mark-lists): new function, replacing
  org-export-mark-list-ending. It adds information as text properties
  to every list, before changes done by exporter destruct them.

* lisp/org-html.el (org-export-as-html): delegate list handling to
  external function org-html-export-list-line.
(org-html-export-list-line): new function.

* lisp/org-latex.el (org-export-latex-lists): small modification.
Nicolas Goaziou 14 년 전
부모
커밋
69e02a73de
5개의 변경된 파일297개의 추가작업 그리고 244개의 파일을 삭제
  1. 94 109
      lisp/org-docbook.el
  2. 61 29
      lisp/org-exp.el
  3. 98 85
      lisp/org-html.el
  4. 40 16
      lisp/org-latex.el
  5. 4 5
      lisp/org-list.el

+ 94 - 109
lisp/org-docbook.el

@@ -499,9 +499,6 @@ publishing directory."
 	 (inquote     nil)
 	 (infixed     nil)
 	 (inverse     nil)
-	 (in-local-list nil)
-	 (local-list-type nil)
-	 (local-list-indent nil)
 	 (llt org-plain-list-ordered-item-terminator)
 	 (email (plist-get opt-plist :email))
 	 (language (plist-get opt-plist :language))
@@ -671,22 +668,6 @@ publishing directory."
 	      (org-export-docbook-open-para))
 	    (throw 'nextline nil))
 
-	  ;; List ender: close every open list.
-	  (when (equal "ORG-LIST-END" line)
-	    (while local-list-type
-	      (let ((listtype (car local-list-type)))
-		(org-export-docbook-close-li listtype)
-		(insert (cond
-			 ((equal listtype "o") "</orderedlist>\n")
-			 ((equal listtype "u") "</itemizedlist>\n")
-			 ((equal listtype "d") "</variablelist>\n"))))
-	      (pop local-list-type))
-	    ;; We did close a list, normal text follows: need <para>
-	    (org-export-docbook-open-para)
-	    (setq local-list-indent nil
-		  in-local-list nil)
-	    (throw 'nextline nil))
-
 	  ;; Protected HTML
 	  (when (get-text-property 0 'org-protected line)
 	    (let (par (ind (get-text-property 0 'original-indentation line)))
@@ -1008,93 +989,15 @@ publishing directory."
 		       (org-format-table-html table-buffer table-orig-buffer
 					      'no-css)))))
 
+	   ;; Normal lines
 	   (t
-	    ;; Normal lines
-	    (when (string-match
-		   (cond
-		    ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
-		   line)
-	      (setq ind (or (get-text-property 0 'original-indentation line)
-			    (org-get-string-indentation line))
-		    item-type (if (match-beginning 4) "o" "u")
-		    starter (if (match-beginning 2)
-				(substring (match-string 2 line) 0 -1))
-		    line (substring line (match-beginning 5))
-		    item-tag nil
-		    item-number nil)
-	      (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
-		  (setq item-number (match-string 1 line)
-			line (replace-match "" t t line)))
-	      (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
-		  (setq item-type "d"
-			item-tag (match-string 1 line)
-			line (substring line (match-end 0))))
-	      (cond
-	       ((and starter
-		     (or (not in-local-list)
-			 (> ind (car local-list-indent))))
-		;; Start new (level of) list
-		(org-export-docbook-close-para-maybe)
-		(insert (cond
-			 ((equal item-type "u") "<itemizedlist>\n<listitem>\n")
-			 ((and (equal item-type "o") item-number)
-			  ;; Check for a specific start number.  If it
-			  ;; is specified, we use the ``override''
-			  ;; attribute of element <listitem> to pass the
-			  ;; info to DocBook.  We could also use the
-			  ;; ``startingnumber'' attribute of element
-			  ;; <orderedlist>, but the former works on both
-			  ;; DocBook 5.0 and prior versions.
-			  (format "<orderedlist>\n<listitem override=\"%s\">\n" item-number))
-			 ((equal item-type "o") "<orderedlist>\n<listitem>\n")
-			 ((equal item-type "d")
-			  (format "<variablelist>\n<varlistentry><term>%s</term><listitem>\n" item-tag))))
-		;; For DocBook, we need to open a para right after tag
-		;; <listitem>.
-		(org-export-docbook-open-para)
-		(push item-type local-list-type)
-		(push ind local-list-indent)
-		(setq in-local-list t))
-		;; Continue current list
-	       (starter
-		;; terminate any previous sublist but first ensure
-		;; list is not ill-formed
-		(let ((min-ind (apply 'min local-list-indent)))
-		  (when (< ind min-ind) (setq ind min-ind)))
-		(while (< ind (car local-list-indent))
-		  (let ((listtype (car local-list-type)))
-		    (org-export-docbook-close-li listtype)
-		    (insert (cond
-			     ((equal listtype "o") "</orderedlist>\n")
-			     ((equal listtype "u") "</itemizedlist>\n")
-			     ((equal listtype "d") "</variablelist>\n"))))
-		  (pop local-list-type) (pop local-list-indent)
-		  (setq in-local-list local-list-indent))
-		;; insert new item
-		(let ((listtype (car local-list-type)))
-		  (org-export-docbook-close-li listtype)
-		  (insert (cond
-			   ((and (equal listtype "o") item-number)
-			    (format "<listitem override=\"%s\">" item-number))
-			   ((equal listtype "o") "<listitem>")
-			   ((equal listtype "u") "<listitem>")
-			   ((equal listtype "d") (format
-						  "<varlistentry><term>%s</term><listitem>"
-						  (or item-tag
-						      "???"))))))
-		;; For DocBook, we need to open a para right after tag
-		;; <listitem>.
-		(org-export-docbook-open-para)))
-	      ;; Checkboxes.
-	      (if (string-match "^[ \t]*\\(\\[[X -]\\]\\)" line)
-		  (setq line
-			(replace-match (concat checkbox-start
-					       (match-string 1 line)
-					       checkbox-end)
-				       t t line))))
+	    ;; This line either is list item or end a list.
+	    (when (when (get-text-property 0 'list-item line)
+	   	      (setq line (org-export-docbook-list-line
+			  line
+			  (get-text-property 0 'list-item line)
+			  (get-text-property 0 'list-struct line)
+			  (get-text-property 0 'list-prevs line)))))
 
 	    ;; Empty lines start a new paragraph.  If hand-formatted lists
 	    ;; are not fully interpreted, lines starting with "-", "+", "*"
@@ -1193,10 +1096,6 @@ publishing directory."
       (insert "</listitem></varlistentry>\n")
     (insert "</listitem>\n")))
 
-(defvar in-local-list)
-(defvar local-list-indent)
-(defvar local-list-type)
-
 (defun org-export-docbook-level-start (level title)
   "Insert a new level in DocBook export.
 When TITLE is nil, just close all open levels."
@@ -1438,6 +1337,92 @@ that need to be preserved in later phase of DocBook exporting."
 	    line (substring line (match-end 0))))
     (concat replaced line)))
 
+(defun org-export-docbook-list-line (line pos struct prevs)
+  "Insert list syntax in export buffer. Return LINE, maybe modified.
+
+POS is the item position or line position the line had before
+modifications to buffer. STRUCT is the list structure. PREVS is
+the alist of previous items."
+  (let* ((get-type
+	  (function
+	   ;; Return type of list containing element POS, among
+	   ;; "ordered", "variable" or "itemized".
+	   (lambda (pos)
+	     (cond
+	      ((string-match "[0-9]" (org-list-get-bullet pos struct))
+	       "ordered")
+	      ((org-list-get-tag pos struct) "variable")
+	      (t "itemized")))))
+	 (get-closings
+	  (function
+	   ;; Return list of all items and sublists ending at POS, in
+	   ;; reverse order.
+	   (lambda (pos)
+	     (let (out)
+	       (catch 'exit
+		 (mapc (lambda (e)
+			 (let ((end (nth 6 e))
+			       (item (car e)))
+			   (cond
+			    ((= end pos) (push item out))
+			    ((>= item pos) (throw 'exit nil)))))
+		       struct))
+	       out)))))
+    ;; First close any previous item, or list, ending at POS.
+    (mapc (lambda (e)
+	    (let* ((lastp (= (org-list-get-last-item e struct prevs) e))
+		   (first-item (org-list-get-list-begin e struct prevs))
+		   (type (funcall get-type first-item)))
+	      ;; Ending for every item
+	      (org-export-docbook-close-para-maybe)
+	      (insert (if (equal type "variable")
+			  "</listitem></varlistentry>\n"
+			"</listitem>\n"))
+	      ;; We're ending last item of the list: end list.
+	      (when lastp (insert (format "</%slist>\n" type)))))
+	  (funcall get-closings pos))
+    (cond
+     ;; At an item: insert appropriate tags in export buffer.
+     ((assq pos struct)
+      (string-match
+       (concat "[ \t]*\\(\\(?:[-+*]\\|[0-9]+[.)]\\)[ \t]+\\)"
+	       "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\)\\]\\)?"
+	       "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
+	       "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+	       "\\(.*\\)") line)
+      (let* ((counter (match-string 2 line))
+	     (checkbox (match-string 3 line))
+	     (desc-tag (or (match-string 4 line) "???"))
+	     (body (match-string 5 line))
+	     (list-beg (org-list-get-list-begin pos struct prevs))
+	     (firstp (= list-beg pos))
+	     ;; Always refer to first item to determine list type, in
+	     ;; case list is ill-formed.
+	     (type (funcall get-type list-beg)))
+	;; When FIRSTP, a new list or sub-list is starting.
+	(when firstp
+	  (org-export-docbook-close-para-maybe)
+	  (insert (format "<%slist>\n" type)))
+	(insert (cond
+		 ((equal type "variable")
+		  (format "<varlistentry><term>%s</term><listitem>" desc-tag))
+		 ((and (equal type "ordered") counter)
+		  (format "<listitem override=\"%s\">" counter))
+		 (t "<listitem>")))
+	;; For DocBook, we need to open a para right after tag
+	;; <listitem>.
+	(org-export-docbook-open-para)
+	;; If line had a checkbox, some additional modification is required.
+	(when checkbox (setq body (concat checkbox " " body)))
+	;; Return modified line
+	body))
+     ;; At a list ender:  normal text follows: need <para>.
+     ((equal "ORG-LIST-END" line)
+      (org-export-docbook-open-para)
+      (throw 'nextline nil))
+     ;; Not at an item: return line unchanged (side-effects only).
+     (t line))))
+
 (provide 'org-docbook)
 
 ;; arch-tag: a24a127c-d365-4c2a-9e9b-f7dcb0ebfdc3

+ 61 - 29
lisp/org-exp.el

@@ -1089,8 +1089,8 @@ on this string to produce the exported version."
 				     (plist-get parameters :exclude-tags))
       (run-hooks 'org-export-preprocess-after-tree-selection-hook)
 
-      ;; Mark end of lists
-      (org-export-mark-list-ending backend)
+      ;; Mark lists
+      (org-export-mark-lists backend)
 
       ;; Export code blocks
       (org-export-blocks-preprocess)
@@ -1670,34 +1670,66 @@ These special cookies will later be interpreted by the backend."
 	(delete-region beg end)
 	(insert (org-add-props content nil 'original-indentation ind))))))
 
-(defun org-export-mark-list-ending (backend)
-  "Mark list endings with special cookies.
-These special cookies will later be interpreted by the backend.
+(defun org-export-mark-lists (backend)
+  "Mark list with special properties.
+These special properties will later be interpreted by the backend.
 `org-list-end-re' is replaced by a blank line in the process."
-  (let ((process-buffer
-	 (lambda (end-list-marker)
-	   (goto-char (point-min))
-	   (while (org-search-forward-unenclosed org-item-beginning-re nil t)
-	     (beginning-of-line)
-	     (goto-char (org-list-get-bottom-point (org-list-struct)))
-	     (when (and (not (eq org-list-ending-method 'indent))
-			(looking-at (org-list-end-re)))
-	       (replace-match "\n"))
-	     (unless (bolp) (insert "\n"))
-	     (unless (looking-at end-list-marker)
-	       (insert end-list-marker))
-	     (unless (eolp) (insert "\n"))))))
-  ;; We need to divide backends into 3 categories.
-  (cond
-   ;; 1. Backends using `org-list-parse-list' do not need markers.
-   ((memq backend '(latex))
-    nil)
-   ;; 2. Line-processing backends need to be told where lists end.
-   ((memq backend '(html docbook))
-    (funcall process-buffer "ORG-LIST-END\n"))
-   ;; 3. Others backends do not need to know this: clean list enders.
-   (t
-    (funcall process-buffer "")))))
+  (let ((mark-list
+	 (function
+	  ;; Mark a list with 3 properties: `list-item' which is
+	  ;; position at beginning of line, `list-struct' which is
+	  ;; list structure, and `list-prevs' which is the alist of
+	  ;; item and its predecessor. Leave point at list ending.
+	  (lambda (ctxt)
+	    (let* ((struct (org-list-struct))
+		   (top (org-list-get-top-point struct))
+		   (bottom (org-list-get-bottom-point struct))
+		   (prevs (org-list-struct-prev-alist struct))
+		   poi)
+	      ;; Get every item and ending position, without dups and
+	      ;; without bottom point of list.
+	      (mapc (lambda (e)
+		      (let ((pos (car e))
+			    (end (nth 6 e)))
+			(unless (memq pos poi)
+			  (push pos poi))
+			(unless (or (= end bottom) (memq end poi))
+			  (push end poi))))
+		    struct)
+	      (setq poi (sort poi '<))
+	      ;; For every point of interest, mark the whole line with
+	      ;; its position in list.
+	      (mapc
+	       (lambda (e)
+		 (goto-char e)
+		 (add-text-properties (point-at-bol) (point-at-eol)
+				      (list 'list-item (point-at-bol)
+					    'list-struct struct
+					    'list-prevs prevs)))
+	       poi)
+	      ;; Take care of bottom point. As it is probably at an
+	      ;; empty line, insert a virtual ending with required
+	      ;; property.
+	      (goto-char bottom)
+	      (when (and (not (eq org-list-ending-method 'indent))
+			 (looking-at (org-list-end-re)))
+		(replace-match ""))
+	      (unless (bolp) (insert "\n"))
+	      (insert
+	       (org-add-props "ORG-LIST-END\n" (list 'list-item bottom
+						     'list-struct struct
+						     'list-prevs prevs)))
+	      ;; Add `list-context' as text property between top and
+	      ;; bottom.
+	      (add-text-properties top (point) (list 'list-context ctxt)))))))
+    ;; Mark lists except for backends not interpreting them.
+    (unless (eq backend 'ascii)
+      (mapc
+       (lambda (e)
+	 (goto-char (point-min))
+	 (while (re-search-forward org-item-beginning-re nil t)
+	   (when (eq (nth 2 (org-list-context)) e) (funcall mark-list e))))
+       '(nil block)))))
 
 (defun org-export-attach-captions-and-attributes (backend target-alist)
   "Move #+CAPTION, #+ATTR_BACKEND, and #+LABEL text into text properties.

+ 98 - 85
lisp/org-html.el

@@ -1116,9 +1116,6 @@ PUB-DIR is set, use this as the publishing directory."
 	 (inquote     nil)
 	 (infixed     nil)
 	 (inverse     nil)
-	 (in-local-list nil)
-	 (local-list-type nil)
-	 (local-list-indent nil)
 	 (llt org-plain-list-ordered-item-terminator)
 	 (email       (plist-get opt-plist :email))
 	 (language    (plist-get opt-plist :language))
@@ -1177,8 +1174,9 @@ PUB-DIR is set, use this as the publishing directory."
 	    ""))
 	 table-open
 	 table-buffer table-orig-buffer
-	 ind item-type starter
-	 snumber item-tag item-number
+	 ind
+	 rpl path attr desc descp desc1 desc2 link
+	 snumber fnc
 	 footnotes footref-seen
 	 href
 	 )
@@ -1404,17 +1402,6 @@ lang=\"%s\" xml:lang=\"%s\">
 	      (org-open-par))
 	    (throw 'nextline nil))
 
-	  ;; Explicit list closure
-	  (when (equal "ORG-LIST-END" line)
-	    (while local-list-indent
-	      (org-close-li (car local-list-type))
-	      (insert (format "</%sl>\n" (car local-list-type)))
-	      (pop local-list-type)
-	      (pop local-list-indent))
-	    (setq in-local-list nil)
-	    (org-open-par)
-	    (throw 'nextline nil))
-
 	  ;; Protected HTML
 	  (when (and (get-text-property 0 'org-protected line)
 		     ;; Make sure it is the entire line that is protected
@@ -1595,72 +1582,17 @@ lang=\"%s\" xml:lang=\"%s\">
 		    table-orig-buffer (nreverse table-orig-buffer))
 	      (org-close-par-maybe)
 	      (insert (org-format-table-html table-buffer table-orig-buffer))))
+
+	   ;; Normal lines
+
 	   (t
-	    ;; Normal lines
-	    (when (string-match
-		   (cond
-		    ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
-		   line)
-	      (setq ind (or (get-text-property 0 'original-indentation line)
-			    (org-get-string-indentation line))
-		    item-type (if (match-beginning 4) "o" "u")
-		    starter (if (match-beginning 2)
-				(substring (match-string 2 line) 0 -1))
-		    line (substring line (match-beginning 5))
-		    item-number nil
-		    item-tag nil)
-	      (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
-		  (setq item-number (match-string 1 line)
-			line (replace-match "" t t line)))
-	      (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
-		  (setq item-type "d"
-			item-tag (match-string 1 line)
-			line (substring line (match-end 0))))
-	      (cond
-	       ((and starter
-		     (or (not in-local-list)
-			 (> ind (car local-list-indent))))
-		;; Start new (level of) list
-		(org-close-par-maybe)
-		(insert (cond
-			 ((equal item-type "u") "<ul>\n<li>\n")
-			 ((and (equal item-type "o") item-number)
-			  (format "<ol>\n<li value=\"%s\">\n" item-number))
-			 ((equal item-type "o") "<ol>\n<li>\n")
-			 ((equal item-type "d")
-			  (format "<dl>\n<dt>%s</dt><dd>\n" item-tag))))
-		(push item-type local-list-type)
-		(push ind local-list-indent)
-		(setq in-local-list t))
-	       ;; Continue list
-	       (starter
-		;; terminate any previous sublist but first ensure
-		;; list is not ill-formed.
-		(let ((min-ind (apply 'min local-list-indent)))
-		  (when (< ind min-ind) (setq ind min-ind)))
-		(while (< ind (car local-list-indent))
-		  (org-close-li (car local-list-type))
-		  (insert (format "</%sl>\n" (car local-list-type)))
-		  (pop local-list-type) (pop local-list-indent)
-		  (setq in-local-list local-list-indent))
-		;; insert new item
-		(org-close-li (car local-list-type))
-		(insert (cond
-			 ((equal (car local-list-type) "d")
-			  (format "<dt>%s</dt><dd>\n" (or item-tag "???")))
-			 ((and (equal item-type "o") item-number)
-			  (format "<li value=\"%s\">\n" item-number))
-			 (t "<li>\n")))))
-	      (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
-		  (setq line
-			(replace-match
-			 (if (equal (match-string 1 line) "X")
-			     "<b>[X]</b>"
-			   "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
-			 t t line))))
+	    ;; This line either is list item or end a list.
+	    (when (get-text-property 0 'list-item line)
+	      (setq line (org-html-export-list-line
+			  line
+			  (get-text-property 0 'list-item line)
+			  (get-text-property 0 'list-struct line)
+			  (get-text-property 0 'list-prevs line))))
 
 	    ;; Horizontal line
 	    (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
@@ -2350,10 +2282,6 @@ If there are links in the string, don't modify these."
   (org-close-par-maybe)
   (insert (if (equal type "d") "</dd>\n" "</li>\n")))
 
-(defvar in-local-list)
-(defvar local-list-indent)
-(defvar local-list-type)
-
 (defvar body-only) ; dynamically scoped into this.
 (defun org-html-level-start (level title umax with-toc head-count)
   "Insert a new level in HTML export.
@@ -2459,6 +2387,91 @@ Replaces invalid characters with \"_\" and then prepends a prefix."
     (org-close-li)
     (insert "</ul>\n")))
 
+(defun org-html-export-list-line (line pos struct prevs)
+  "Insert list syntax in export buffer. Return LINE, maybe modified.
+
+POS is the item position or line position the line had before
+modifications to buffer. STRUCT is the list structure. PREVS is
+the alist of previous items."
+  (let* ((get-type
+	  (function
+	   ;; Return type of list containing element POS, among "d",
+	   ;; "o" or "u".
+	   (lambda (pos)
+	     (cond
+	      ((string-match "[0-9]" (org-list-get-bullet pos struct)) "o")
+	      ((org-list-get-tag pos struct) "d")
+	      (t "u")))))
+	 (get-closings
+	  (function
+	   ;; Return list of all items and sublists ending at POS, in
+	   ;; reverse order.
+	   (lambda (pos)
+	     (let (out)
+	       (catch 'exit
+		 (mapc (lambda (e)
+			 (let ((end (nth 6 e))
+			       (item (car e)))
+			   (cond
+			    ((= end pos) (push item out))
+			    ((>= item pos) (throw 'exit nil)))))
+		       struct))
+	       out)))))
+    ;; First close any previous item, or list, ending at POS.
+    (mapc (lambda (e)
+	    (let* ((lastp (= (org-list-get-last-item e struct prevs) e))
+		   (first-item (org-list-get-list-begin e struct prevs))
+		   (type (funcall get-type first-item)))
+	      (org-close-par-maybe)
+	      ;; Ending for every item
+	      (org-close-li type)
+	      ;; We're ending last item of the list: end list.
+	      (when lastp (insert (format "</%sl>\n" type)))))
+	  (funcall get-closings pos))
+    (cond
+     ;; At an item: insert appropriate tags in export buffer.
+     ((assq pos struct)
+      (string-match
+       (concat "[ \t]*\\(\\(?:[-+*]\\|[0-9]+[.)]\\)[ \t]+\\)"
+	       "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\)\\]\\)?"
+	       "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
+	       "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+	       "\\(.*\\)") line)
+      (let* ((counter (match-string 2 line))
+	     (checkbox (match-string 3 line))
+	     (desc-tag (or (match-string 4 line) "???"))
+	     (body (match-string 5 line))
+	     (list-beg (org-list-get-list-begin pos struct prevs))
+	     (firstp (= list-beg pos))
+	     ;; Always refer to first item to determine list type, in
+	     ;; case list is ill-formed.
+	     (type (funcall get-type list-beg)))
+	(when firstp
+	  (org-close-par-maybe)
+	  (insert (format "<%sl>\n" type)))
+	(insert (cond
+		 ((equal type "d")
+		  (format "<dt>%s</dt><dd>\n" desc-tag))
+		 ((and (equal type "o") counter)
+		  (format "<li value=\"%s\">\n" counter))
+		 (t "<li>\n")))
+	;; If line had a checkbox, some additional modification is required.
+	(when checkbox
+	  (setq body
+		(concat
+		 (cond
+		  ((string-match "X" checkbox) "<b>[X]</b> ")
+		  ((string-match " " checkbox)
+		   "<b>[<span style=\"visibility:hidden;\">X</span>]</b> ")
+		  (t "[-] "))
+		 body)))
+	;; Return modified line
+	body))
+     ;; At a list ender: go to next line (side-effects only).
+     ((equal "ORG-LIST-END" line) (throw 'nextline nil))
+     ;; Not at an item: return line unchanged (side-effects only).
+     (t line))))
+
 (provide 'org-html)
 
 ;; arch-tag: 8109d84d-eb8f-460b-b1a8-f45f3a6c7ea1

+ 40 - 16
lisp/org-latex.el

@@ -2460,22 +2460,46 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
 
 (defun org-export-latex-lists ()
   "Convert plain text lists in current buffer into LaTeX lists."
-  (let (res)
-    (goto-char (point-min))
-    (while (org-search-forward-unenclosed org-item-beginning-re nil t)
-      (beginning-of-line)
-      (setq res (org-list-to-latex (org-list-parse-list t)
-				   org-export-latex-list-parameters))
-      (while (string-match "^\\(\\\\item[ \t]+\\)\\[@\\(?:start:\\)?\\([0-9]+\\)\\]"
-			   res)
-	(setq res (replace-match
-		   (concat (format "\\setcounter{enumi}{%d}"
-				   (1- (string-to-number
-					(match-string 2 res))))
-			   "\n"
-			   (match-string 1 res))
-		   t t res)))
-      (insert res))))
+  (mapc
+   (lambda (e)
+     ;; For each type of context allowed for list export (E), find
+     ;; every list, parse it, delete it and insert resulting
+     ;; conversion to latex (RES).
+     (let (res)
+       (goto-char (point-min))
+       (while (re-search-forward org-item-beginning-re nil t)
+	 (when (eq (get-text-property (point) 'list-context) e)
+	   (beginning-of-line)
+	   (setq res
+		 (org-list-to-latex
+		  ;; Narrowing is needed because we're converting
+		  ;; inner functions to outer ones.
+		  (save-restriction
+		    (narrow-to-region (point) (point-max))
+		    ;; `org-list-end-re' output has changed since
+		    ;; preprocess from org-exp.el. Tell it to
+		    ;; `org-list-parse-list'.
+		    (flet ((org-list-end-re nil "^ORG-LIST-END\n"))
+		      (org-list-parse-list t)))
+		  org-export-latex-list-parameters))
+	   ;; Replace any counter with its latex expression in output
+	   ;; string.
+	   (while (string-match
+		   "^\\(\\\\item[ \t]+\\)\\[@\\(?:start:\\)?\\([0-9]+\\)\\]"
+		   res)
+	     (setq res (replace-match
+			(concat (format "\\setcounter{enumi}{%d}"
+					(1- (string-to-number
+					     (match-string 2 res))))
+				"\n"
+				(match-string 1 res))
+			t t res)))
+	   ;; Extend previous value of original-indentation to the whole
+	   ;; string
+	   (insert (org-add-props res nil 'original-indentation
+				  (org-find-text-property-in-string
+				   'original-indentation res)))))))
+   '(block nil)))
 
 (defconst org-latex-entities
  '("\\!"

+ 4 - 5
lisp/org-list.el

@@ -2494,13 +2494,12 @@ Point is left at list end."
     ;; store output, take care of cursor position and deletion of
     ;; list, then return output.
     (setq out (funcall parse-sublist (org-list-get-all-items top struct prevs)))
-    (goto-char bottom)
+    (goto-char top)
     (when delete
       (delete-region top bottom)
-      (save-match-data
-	(when (and (not (eq org-list-ending-method 'indent))
-		   (looking-at (org-list-end-re)))
-	  (replace-match "\n"))))
+      (when (and (not (eq org-list-ending-method 'indent))
+		 (looking-at (org-list-end-re)))
+	(replace-match "\n")))
     out))
 
 (defun org-list-make-subtree ()