Browse Source

Merge branch 'maint' into emacs-sync

Kyle Meyer 8 months ago
parent
commit
594201d414

+ 2 - 2
contrib/lisp/ox-koma-letter.el

@@ -705,7 +705,7 @@ holding export options."
 	      (or (if (plist-get info :special-headings)
 		      (or heading-val keyword-val)
 		    (or keyword-val heading-val))
-		  "\\\\mbox{}"))))
+		  "\\mbox{}"))))
    ;; Opening.
    (format "\\opening{%s}\n\n"
 	   (org-koma-letter--keyword-or-headline
@@ -717,7 +717,7 @@ holding export options."
    (format "\\closing{%s}\n"
 	   (org-koma-letter--keyword-or-headline
 	    :closing (lambda (h i) (eq (org-koma-letter--special-tag h i)
-				       'closing))
+				  'closing))
 	    info))
    (org-koma-letter--special-contents-inline
     (plist-get info :special-tags-after-closing) info)

+ 2 - 1
contrib/lisp/ox-s5.el

@@ -292,7 +292,8 @@ which will make the list into a \"build\"."
              "<%s class='org-%s%s'>" tag tag
              (if (org-export-get-node-property :INCREMENTAL plain-list t)
                  " incremental" ""))
-            contents (org-html-end-plain-list type))))
+            contents
+	    (format "</%s>" tag))))
 
 (defun org-s5-inner-template (contents info)
   "Return body of document string after HTML conversion.

+ 21 - 12
doc/org.texi

@@ -1461,10 +1461,10 @@ Demote current heading by one level.
 Promote the current subtree by one level.
 @orgcmd{M-S-@key{right},org-demote-subtree}
 Demote the current subtree by one level.
-@orgcmd{M-S-@key{up},org-move-subtree-up}
+@orgcmd{M-@key{up},org-move-subtree-up}
 Move subtree up (swap with previous subtree of same
 level).
-@orgcmd{M-S-@key{down},org-move-subtree-down}
+@orgcmd{M-@key{down},org-move-subtree-down}
 Move subtree down (swap with next subtree of same level).
 @orgcmd{M-h,org-mark-element}
 Mark the element at point.  Hitting repeatedly will mark subsequent elements
@@ -7352,6 +7352,7 @@ gnus                             |  %:group, @r{for messages also all email fiel
 eww, w3, w3m                     |  %:url
 info                             |  %:file %:node
 calendar                         |  %:date
+org-protocol                     |  %:link %:description %:annotation
 @end smallexample
 
 @noindent
@@ -7593,22 +7594,15 @@ javascript:location.href='org-protocol://store-link?url='+
 @cindex capture protocol
 @cindex protocol, capture
 
-@cindex capture, %:url placeholder
-@cindex %:url template expansion in capture
-@cindex capture, %:title placeholder
-@cindex %:title template expansion in capture
 Activating @code{capture} handler pops up a @samp{Capture} buffer and fills
-the capture template associated to the @samp{X} key with them.  The template
-refers to the data through @code{%:url} and @code{%:title} placeholders.
-Moreover, any selected text in the browser is appended to the body of the
-entry.
+the capture template associated to the @samp{X} key with them.
 
 @example
 emacsclient org-protocol://capture?template=X?url=URL?title=TITLE?body=BODY
 @end example
 
-To use this feature, add a bookmark with an arbitrary name, e.g.
-@samp{Org: capture} and enter this as @samp{Location}:
+To use this feature, add a bookmark with an arbitrary name, e.g.  @samp{Org:
+capture} and enter this as @samp{Location}:
 
 @example
 javascript:location.href='org-protocol://template=x'+
@@ -7622,6 +7616,21 @@ The result depends on the capture template used, which is set in the bookmark
 itself, as in the example above, or in
 @code{org-protocol-default-template-key}.
 
+@cindex capture, %:link placeholder
+@cindex %:link template expansion in capture
+@cindex capture, %:description placeholder
+@cindex %:description template expansion in capture
+@cindex capture, %:annotation placeholder
+@cindex %:annotation template expansion in capture
+The following template placeholders are available:
+
+@example
+%:link          The URL
+%:description   The webpage title
+%:annotation    Equivalent to [[%:link][%:description]]
+%i              The selected text
+@end example
+
 @node @code{open-source} protocol
 @subsection @code{open-source} protocol
 @cindex open-source protocol

+ 3 - 4
lisp/ob-tangle.el

@@ -494,10 +494,9 @@ non-nil, return the full association list to be used by
 		  link)
 		source-name
 		params
-		(org-unescape-code-in-string
-		 (if org-src-preserve-indentation
-		     (org-trim body t)
-		   (org-trim (org-remove-indentation body))))
+		(if org-src-preserve-indentation
+		    (org-trim body t)
+		  (org-trim (org-remove-indentation body)))
 		comment)))
     (if only-this-block
 	(list (cons src-lang (list result)))

+ 1 - 1
lisp/org-attach.el

@@ -507,7 +507,7 @@ This can be used after files have been added externally."
   (let ((attach-dir (org-attach-dir)))
     (when attach-dir
       (let ((files (org-attach-file-list attach-dir)))
-	(and files (org-attach-tag))
+	(org-attach-tag (not files))
 	(when org-attach-file-list-property
 	  (dolist (file files)
 	    (unless (string-match "^\\.\\.?\\'" file)

+ 6 - 7
lisp/org-capture.el

@@ -1311,8 +1311,8 @@ Of course, if exact position has been required, just put it there."
 
 (defun org-capture-mark-kill-region (beg end)
   "Mark the region that will have to be killed when aborting capture."
-  (let ((m1 (move-marker (make-marker) beg))
-	(m2 (move-marker (make-marker) end)))
+  (let ((m1 (copy-marker beg))
+	(m2 (copy-marker end t)))
     (org-capture-put :begin-marker m1)
     (org-capture-put :end-marker m2)))
 
@@ -1792,11 +1792,10 @@ The template may still contain \"%?\" for cursor positioning."
 		     (let* ((upcase? (equal (upcase key) key))
 			    (org-end-time-was-given nil)
 			    (time (org-read-date upcase? t nil prompt)))
-		       (let ((org-time-was-given upcase?))
-			 (org-insert-time-stamp
-			  time org-time-was-given
-			  (member key '("u" "U"))
-			  nil nil (list org-end-time-was-given)))))
+		       (org-insert-time-stamp
+			time (or org-time-was-given upcase?)
+			(member key '("u" "U"))
+			nil nil (list org-end-time-was-given))))
 		    (`nil
 		     (push (org-completing-read
 			    (concat (or prompt "Enter string")

+ 10 - 3
lisp/org-clock.el

@@ -487,7 +487,7 @@ to add an effort property.")
                                    "10\\.6\\.[[:digit:]]"
                                    (shell-command-to-string
                                     "sw_vers -productVersion"))
-                                  (<= m -1034058203136))
+                                  (<= m -1034058203135))
                        (ignore-errors (decode-time (list m 0)))))))
 	 (low
 	  (funcall dichotomy
@@ -2725,7 +2725,9 @@ LEVEL is an integer.  Indent by two spaces per level above 1."
       (setq te (float-time (apply #'encode-time (org-parse-time-string te))))))
     (setq tsb
 	  (if (eq step0 'week)
-	      (- ts (* 86400 (- (nth 6 (decode-time (seconds-to-time ts))) ws)))
+	      (let ((dow (nth 6 (decode-time (seconds-to-time ts)))))
+		(if (< dow ws) ts
+		  (- ts (* 86400 (- dow ws)))))
 	    ts))
     (setq p1 (plist-put p1 :header ""))
     (setq p1 (plist-put p1 :step nil))
@@ -2735,9 +2737,14 @@ LEVEL is an integer.  Indent by two spaces per level above 1."
       (setq p1 (plist-put p1 :tstart (format-time-string
 				      (org-time-stamp-format nil t)
 				      (seconds-to-time (max tsb ts)))))
+      (cl-incf tsb (let ((dow (nth 6 (decode-time (seconds-to-time tsb)))))
+		     (if (or (eq step0 'day)
+			     (= dow ws))
+			 step
+		       (* 86400 (- ws dow)))))
       (setq p1 (plist-put p1 :tend (format-time-string
 				    (org-time-stamp-format nil t)
-				    (seconds-to-time (min te (setq tsb (+ tsb step)))))))
+				    (seconds-to-time (min te tsb)))))
       (insert "\n" (if (eq step0 'day) "Daily report: "
 		     "Weekly report starting on: ")
 	      (plist-get p1 :tstart) "\n")

+ 16 - 19
lisp/org-element.el

@@ -1308,23 +1308,19 @@ CONTENTS is the contents of the element."
 	(inlinetask-re (and (featurep 'org-inlinetask) "^\\*+ "))
 	items struct)
     (save-excursion
-      (catch 'exit
+      (catch :exit
 	(while t
 	  (cond
 	   ;; At limit: end all items.
 	   ((>= (point) limit)
-	    (throw 'exit
-		   (let ((end (progn (skip-chars-backward " \r\t\n")
-				     (forward-line)
-				     (point))))
-		     (dolist (item items (sort (nconc items struct)
-					       'car-less-than-car))
-		       (setcar (nthcdr 6 item) end)))))
+	    (let ((end (progn (skip-chars-backward " \r\t\n")
+			      (line-beginning-position 2))))
+	      (dolist (item items) (setcar (nthcdr 6 item) end)))
+	    (throw :exit (sort (nconc items struct) #'car-less-than-car)))
 	   ;; At list end: end all items.
 	   ((looking-at org-list-end-re)
-	    (throw 'exit (dolist (item items (sort (nconc items struct)
-						   'car-less-than-car))
-			   (setcar (nthcdr 6 item) (point)))))
+	    (dolist (item items) (setcar (nthcdr 6 item) (point)))
+	    (throw :exit (sort (nconc items struct) #'car-less-than-car)))
 	   ;; At a new item: end previous sibling.
 	   ((looking-at item-re)
 	    (let ((ind (save-excursion (skip-chars-forward " \t")
@@ -1348,7 +1344,7 @@ CONTENTS is the contents of the element."
 				   ;; Ending position, unknown so far.
 				   nil)))
 		    items))
-	    (forward-line 1))
+	    (forward-line))
 	   ;; Skip empty lines.
 	   ((looking-at "^[ \t]*$") (forward-line))
 	   ;; Skip inline tasks and blank lines along the way.
@@ -1360,17 +1356,18 @@ CONTENTS is the contents of the element."
 		  (goto-char origin)))))
 	   ;; At some text line.  Check if it ends any previous item.
 	   (t
-	    (let ((ind (save-excursion (skip-chars-forward " \t")
-				       (current-column))))
-	      (when (<= ind top-ind)
-		(skip-chars-backward " \r\t\n")
-		(forward-line))
+	    (let ((ind (save-excursion
+			 (skip-chars-forward " \t")
+			 (current-column)))
+		  (end (save-excursion
+			 (skip-chars-backward " \r\t\n")
+			 (line-beginning-position 2))))
 	      (while (<= ind (nth 1 (car items)))
 		(let ((item (pop items)))
-		  (setcar (nthcdr 6 item) (line-beginning-position))
+		  (setcar (nthcdr 6 item) end)
 		  (push item struct)
 		  (unless items
-		    (throw 'exit (sort struct #'car-less-than-car))))))
+		    (throw :exit (sort struct #'car-less-than-car))))))
 	    ;; Skip blocks (any type) and drawers contents.
 	    (cond
 	     ((and (looking-at "[ \t]*#\\+BEGIN\\(:\\|_\\S-+\\)")

+ 1 - 1
lisp/org-faces.el

@@ -291,7 +291,7 @@ determines if it is a foreground or a background color."
 (defcustom org-priority-faces nil
   "Faces for specific Priorities.
 This is a list of cons cells, with priority character in the car
-and faces in the cdr.  The face can be a symbol, a color as
+and faces in the cdr.  The face can be a symbol, a color
 as a string, or a property list of attributes, like
     (:foreground \"blue\" :weight bold :underline t).
 If it is a color string, the variable `org-faces-easy-properties'

+ 1 - 2
lisp/org-id.el

@@ -539,8 +539,7 @@ When FILES is given, scan these files instead."
     (with-temp-buffer
       (condition-case nil
 	  (progn
-	    (insert-file-contents-literally org-id-locations-file)
-	    (goto-char (point-min))
+	    (insert-file-contents org-id-locations-file)
 	    (setq org-id-locations (read (current-buffer))))
 	(error
 	 (message "Could not read org-id-values from %s.  Setting it to nil."

+ 1 - 1
lisp/org-inlinetask.el

@@ -114,7 +114,7 @@ When nil, the first star is not shown."
 (defcustom org-inlinetask-default-state nil
   "Non-nil means make inline tasks have a TODO keyword initially.
 This should be the state `org-inlinetask-insert-task' should use by
-default, or nil of no state should be assigned."
+default, or nil if no state should be assigned."
   :group 'org-inlinetask
   :version "24.1"
   :type '(choice

+ 12 - 13
lisp/org-macs.el

@@ -51,8 +51,8 @@ Otherwise, return nil."
 SEPARATORS is a regular expression.  When nil, it defaults to
 \"[ \f\t\n\r\v]+\".
 
-Unlike to `split-string', matching SEPARATORS at the beginning
-and end of string are ignored."
+Unlike `split-string', matching SEPARATORS at the beginning and
+end of string are ignored."
   (let ((separators (or separators "[ \f\t\n\r\v]+")))
     (when (string-match (concat "\\`" separators) string)
       (setq string (replace-match "" nil nil string)))
@@ -108,16 +108,15 @@ text properties."
 			      (value (if (stringp display) display
 				       (cl-some #'stringp display))))
 			 (when value
-			   (apply
-			    #'propertize
-			    ;; Displayed string could contain
-			    ;; invisible parts, but no nested display.
-			    (funcall prune-invisible value)
-			    (plist-put props
-				       'display
-				       (and (not (stringp display))
-					    (cl-remove-if #'stringp
-							  display)))))))))))
+			   (apply #'propertize
+				  ;; Displayed string could contain
+				  ;; invisible parts, but no nested
+				  ;; display.
+				  (funcall prune-invisible value)
+				  'display
+				  (and (not (stringp display))
+				       (cl-remove-if #'stringp display))
+				  props))))))))
     ;; `display' property overrides `invisible' one.  So we first
     ;; replace characters with `display' property.  Then we remove
     ;; invisible characters.
@@ -125,7 +124,7 @@ text properties."
 
 (defun org-string-width (string)
   "Return width of STRING when displayed in the current buffer.
-Unlike to `string-width', this function takes into consideration
+Unlike `string-width', this function takes into consideration
 `invisible' and `display' text properties."
   (string-width (org-string-display string)))
 

+ 5 - 4
lisp/org-src.el

@@ -581,14 +581,15 @@ Escaping happens when a line starts with \"*\", \"#+\", \",*\" or
   (interactive "r")
   (save-excursion
     (goto-char end)
-    (while (re-search-backward "^[ \t]*,?\\(\\*\\|#\\+\\)" beg t)
+    (while (re-search-backward "^[ \t]*\\(,*\\(?:\\*\\|#\\+\\)\\)" beg t)
       (save-excursion (replace-match ",\\1" nil nil nil 1)))))
 
 (defun org-escape-code-in-string (s)
   "Escape lines in string S.
 Escaping happens when a line starts with \"*\", \"#+\", \",*\" or
 \",#+\" by appending a comma to it."
-  (replace-regexp-in-string "^[ \t]*,?\\(\\*\\|#\\+\\)" ",\\1" s nil nil 1))
+  (replace-regexp-in-string "^[ \t]*\\(,*\\(?:\\*\\|#\\+\\)\\)" ",\\1"
+			    s nil nil 1))
 
 (defun org-unescape-code-in-region (beg end)
   "Un-escape lines between BEG and END.
@@ -597,7 +598,7 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
   (interactive "r")
   (save-excursion
     (goto-char end)
-    (while (re-search-backward "^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" beg t)
+    (while (re-search-backward "^[ \t]*,*\\(,\\)\\(?:\\*\\|#\\+\\)" beg t)
       (save-excursion (replace-match "" nil nil nil 1)))))
 
 (defun org-unescape-code-in-string (s)
@@ -605,7 +606,7 @@ with \",*\", \",#+\", \",,*\" and \",,#+\"."
 Un-escaping happens by removing the first comma on lines starting
 with \",*\", \",#+\", \",,*\" and \",,#+\"."
   (replace-regexp-in-string
-   "^[ \t]*,?\\(,\\)\\(?:\\*\\|#\\+\\)" "" s nil nil 1))
+   "^[ \t]*,*\\(,\\)\\(?:\\*\\|#\\+\\)" "" s nil nil 1))
 
 
 

+ 1 - 1
lisp/org-table.el

@@ -3242,7 +3242,7 @@ existing formula for column %s"
 	 (goto-char beg)
 	 ;; Mark named fields untouchable.  Also check if several
 	 ;; field/range formulas try to set the same field.
-	 (remove-text-properties beg end '(org-untouchable t))
+	 (remove-text-properties beg end '(:org-untouchable t))
 	 (let ((current-line (count-lines org-table-current-begin-pos
 					  (line-beginning-position)))
 	       seen-fields)

+ 41 - 28
lisp/org.el

@@ -1284,7 +1284,7 @@ star at the beginning of the headline, you can do this:
 This list will be checked before `org-speed-commands-default'
 when the variable `org-use-speed-commands' is non-nil
 and when the cursor is at the beginning of a headline.
-The car if each entry is a string with a single letter, which must
+The car of each entry is a string with a single letter, which must
 be assigned to `self-insert-command' in the global map.
 The cdr is either a command to be called interactively, a function
 to be called, or a form to be evaluated.
@@ -5290,7 +5290,8 @@ is available.  This option applies only if FILE is a URL."
 	;; Move point to after the url-retrieve header.
 	(search-forward "\n\n" nil :move)
 	;; Search for the success code only in the url-retrieve header.
-	(if (save-excursion (re-search-backward "HTTP.*\\s-+200\\s-OK" nil :noerror))
+	(if (save-excursion
+	      (re-search-backward "HTTP.*\\s-+200\\s-OK" nil :noerror))
 	    ;; Update the cache `org--file-cache' and return contents.
 	    (puthash file
 		     (buffer-substring-no-properties (point) (point-max))
@@ -5300,13 +5301,14 @@ is available.  This option applies only if FILE is a URL."
 		   file))))
      (t
       (with-temp-buffer
-        (condition-case err
+        (condition-case nil
 	    (progn
 	      (insert-file-contents file)
 	      (buffer-string))
 	  (file-error
            (funcall (if noerror #'message #'user-error)
-		    (error-message-string err)))))))))
+		    "Unable to read file %S"
+		    file))))))))
 
 (defun org-extract-log-state-settings (x)
   "Extract the log state setting from a TODO keyword string.
@@ -5750,18 +5752,23 @@ This should be called after the variable `org-link-parameters' has changed."
 	       (verbatim? (member marker '("~" "="))))
 	  (when (save-excursion
 		  (goto-char (match-beginning 0))
-		  ;; Do not match headline stars.  Do not consider
-		  ;; stars of a headline as closing marker for bold
-		  ;; markup either.  Do not match table hlines.
 		  (and
-		   (not (looking-at-p org-outline-regexp-bol))
+		   ;; Do not match headline stars.  Do not consider
+		   ;; stars of a headline as closing marker for bold
+		   ;; markup either.
+		   (not (and (equal marker "*")
+			     (save-excursion
+			       (forward-char)
+			       (skip-chars-backward "*")
+			       (looking-at-p org-outline-regexp-bol))))
+		   ;; Do not match table hlines.
 		   (not (and (equal marker "+")
 			     (org-match-line
 			      "^[ \t]*\\(|[-+]+|?\\|\\+[-+]+\\+\\)[ \t]*$")))
 		   (looking-at (if verbatim? org-verbatim-re org-emph-re))
-		   (not (string-match-p
-			 (concat org-outline-regexp-bol "\\'")
-			 (match-string 0)))))
+		   ;; At a table row, do not cross cell boundaries.
+		   (not (and (save-match-data (org-match-line "[ \t]*|"))
+			     (string-match-p "|" (match-string 4))))))
 	    (pcase-let ((`(,_ ,face ,_) (assoc marker org-emphasis-alist)))
 	      (font-lock-prepend-text-property
 	       (match-beginning 2) (match-end 2) 'face face)
@@ -7945,8 +7952,7 @@ unchecked check box."
     (org-insert-heading (or (and (equal arg '(16)) '(16))
 			    force-heading))
     (save-excursion
-      (org-back-to-heading)
-      (outline-previous-heading)
+      (org-forward-heading-same-level -1)
       (let ((case-fold-search nil)) (looking-at org-todo-line-regexp)))
     (let* ((new-mark-x
 	    (if (or (equal arg '(4))
@@ -9845,7 +9851,9 @@ active region."
 	(car org-stored-links)))))
 
 (defun org-store-link-props (&rest plist)
-  "Store link properties, extract names, addresses and dates."
+  "Store link properties.
+The properties are pre-processed by extracting names, addresses
+and dates."
   (let ((x (plist-get plist :from)))
     (when x
       (let ((adr (mail-extract-address-components x)))
@@ -19327,9 +19335,9 @@ boundaries."
 	    ;; "file:" links.  Also check link abbreviations since
 	    ;; some might expand to "file" links.
 	    (file-types-re (format "[][]\\[\\(?:file\\|[./~]%s\\)"
-				   (and link-abbrevs
-					(format "\\|\\(?:%s:\\)"
-						(regexp-opt link-abbrevs))))))
+				   (if (not link-abbrevs) ""
+				     (format "\\|\\(?:%s:\\)"
+					     (regexp-opt link-abbrevs))))))
        (while (re-search-forward file-types-re end t)
 	 (let ((link (save-match-data (org-element-context))))
 	   ;; Check if we're at an inline image, i.e., an image file
@@ -20782,8 +20790,8 @@ This command does many different things, depending on context:
 	     '(babel-call clock dynamic-block footnote-definition
 			  footnote-reference inline-babel-call inline-src-block
 			  inlinetask item keyword node-property paragraph
-			  plain-list property-drawer radio-target src-block
-			  statistics-cookie table table-cell table-row
+			  plain-list planning property-drawer radio-target
+			  src-block statistics-cookie table table-cell table-row
 			  timestamp)
 	     t))
 	   (type (org-element-type context)))
@@ -20935,7 +20943,8 @@ Use `\\[org-edit-special]' to edit table.el tables"))
 	     (cond (arg (call-interactively #'org-table-recalculate))
 		   ((org-table-maybe-recalculate-line))
 		   (t (org-table-align))))))
-	(`timestamp (org-timestamp-change 0 'day))
+	((or `timestamp (and `planning (guard (org-at-timestamp-p 'lax))))
+	 (org-timestamp-change 0 'day))
 	((and `nil (guard (org-at-heading-p)))
 	 ;; When point is on an unsupported object type, we can miss
 	 ;; the fact that it also is at a heading.  Handle it here.
@@ -21568,7 +21577,9 @@ Your bug report will be posted to the Org mailing list.
 	   ["Cycle through agenda files" org-cycle-agenda-files t]
 	   ["Occur in all agenda files" org-occur-in-agenda-files t]
 	   "--")
-	  (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
+	  (mapcar 'org-file-menu-entry
+		  ;; Prevent initialization from failing.
+		  (ignore-errors (org-agenda-files t)))))))))
 
 ;;;; Documentation
 
@@ -23617,7 +23628,9 @@ depending on context."
 					(skip-chars-forward " \r\t\n"))))
 	    (narrow-to-region (org-element-property :contents-begin element)
 			      contents-end))
-	  (call-interactively #'forward-sentence))))))
+	  ;; End of heading is considered as the end of a sentence.
+	  (let ((sentence-end (concat (sentence-end) "\\|^\\*+ .*$")))
+	    (call-interactively #'forward-sentence)))))))
 
 (define-key org-mode-map "\M-a" 'org-backward-sentence)
 (define-key org-mode-map "\M-e" 'org-forward-sentence)
@@ -24230,10 +24243,11 @@ convenience:
 	(backward-char)
 	(org-backward-paragraph))
        ((<= (point) post-affiliated) (goto-char begin))
+       ;; Special behavior: on a table or a property drawer, move to
+       ;; its beginning.
        ((memq type '(node-property table-row))
 	(goto-char (org-element-property
 		    :post-affiliated (org-element-property :parent element))))
-       ((memq type '(property-drawer table)) (goto-char begin))
        (special?
 	(if (<= (point) contents-begin) (goto-char post-affiliated)
 	  ;; Inside a verse block, see blank lines as paragraph
@@ -24244,8 +24258,7 @@ convenience:
 	      (skip-chars-forward " \r\t\n" origin)
 	      (if (= (point) origin) (goto-char contents-begin)
 		(beginning-of-line))))))
-       ((eq type 'paragraph)
-	(goto-char contents-begin)
+       ((eq type 'paragraph) (goto-char contents-begin)
 	;; When at first paragraph in an item or a footnote definition,
 	;; move directly to beginning of line.
 	(let ((parent-contents
@@ -24253,9 +24266,9 @@ convenience:
 		:contents-begin (org-element-property :parent element))))
 	  (when (and parent-contents (= parent-contents contents-begin))
 	    (beginning-of-line))))
-       ;; At the end of a greater element, move to the beginning of the
-       ;; last element within.
-       ((>= (point) contents-end)
+       ;; At the end of a greater element, move to the beginning of
+       ;; the last element within.
+       ((and contents-end (>= (point) contents-end))
 	(goto-char (1- contents-end))
 	(org-backward-paragraph))
        (t (goto-char (or post-affiliated begin))))

+ 102 - 97
lisp/ox-ascii.el

@@ -177,7 +177,8 @@ Inner margin is applied between each headline."
 
 (defcustom org-ascii-quote-margin 6
   "Width of margin used for quoting text, in characters.
-This margin is applied on both sides of the text."
+This margin is applied on both sides of the text.  It is also
+applied on the left side of contents in descriptive lists."
   :group 'org-export-ascii
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -551,79 +552,69 @@ INFO is a plist used as a communication channel."
     (`inlinetask (plist-get info :ascii-inlinetask-width))
     (`headline
      (- (plist-get info :ascii-text-width)
-	(let ((low-level-rank (org-export-low-level-p element info)))
-	  (if low-level-rank (* low-level-rank 2)
-	    (plist-get info :ascii-global-margin)))))
+        (let ((low-level-rank (org-export-low-level-p element info)))
+          (if low-level-rank (* low-level-rank 2)
+            (plist-get info :ascii-global-margin)))))
     ;; Elements with a relative width: store maximum text width in
     ;; TOTAL-WIDTH.
     (_
      (let* ((genealogy (org-element-lineage element nil t))
-	    ;; Total width is determined by the presence, or not, of an
-	    ;; inline task among ELEMENT parents.
-	    (total-width
-	     (if (cl-some (lambda (parent)
-			    (eq (org-element-type parent) 'inlinetask))
-			  genealogy)
-		 (plist-get info :ascii-inlinetask-width)
-	       ;; No inlinetask: Remove global margin from text width.
-	       (- (plist-get info :ascii-text-width)
-		  (plist-get info :ascii-global-margin)
-		  (let ((parent (org-export-get-parent-headline element)))
-		    ;; Inner margin doesn't apply to text before first
-		    ;; headline.
-		    (if (not parent) 0
-		      (let ((low-level-rank
-			     (org-export-low-level-p parent info)))
-			;; Inner margin doesn't apply to contents of
-			;; low level headlines, since they've got their
-			;; own indentation mechanism.
-			(if low-level-rank (* low-level-rank 2)
-			  (plist-get info :ascii-inner-margin)))))))))
+            ;; Total width is determined by the presence, or not, of an
+            ;; inline task among ELEMENT parents.
+            (total-width
+             (if (cl-some (lambda (parent)
+                            (eq (org-element-type parent) 'inlinetask))
+                          genealogy)
+                 (plist-get info :ascii-inlinetask-width)
+               ;; No inlinetask: Remove global margin from text width.
+               (- (plist-get info :ascii-text-width)
+                  (plist-get info :ascii-global-margin)
+                  (let ((parent (org-export-get-parent-headline element)))
+                    ;; Inner margin doesn't apply to text before first
+                    ;; headline.
+                    (if (not parent) 0
+                      (let ((low-level-rank
+                             (org-export-low-level-p parent info)))
+                        ;; Inner margin doesn't apply to contents of
+                        ;; low level headlines, since they've got their
+                        ;; own indentation mechanism.
+                        (if low-level-rank (* low-level-rank 2)
+                          (plist-get info :ascii-inner-margin)))))))))
        (- total-width
-	  ;; Each `quote-block' and `verse-block' above narrows text
-	  ;; width by twice the standard margin size.
-	  (+ (* (cl-count-if (lambda (parent)
-			       (memq (org-element-type parent)
-				     '(quote-block verse-block)))
-			     genealogy)
-		2
-		(plist-get info :ascii-quote-margin))
-	     ;; Apply list margin once per "top-level" plain-list
-	     ;; containing current line
-	     (* (cl-count-if
-		 (lambda (e)
-		   (and (eq (org-element-type e) 'plain-list)
-			(not (eq (org-element-type (org-export-get-parent e))
-				 'item))))
-		 genealogy)
-		(plist-get info :ascii-list-margin))
-	     ;; Text width within a plain-list is restricted by
-	     ;; indentation of current item.  If that's the case,
-	     ;; compute it with the help of `:structure' property from
-	     ;; parent item, if any.
-	     (let ((item
-		    (if (eq (org-element-type element) 'item) element
-		      (cl-find-if (lambda (parent)
-				    (eq (org-element-type parent) 'item))
-				  genealogy))))
-	       (if (not item) 0
-		 ;; Compute indentation offset of the current item,
-		 ;; that is the sum of the difference between its
-		 ;; indentation and the indentation of the top item in
-		 ;; the list and current item bullet's length.  Also
-		 ;; remove checkbox length, and tag length (for
-		 ;; description lists) or bullet length.
-		 (let ((struct (org-element-property :structure item))
-		       (beg-item (org-element-property :begin item)))
-		   (+ (- (org-list-get-ind beg-item struct)
-			 (org-list-get-ind
-			  (org-list-get-top-point struct) struct))
-		      (string-width (or (org-ascii--checkbox item info)
-					""))
-		      (string-width
-		       (let ((tag (org-element-property :tag item)))
-			 (if tag (org-export-data tag info)
-			   (org-element-property :bullet item))))))))))))))
+          ;; Each `quote-block' and `verse-block' above narrows text
+          ;; width by twice the standard margin size.
+          (+ (* (cl-count-if (lambda (parent)
+                               (memq (org-element-type parent)
+                                     '(quote-block verse-block)))
+                             genealogy)
+                2
+                (plist-get info :ascii-quote-margin))
+             ;; Apply list margin once per "top-level" plain-list
+             ;; containing current line
+             (* (cl-count-if
+                 (lambda (e)
+                   (and (eq (org-element-type e) 'plain-list)
+                        (not (eq (org-element-type (org-export-get-parent e))
+                                 'item))))
+                 genealogy)
+                (plist-get info :ascii-list-margin))
+             ;; Compute indentation offset due to current list.  It is
+	     ;; `org-ascii-quote-margin' per descriptive item in the
+	     ;; genealogy, bullet's length otherwise.
+             (let ((indentation 0))
+               (dolist (e genealogy)
+                 (cond
+                  ((not (eq 'item (org-element-type e))))
+                  ((eq (org-element-property :type (org-export-get-parent e))
+                       'descriptive)
+                   (cl-incf indentation org-ascii-quote-margin))
+                  (t
+                   (cl-incf indentation
+                            (+ (string-width
+                                (or (org-ascii--checkbox e info) ""))
+                               (string-width
+                                (org-element-property :bullet e)))))))
+               indentation)))))))
 
 (defun org-ascii--current-justification (element)
   "Return expected justification for ELEMENT's contents.
@@ -1458,40 +1449,54 @@ contextual information."
 	 (bullet
 	  ;; First parent of ITEM is always the plain-list.  Get
 	  ;; `:type' property from it.
-	  (org-list-bullet-string
-	   (pcase list-type
-	     (`descriptive
-	      (concat checkbox
-		      (org-export-data (org-element-property :tag item) info)
-		      ": "))
-	     (`ordered
-	      ;; Return correct number for ITEM, paying attention to
-	      ;; counters.
-	      (let* ((struct (org-element-property :structure item))
-		     (bul (org-element-property :bullet item))
-		     (num (number-to-string
-			   (car (last (org-list-get-item-number
-				       (org-element-property :begin item)
-				       struct
-				       (org-list-prevs-alist struct)
-				       (org-list-parents-alist struct)))))))
-		(replace-regexp-in-string "[0-9]+" num bul)))
-	     (_ (let ((bul (org-element-property :bullet item)))
-		  ;; Change bullets into more visible form if UTF-8 is active.
-		  (if (not utf8p) bul
+	  (pcase list-type
+	    (`descriptive
+	     (concat checkbox
+		     (org-export-data (org-element-property :tag item)
+				      info)))
+	    (`ordered
+	     ;; Return correct number for ITEM, paying attention to
+	     ;; counters.
+	     (let* ((struct (org-element-property :structure item))
+		    (bul (org-list-bullet-string
+			  (org-element-property :bullet item)))
+		    (num (number-to-string
+			  (car (last (org-list-get-item-number
+				      (org-element-property :begin item)
+				      struct
+				      (org-list-prevs-alist struct)
+				      (org-list-parents-alist struct)))))))
+	       (replace-regexp-in-string "[0-9]+" num bul)))
+	    (_ (let ((bul (org-list-bullet-string
+			   (org-element-property :bullet item))))
+		 ;; Change bullets into more visible form if UTF-8 is active.
+		 (if (not utf8p) bul
+		   (replace-regexp-in-string
+		    "-" "•"
 		    (replace-regexp-in-string
-		     "-" "•"
-		     (replace-regexp-in-string
-		      "+" "⁃"
-		      (replace-regexp-in-string "*" "‣" bul))))))))))
+		     "+" "⁃"
+		     (replace-regexp-in-string "*" "‣" bul))))))))
+	 (indentation (if (eq list-type 'descriptive) org-ascii-quote-margin
+			(string-width bullet))))
     (concat
      bullet
-     (unless (eq list-type 'descriptive) checkbox)
+     checkbox
      ;; Contents: Pay attention to indentation.  Note: check-boxes are
      ;; already taken care of at the paragraph level so they don't
      ;; interfere with indentation.
-     (let ((contents (org-ascii--indent-string contents (string-width bullet))))
-       (if (eq (org-element-type (car (org-element-contents item))) 'paragraph)
+     (let ((contents (org-ascii--indent-string contents indentation)))
+       ;; Determine if contents should follow the bullet or start
+       ;; a new line.  Do the former when the first contributing
+       ;; element to contents is a paragraph.  In descriptive lists
+       ;; however, contents always start a new line.
+       (if (and (not (eq list-type 'descriptive))
+		(org-string-nw-p contents)
+		(eq 'paragraph
+		    (org-element-type
+		     (cl-some (lambda (e)
+				(and (org-string-nw-p (org-export-data e info))
+				     e))
+			      (org-element-contents item)))))
 	   (org-trim contents)
 	 (concat "\n" contents))))))
 

+ 8 - 21
lisp/ox-html.el

@@ -2154,21 +2154,17 @@ CODE is a string representing the source code to colorize.  LANG
 is the language used for CODE, as a string, or nil."
   (when code
     (cond
-     ;; Case 1: No lang.  Possibly an example block.
-     ((not lang)
-      ;; Simple transcoding.
-      (org-html-encode-plain-text code))
-     ;; Case 2: No htmlize or an inferior version of htmlize
+     ;; No language.  Possibly an example block.
+     ((not lang) (org-html-encode-plain-text code))
+     ;; Plain text explicitly set.
+     ((not org-html-htmlize-output-type) (org-html-encode-plain-text code))
+     ;; No htmlize library or an inferior version of htmlize.
      ((not (and (or (require 'htmlize nil t)
-		    (error "Please install htmlize from https://github.com/hniksic/emacs-htmlize"))
+		    (error "Please install htmlize from \
+https://github.com/hniksic/emacs-htmlize"))
 		(fboundp 'htmlize-region-for-paste)))
       ;; Emit a warning.
       (message "Cannot fontify src block (htmlize.el >= 1.34 required)")
-      ;; Simple transcoding.
-      (org-html-encode-plain-text code))
-     ;; Case 3: plain text explicitly set
-     ((not org-html-htmlize-output-type)
-      ;; Simple transcoding.
       (org-html-encode-plain-text code))
      (t
       ;; Map language
@@ -2177,7 +2173,6 @@ is the language used for CODE, as a string, or nil."
 	(cond
 	 ;; Case 1: Language is not associated with any Emacs mode
 	 ((not (functionp lang-mode))
-	  ;; Simple transcoding.
 	  (org-html-encode-plain-text code))
 	 ;; Case 2: Default.  Fontify code.
 	 (t
@@ -2328,15 +2323,7 @@ INFO is a plist used as a communication channel."
 			(org-element-property :priority headline)))
 	 (text (org-export-data-with-backend
 		(org-export-get-alt-title headline info)
-		;; Create an anonymous back-end that will ignore any
-		;; footnote-reference, link, radio-target and target
-		;; in table of contents.
-		(org-export-create-backend
-		 :parent 'html
-		 :transcoders '((footnote-reference . ignore)
-				(link . (lambda (object c i) c))
-				(radio-target . (lambda (object c i) c))
-				(target . ignore)))
+		(org-export-toc-entry-backend 'html)
 		info))
 	 (tags (and (eq (plist-get info :with-tags) t)
 		    (org-export-get-tags headline info))))

+ 11 - 9
lisp/ox-man.el

@@ -285,6 +285,10 @@ This function shouldn't be used for floats.  See
         output
       (concat (format "%s\n.br\n" label) output))))
 
+(defun org-man--protect-text (text)
+  "Protect minus and backslash characters in string TEXT."
+  (replace-regexp-in-string "-" "\\-" text nil t))
+
 
 
 ;;; Template
@@ -350,10 +354,9 @@ holding contextual information."
 ;;; Code
 
 (defun org-man-code (code _contents _info)
-  "Transcode a CODE object from Org to Man.
-CONTENTS is nil.  INFO is a plist used as a communication
-channel."
-  (format "\\fC%s\\fP" code))
+  "Transcode a CODE object from Org to Man."
+  (format "\\fC%s\\fP"
+	  (org-man--protect-text (org-element-property :value code))))
 
 
 ;;; Drawer
@@ -1029,11 +1032,10 @@ holding contextual information."
 
 ;;; Verbatim
 
-(defun org-man-verbatim (_verbatim contents _info)
-  "Transcode a VERBATIM object from Org to Man.
-CONTENTS is nil.  INFO is a plist used as a communication
-channel."
-  (format ".nf\n%s\n.fi" contents))
+(defun org-man-verbatim (verbatim _contents _info)
+  "Transcode a VERBATIM object from Org to Man."
+  (format "\\fI%s\\fP"
+	  (org-man--protect-text (org-element-property :value verbatim))))
 
 
 ;;; Verse Block

+ 2 - 11
lisp/ox-md.el

@@ -240,7 +240,7 @@ a communication channel."
 		    (format "<a id=\"%s\"></a>"
 			    (or (org-element-property :CUSTOM_ID headline)
 				(org-export-get-reference headline info))))))
-	  (concat (org-md--headline-title style level title anchor tags)
+	  (concat (org-md--headline-title style level heading anchor tags)
 		  contents)))))))
 
 
@@ -582,16 +582,7 @@ contents according to the current headline."
 	      (format "[%s](#%s)"
 		      (org-export-data-with-backend
 		       (org-export-get-alt-title headline info)
-		       ;; Create an anonymous back-end that will
-		       ;; ignore any footnote-reference, link,
-		       ;; radio-target and target in table of
-		       ;; contents.
-		       (org-export-create-backend
-			:parent 'md
-			:transcoders '((footnote-reference . ignore)
-				       (link . (lambda (object c i) c))
-				       (radio-target . (lambda (object c i) c))
-				       (target . ignore)))
+		       (org-export-toc-entry-backend 'md)
 		       info)
 		      (or (org-element-property :CUSTOM_ID headline)
 			  (org-export-get-reference headline info))))

+ 2 - 6
lisp/ox-odt.el

@@ -1159,12 +1159,8 @@ table of contents as a string, or nil."
   ;; Likewise, links, footnote references and regular targets are also
   ;; suppressed.
   (let* ((headlines (org-export-collect-headlines info depth scope))
-	 (backend (org-export-create-backend
-		   :parent (org-export-backend-name (plist-get info :back-end))
-		   :transcoders '((footnote-reference . ignore)
-				  (link . (lambda (object c i) c))
-				  (radio-target . (lambda (object c i) c))
-				  (target . ignore)))))
+	 (backend (org-export-toc-entry-backend
+		      (org-export-backend-name (plist-get info :back-end)))))
     (when headlines
       (org-odt--format-toc
        (and (not scope) (org-export-translate "Table of Contents" :utf-8 info))

+ 52 - 44
lisp/ox-texinfo.el

@@ -83,7 +83,8 @@
   :filters-alist
   '((:filter-headline . org-texinfo--filter-section-blank-lines)
     (:filter-parse-tree . org-texinfo--normalize-headlines)
-    (:filter-section . org-texinfo--filter-section-blank-lines))
+    (:filter-section . org-texinfo--filter-section-blank-lines)
+    (:filter-final-output . org-texinfo--untabify))
   :menu-entry
   '(?i "Export to Texinfo"
        ((?t "As TEXI file" org-texinfo-export-to-texinfo)
@@ -405,6 +406,10 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" and
 
 ;;; Internal Functions
 
+(defun org-texinfo--untabify (s _backend _info)
+  "Remove TAB characters in string S."
+  (replace-regexp-in-string "\t" (make-string tab-width ?\s) s))
+
 (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
   "Filter controlling number of blank lines after a section."
   (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline))
@@ -499,8 +504,12 @@ export state, as a plist."
    (org-export-create-backend
     :parent 'texinfo
     :transcoders '((footnote-reference . ignore)
-		   (link . (lambda (object c i) c))
-		   (radio-target . (lambda (object c i) c))
+		   (link . (lambda (l c i)
+			     (or c
+				 (org-export-data
+				  (org-element-property :raw-link l)
+				  i))))
+		   (radio-target . (lambda (_r c _i) c))
 		   (target . ignore)))
    info))
 
@@ -519,18 +528,27 @@ strings (e.g., returned by `org-export-get-caption')."
   (let* ((backend
 	  (org-export-create-backend
 	   :parent 'texinfo
-	   :transcoders '((link . (lambda (object c i) c))
-			  (radio-target . (lambda (object c i) c))
+	   :transcoders '((link . (lambda (l c i)
+				    (or c
+					(org-export-data
+					 (org-element-property :raw-link l)
+					 i))))
+			  (radio-target . (lambda (_r c _i) c))
 			  (target . ignore))))
 	 (short-backend
 	  (org-export-create-backend
 	   :parent 'texinfo
-	   :transcoders '((footnote-reference . ignore)
-			  (inline-src-block . ignore)
-			  (link . (lambda (object c i) c))
-			  (radio-target . (lambda (object c i) c))
-			  (target . ignore)
-			  (verbatim . ignore))))
+	   :transcoders
+	   '((footnote-reference . ignore)
+	     (inline-src-block . ignore)
+	     (link . (lambda (l c i)
+		       (or c
+			   (org-export-data
+			    (org-element-property :raw-link l)
+			    i))))
+	     (radio-target . (lambda (_r c _i) c))
+	     (target . ignore)
+	     (verbatim . ignore))))
 	 (short-str
 	  (if (and short caption)
 	      (format "@shortcaption{%s}\n"
@@ -1017,15 +1035,17 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 
 (defun org-texinfo--@ref (datum description info)
   "Return @ref command for element or object DATUM.
-DESCRIPTION is the name of the section to print, as a string."
+DESCRIPTION is the printed name of the section, as a string, or
+nil."
   (let ((node-name (org-texinfo--get-node datum info))
 	;; Sanitize DESCRIPTION for cross-reference use.  In
-	;; particular, remove colons as they seem to cause (even
-	;; within @asis{...} to the Texinfo reader.
-	(title (replace-regexp-in-string
-		"[ \t]*:+" ""
-		(replace-regexp-in-string "," "@comma{}" description))))
-    (if (equal title node-name)
+	;; particular, remove colons as they seem to cause pain (even
+	;; within @asis{...}) to the Texinfo reader.
+	(title (and description
+		    (replace-regexp-in-string
+		     "[ \t]*:+" ""
+		     (replace-regexp-in-string "," "@comma{}" description)))))
+    (if (or (not title) (equal title node-name))
 	(format "@ref{%s}" node-name)
       (format "@ref{%s, , %s}" node-name title))))
 
@@ -1073,20 +1093,8 @@ INFO is a plist holding contextual information.  See
 			       (org-element-type
 				(org-element-property :parent destination))))))
 	   (let ((headline (org-element-lineage destination '(headline) t)))
-	     (org-texinfo--@ref
-	      headline
-	      (or desc (org-texinfo--sanitize-title
-			(org-element-property :title headline) info))
-	      info)))
-	  (_
-	   (org-texinfo--@ref
-	    destination
-	    (or desc
-		(pcase (org-export-get-ordinal destination info)
-		  ((and (pred integerp) n) (number-to-string n))
-		  ((and (pred consp) n) (mapconcat #'number-to-string n "."))
-		  (_ "???")))		;cannot guess the description
-	    info)))))
+	     (org-texinfo--@ref headline desc info)))
+	  (_ (org-texinfo--@ref destination desc info)))))
      ((string= type "mailto")
       (format "@email{%s}"
 	      (concat (org-texinfo--sanitize-content path)
@@ -1167,19 +1175,19 @@ is an integer, build the menu recursively, down to this depth."
   (cond
    ((not level)
     (org-texinfo--format-entries (org-texinfo--menu-entries scope info) info))
-   ((zerop level) nil)
+   ((zerop level) "\n")
    (t
-    (org-element-normalize-string
-     (mapconcat
-      (lambda (h)
-	(let ((entries (org-texinfo--menu-entries h info)))
-	  (when entries
-	    (concat
-	     (format "%s\n\n%s\n"
-		     (org-export-data (org-export-get-alt-title h info) info)
-		     (org-texinfo--format-entries entries info))
-	     (org-texinfo--build-menu h info (1- level))))))
-      (org-texinfo--menu-entries scope info) "\n")))))
+    (mapconcat
+     (lambda (h)
+       (let ((entries (org-texinfo--menu-entries h info)))
+	 (when entries
+	   (concat
+	    (format "%s\n\n%s\n"
+		    (org-export-data (org-export-get-alt-title h info) info)
+		    (org-texinfo--format-entries entries info))
+	    (org-texinfo--build-menu h info (1- level))))))
+     (org-texinfo--menu-entries scope info)
+     ""))))
 
 (defun org-texinfo--format-entries (entries info)
   "Format all direct menu entries in SCOPE, as a string.

+ 48 - 2
lisp/ox.el

@@ -5176,7 +5176,7 @@ return nil."
       info 'first-match)))
 
 
-;;;; For Tables Of Contents
+;;;; For Tables of Contents
 ;;
 ;; `org-export-collect-headlines' builds a list of all exportable
 ;; headline elements, maybe limited to a certain depth.  One can then
@@ -5186,6 +5186,9 @@ return nil."
 ;; Once the generic function `org-export-collect-elements' is defined,
 ;; `org-export-collect-tables', `org-export-collect-figures' and
 ;; `org-export-collect-listings' can be derived from it.
+;;
+;; `org-export-toc-entry-backend' builds a special anonymous back-end
+;; useful to export table of contents' entries.
 
 (defun org-export-collect-headlines (info &optional n scope)
   "Collect headlines in order to build a table of contents.
@@ -5271,6 +5274,32 @@ INFO is a plist used as a communication channel.
 Return a list of src-block elements with a caption."
   (org-export-collect-elements 'src-block info))
 
+(defun org-export-toc-entry-backend (parent &rest transcoders)
+  "Return an export back-end appropriate for table of contents entries.
+
+PARENT is an export back-end the returned back-end should inherit
+from.
+
+By default, the back-end removes footnote references and targets.
+It also changes links and radio targets into regular text.
+TRANSCODERS optional argument, when non-nil, specifies additional
+transcoders.  A transcoder follows the pattern (TYPE . FUNCTION)
+where type is an element or object type and FUNCTION the function
+transcoding it."
+  (declare (indent 1))
+  (org-export-create-backend
+   :parent parent
+   :transcoders
+   (append transcoders
+	   `((footnote-reference . ,#'ignore)
+	     (link . ,(lambda (l c i)
+			(or c
+			    (org-export-data
+			     (org-element-property :raw-link l)
+			     i))))
+	     (radio-target . ,(lambda (_r c _) c))
+	     (target . ,#'ignore)))))
+
 
 ;;;; Smart Quotes
 ;;
@@ -5657,6 +5686,7 @@ them."
      ("zh-TW" :html "&#20316;&#32773;" :utf-8 "作者"))
     ("Continued from previous page"
      ("ar" :default "تتمة الصفحة السابقة")
+     ("cs" :default "Pokračování z předchozí strany")
      ("de" :default "Fortsetzung von vorheriger Seite")
      ("es" :html "Contin&uacute;a de la p&aacute;gina anterior" :ascii "Continua de la pagina anterior" :default "Continúa de la página anterior")
      ("fr" :default "Suite de la page précédente")
@@ -5669,6 +5699,7 @@ them."
      ("sl" :default "Nadaljevanje s prejšnje strani"))
     ("Continued on next page"
      ("ar" :default "التتمة في الصفحة التالية")
+     ("cs" :default "Pokračuje na další stránce")
      ("de" :default "Fortsetzung nächste Seite")
      ("es" :html "Contin&uacute;a en la siguiente p&aacute;gina" :ascii "Continua en la siguiente pagina" :default "Continúa en la siguiente página")
      ("fr" :default "Suite page suivante")
@@ -5680,6 +5711,7 @@ them."
       :utf-8 "(Продолжение следует)")
      ("sl" :default "Nadaljevanje na naslednji strani"))
     ("Created"
+     ("cs" :default "Vytvořeno")
      ("sl" :default "Ustvarjeno"))
     ("Date"
      ("ar" :default "بتاريخ")
@@ -5709,6 +5741,7 @@ them."
      ("zh-TW" :html "&#26085;&#26399;" :utf-8 "日期"))
     ("Equation"
      ("ar" :default "معادلة")
+     ("cs" :default "Rovnice")
      ("da" :default "Ligning")
      ("de" :default "Gleichung")
      ("es" :ascii "Ecuacion" :html "Ecuaci&oacute;n" :default "Ecuación")
@@ -5727,6 +5760,7 @@ them."
      ("zh-CN" :html "&#26041;&#31243;" :utf-8 "方程"))
     ("Figure"
      ("ar" :default "شكل")
+     ("cs" :default "Obrázek")
      ("da" :default "Figur")
      ("de" :default "Abbildung")
      ("es" :default "Figura")
@@ -5742,6 +5776,7 @@ them."
      ("zh-CN" :html "&#22270;" :utf-8 "图"))
     ("Figure %d:"
      ("ar" :default "شكل %d:")
+     ("cs" :default "Obrázek %d:")
      ("da" :default "Figur %d")
      ("de" :default "Abbildung %d:")
      ("es" :default "Figura %d:")
@@ -5760,7 +5795,7 @@ them."
     ("Footnotes"
      ("ar" :default "الهوامش")
      ("ca" :html "Peus de p&agrave;gina")
-     ("cs" :default "Pozn\xe1mky pod carou")
+     ("cs" :default "Poznámky pod čarou")
      ("da" :default "Fodnoter")
      ("de" :html "Fu&szlig;noten" :default "Fußnoten")
      ("eo" :default "Piednotoj")
@@ -5787,6 +5822,7 @@ them."
      ("zh-TW" :html "&#33139;&#35387;" :utf-8 "腳註"))
     ("List of Listings"
      ("ar" :default "قائمة بالبرامج")
+     ("cs" :default "Seznam programů")
      ("da" :default "Programmer")
      ("de" :default "Programmauflistungsverzeichnis")
      ("es" :ascii "Indice de Listados de programas" :html "&Iacute;ndice de Listados de programas" :default "Índice de Listados de programas")
@@ -5801,6 +5837,7 @@ them."
      ("zh-CN" :html "&#20195;&#30721;&#30446;&#24405;" :utf-8 "代码目录"))
     ("List of Tables"
      ("ar" :default "قائمة بالجداول")
+     ("cs" :default "Seznam tabulek")
      ("da" :default "Tabeller")
      ("de" :default "Tabellenverzeichnis")
      ("es" :ascii "Indice de tablas" :html "&Iacute;ndice de tablas" :default "Índice de tablas")
@@ -5819,6 +5856,7 @@ them."
      ("zh-CN" :html "&#34920;&#26684;&#30446;&#24405;" :utf-8 "表格目录"))
     ("Listing"
      ("ar" :default "برنامج")
+     ("cs" :default "Program")
      ("da" :default "Program")
      ("de" :default "Programmlisting")
      ("es" :default "Listado de programa")
@@ -5834,6 +5872,7 @@ them."
      ("zh-CN" :html "&#20195;&#30721;" :utf-8 "代码"))
     ("Listing %d:"
      ("ar" :default "برنامج %d:")
+     ("cs" :default "Program %d:")
      ("da" :default "Program %d")
      ("de" :default "Programmlisting %d")
      ("es" :default "Listado de programa %d")
@@ -5849,20 +5888,24 @@ them."
      ("zh-CN" :html "&#20195;&#30721;%d&nbsp;" :utf-8 "代码%d "))
     ("References"
      ("ar" :default "المراجع")
+     ("cs" :default "Reference")
      ("fr" :ascii "References" :default "Références")
      ("de" :default "Quellen")
      ("es" :default "Referencias")
      ("sl" :default "Reference"))
     ("See figure %s"
+     ("cs" :default "Viz obrázek %s")
      ("fr" :default "cf. figure %s"
       :html "cf.&nbsp;figure&nbsp;%s" :latex "cf.~figure~%s")
      ("sl" :default "Glej sliko %s"))
     ("See listing %s"
+     ("cs" :default "Viz program %s")
      ("fr" :default "cf. programme %s"
       :html "cf.&nbsp;programme&nbsp;%s" :latex "cf.~programme~%s")
      ("sl" :default "Glej izpis programa %s"))
     ("See section %s"
      ("ar" :default "انظر قسم %s")
+     ("cs" :default "Viz sekce %s")
      ("da" :default "jævnfør afsnit %s")
      ("de" :default "siehe Abschnitt %s")
      ("es" :ascii "Vea seccion %s" :html "Vea secci&oacute;n %s" :default "Vea sección %s")
@@ -5876,11 +5919,13 @@ them."
      ("sl" :default "Glej poglavje %d")
      ("zh-CN" :html "&#21442;&#35265;&#31532;%s&#33410;" :utf-8 "参见第%s节"))
     ("See table %s"
+     ("cs" :default "Viz tabulka %s")
      ("fr" :default "cf. tableau %s"
       :html "cf.&nbsp;tableau&nbsp;%s" :latex "cf.~tableau~%s")
      ("sl" :default "Glej tabelo %s"))
     ("Table"
      ("ar" :default "جدول")
+     ("cs" :default "Tabulka")
      ("de" :default "Tabelle")
      ("es" :default "Tabla")
      ("et" :default "Tabel")
@@ -5893,6 +5938,7 @@ them."
      ("zh-CN" :html "&#34920;" :utf-8 "表"))
     ("Table %d:"
      ("ar" :default "جدول %d:")
+     ("cs" :default "Tabulka %d:")
      ("da" :default "Tabel %d")
      ("de" :default "Tabelle %d")
      ("es" :default "Tabla %d")

+ 25 - 0
testing/lisp/test-ob-tangle.el

@@ -197,6 +197,31 @@ another block
           (org-babel-tangle-jump-to-org)
           (buffer-string)))))))
 
+(ert-deftest ob-tangle/nested-block ()
+  "Test tangling of org file with nested block."
+  (should
+   (string=
+    "#+begin_src org
+,#+begin_src emacs-lisp
+1
+,#+end_src
+#+end_src
+"
+    (org-test-with-temp-text-in-file
+        "#+header: :tangle \"test-ob-tangle.org\"
+#+begin_src org
+,#+begin_src org
+,,#+begin_src emacs-lisp
+1
+,,#+end_src
+,#+end_src
+#+end_src"
+      (unwind-protect
+          (progn (org-babel-tangle)
+                 (with-temp-buffer (insert-file-contents "test-ob-tangle.org")
+                                   (buffer-string)))
+        (delete-file "test-ob-tangle.org"))))))
+
 (provide 'test-ob-tangle)
 
 ;;; test-ob-tangle.el ends here

+ 16 - 0
testing/lisp/test-org-capture.el

@@ -146,5 +146,21 @@
 	     (list file1 file2 (buffer-file-name)))))))))
 
 
+(ert-deftest test-org-capture/insert-at-end-abort ()
+  "Test that capture can be aborted after inserting at end of capture buffer."
+  (should
+   (equal
+    "* A\n* B\n"
+    (org-test-with-temp-text-in-file "* A\n* B\n"
+      (let* ((file (buffer-file-name))
+	     (org-capture-templates
+	      `(("t" "Todo" entry (file+headline ,file "A") "** H1 %?"))))
+	(org-capture nil "t")
+	(goto-char (point-max))
+	(insert "Capture text")
+	(org-capture-kill))
+      (buffer-string)))))
+
+
 (provide 'test-org-capture)
 ;;; test-org-capture.el ends here

+ 105 - 0
testing/lisp/test-org-clock.el

@@ -828,5 +828,110 @@ CLOCK: [2016-12-28 Wed 11:09]--[2016-12-28 Wed 11:09] =>  0:00
 CLOCK: [2016-12-28 Wed 13:09]--[2016-12-28 Wed 13:09] =>  0:00"
             (test-org-clock-clocktable-contents ":tcolumns 2")))))
 
+(ert-deftest test-org-clock/clocktable/step ()
+  "Test \":step\" parameter in Clock table."
+  ;; Regression test: week crossing month boundary before :wstart
+  ;; day-of-week.
+  (should
+   (equal "
+Weekly report starting on: [2017-09-25 Mon]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *1:00* |
+|--------------+--------|
+| Foo          | 1:00   |"
+    (org-test-with-temp-text
+	"* Foo
+CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] =>  1:00
+CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] =>  2:00
+CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] =>  3:00"
+      (let ((system-time-locale "en_US"))
+	(test-org-clock-clocktable-contents
+	    ":step week :block 2017-09 :stepskip0 t")))))
+  (should
+   (equal "
+Weekly report starting on: [2017-10-01 Sun]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *2:00* |
+|--------------+--------|
+| Foo          | 2:00   |
+
+Weekly report starting on: [2017-10-02 Mon]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *7:00* |
+|--------------+--------|
+| Foo          | 7:00   |
+
+Weekly report starting on: [2017-10-09 Mon]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *5:00* |
+|--------------+--------|
+| Foo          | 5:00   |
+"
+	  (org-test-with-temp-text
+	      "* Foo
+CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] =>  1:00
+CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] =>  2:00
+CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] =>  3:00
+CLOCK: [2017-10-08 Sun 09:00]--[2017-10-08 Sun 13:00] =>  4:00
+CLOCK: [2017-10-09 Mon 09:00]--[2017-10-09 Mon 14:00] =>  5:00"
+	    (let ((system-time-locale "en_US"))
+	      (test-org-clock-clocktable-contents
+		  ":step week :block 2017-10 :stepskip0 t")))))
+  ;; :step day
+  (should
+   (equal "
+Daily report: [2017-10-02 Mon]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *3:00* |
+|--------------+--------|
+| Foo          | 3:00   |
+
+Daily report: [2017-10-03 Tue]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *0:00* |
+
+Daily report: [2017-10-04 Wed]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *0:00* |
+
+Daily report: [2017-10-05 Thu]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *0:00* |
+
+Daily report: [2017-10-06 Fri]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *0:00* |
+
+Daily report: [2017-10-07 Sat]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *0:00* |
+
+Daily report: [2017-10-08 Sun]
+| Headline     | Time   |
+|--------------+--------|
+| *Total time* | *4:00* |
+|--------------+--------|
+| Foo          | 4:00   |"
+	  (org-test-with-temp-text
+	      "* Foo
+CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] =>  1:00
+CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] =>  2:00
+CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] =>  3:00
+CLOCK: [2017-10-08 Sun 09:00]--[2017-10-08 Sun 13:00] =>  4:00
+CLOCK: [2017-10-09 Mon 09:00]--[2017-10-09 Mon 14:00] =>  5:00"
+	    (let ((system-time-locale "en_US"))
+	      (test-org-clock-clocktable-contents
+		  ":step day :block 2017-W40"))))))
+
 (provide 'test-org-clock)
 ;;; test-org-clock.el end here

+ 24 - 4
testing/lisp/test-org-element.el

@@ -1444,9 +1444,19 @@ DEADLINE: <2012-03-29 thu.>"
 	      'org-element-contents))))
   ;; Block in an item: ignore indentation within the block.
   (should
-   (org-test-with-temp-text "- item\n  #+begin_src emacs-lisp\n(+ 1 1)\n  #+end_src"
-     (forward-char)
-     (= (org-element-property :end (org-element-at-point)) (point-max)))))
+   (org-test-with-temp-text
+       "-<point> item\n  #+begin_src emacs-lisp\n(+ 1 1)\n  #+end_src"
+     (= (org-element-property :end (org-element-at-point)) (point-max))))
+  ;; Last item in a list or sub-list has no `:post-blank' lines, since
+  ;; those belong to the plain-list.
+  (should
+   (= 0
+      (org-test-with-temp-text "- A\n\n- <point>B\n\nEnd list"
+	(org-element-property :post-blank (org-element-at-point)))))
+  (should
+   (= 0
+      (org-test-with-temp-text "- A\n\n  - B\n\n<point>  - C\n\n  End sub-list"
+	(org-element-property :post-blank (org-element-at-point))))))
 
 
 ;;;; Keyword
@@ -1962,7 +1972,17 @@ e^{i\\pi}+1=0
   "Test `plain-list' parser."
   (org-test-with-temp-text "- item"
     (should (org-element-map (org-element-parse-buffer) 'plain-list 'identity)))
-  ;; Blank lines after the list only belong to outer plain list.
+  ;; Blank lines after a list or sub-list belongs to that list.
+  (should
+   (= 1
+      (org-test-with-temp-text "- A\n\n- B\n\nEnd list"
+	(org-element-property :post-blank (org-element-at-point)))))
+  (should
+   (= 1
+      (org-test-with-temp-text "- A\n\n<point>  - B\n\n  - C\n\n  End sub-list"
+	(org-element-property :post-blank (org-element-at-point)))))
+  ;; Blank lines after the list only belong to outer plain list,
+  ;; however.
   (should
    (equal
     '(t t)

+ 7 - 1
testing/lisp/test-org-macs.el

@@ -68,7 +68,13 @@
    (eq 'foo
        (get-text-property 1 'face
 			  (org-string-display
-			   #("123" 1 2 (display "abc" face foo)))))))
+			   #("123" 1 2 (display "abc" face foo))))))
+  ;; Also preserve `display' property in original string.
+  (should
+   (equal "abc"
+	  (let ((s #("123" 1 2 (display "abc" face foo))))
+	    (org-string-display s)
+	    (get-text-property 1 'display s)))))
 
 
 (provide 'test-org-macs)

+ 38 - 0
testing/lisp/test-org-src.el

@@ -443,5 +443,43 @@ This is a tab:\t.
 	 (org-edit-special)
 	 (prog1 foo (org-edit-src-exit))))))
 
+;;; Code escaping
+
+(ert-deftest test-org-src/escape-code-in-string ()
+  "Test `org-escape-code-in-string' specifications."
+  ;; Escape lines starting with "*" or "#+".
+  (should (equal ",*" (org-escape-code-in-string "*")))
+  (should (equal ",#+" (org-escape-code-in-string "#+")))
+  ;; Escape lines starting with ",*" and ",#+".  Number of leading
+  ;; commas does not matter.
+  (should (equal ",,*" (org-escape-code-in-string ",*")))
+  (should (equal ",,#+" (org-escape-code-in-string ",#+")))
+  (should (equal ",,,*" (org-escape-code-in-string ",,*")))
+  (should (equal ",,,#+" (org-escape-code-in-string ",,#+")))
+  ;; Indentation does not matter.
+  (should (equal " ,*" (org-escape-code-in-string " *")))
+  (should (equal " ,#+" (org-escape-code-in-string " #+")))
+  ;; Do nothing on other cases.
+  (should (equal "a" (org-escape-code-in-string "a")))
+  (should (equal "#" (org-escape-code-in-string "#")))
+  (should (equal "," (org-escape-code-in-string ","))))
+
+(ert-deftest test-org-src/unescape-code-in-string ()
+  "Test `org-unescape-code-in-string' specifications."
+  ;; Unescape lines starting with ",*" or ",#+".  Number of leading
+  ;; commas does not matter.
+  (should (equal "*" (org-unescape-code-in-string ",*")))
+  (should (equal "#+" (org-unescape-code-in-string ",#+")))
+  (should (equal ",*" (org-unescape-code-in-string ",,*")))
+  (should (equal ",#+" (org-unescape-code-in-string ",,#+")))
+  ;; Indentation does not matter.
+  (should (equal " *" (org-unescape-code-in-string " ,*")))
+  (should (equal " #+" (org-unescape-code-in-string " ,#+")))
+  ;; Do nothing on other cases.
+  (should (equal "a" (org-unescape-code-in-string "a")))
+  (should (equal "#" (org-unescape-code-in-string "#")))
+  (should (equal "," (org-unescape-code-in-string ","))))
+
+
 (provide 'test-org-src)
 ;;; test-org-src.el ends here

+ 21 - 0
testing/lisp/test-org-table.el

@@ -1906,6 +1906,27 @@ is t, then new columns should be added as needed"
       (org-table-calc-current-TBLFM)
       (buffer-string)))))
 
+(ert-deftest test-org-table/formula-priority ()
+  "Test field formula priority over column formula."
+  ;; Field formulas bind stronger than column formulas.
+  (should
+   (equal
+    "| 1 |  3 |\n| 2 | 99 |\n"
+    (org-test-with-temp-text
+	"| 1 |   |\n| 2 |   |\n<point>#+tblfm: $2=3*$1::@2$2=99"
+      (org-table-calc-current-TBLFM)
+      (buffer-substring-no-properties (point-min) (point)))))
+  ;; When field formula is removed, table formulas is applied again.
+  (should
+   (equal
+    "| 1 | 3 |\n| 2 | 6 |\n"
+    (org-test-with-temp-text
+	"| 1 |   |\n| 2 |   |\n#+tblfm: $2=3*$1<point>::@2$2=99"
+      (org-table-calc-current-TBLFM)
+      (delete-region (point) (line-end-position))
+      (org-table-calc-current-TBLFM)
+      (buffer-substring-no-properties (point-min) (line-beginning-position))))))
+
 (ert-deftest test-org-table/tab-indent ()
   "Test named fields with tab indentation."
   (should

+ 19 - 3
testing/lisp/test-org.el

@@ -1416,6 +1416,13 @@
     (org-test-with-temp-text "* H\n- an item\n- another one"
       (search-forward "an ")
       (org-insert-todo-heading-respect-content)
+      (buffer-substring-no-properties (line-beginning-position) (point-max)))))
+  ;; Use the same TODO keyword as current heading.
+  (should
+   (equal
+    "* TODO \n"
+    (org-test-with-temp-text "* TODO\n** WAITING\n"
+      (org-insert-todo-heading-respect-content)
       (buffer-substring-no-properties (line-beginning-position) (point-max))))))
 
 (ert-deftest test-org/clone-with-time-shift ()
@@ -3414,8 +3421,8 @@ SCHEDULED: <2017-05-06 Sat>
    (org-test-with-temp-text "Paragraph 1.<point>\n\nParagraph 2."
      (org-forward-sentence)
      (eobp)))
-  ;; On a headline, stop at the end of the line, unless point is
-  ;; already there.
+  ;; Headlines are considered to be sentences by themselves, even if
+  ;; they do not end with a full stop.
   (should
    (equal
     "* Headline"
@@ -3425,7 +3432,11 @@ SCHEDULED: <2017-05-06 Sat>
   (should
    (org-test-with-temp-text "* Headline<point>\nSentence."
      (org-forward-sentence)
-     (eobp))))
+     (eobp)))
+  (should
+   (org-test-with-temp-text "Sentence.<point>\n\n* Headline\n\nSentence 2."
+     (org-forward-sentence)
+     (and (org-at-heading-p) (eolp)))))
 
 (ert-deftest test-org/backward-sentence ()
   "Test `org-backward-sentence' specifications."
@@ -3607,6 +3618,11 @@ SCHEDULED: <2017-05-06 Sat>
   (should
    (org-test-with-temp-text "#+BEGIN_<point>EXAMPLE\nL1\n#+END_EXAMPLE"
      (org-backward-paragraph)
+     (bobp)))
+  ;; Pathological case: on an empty heading, move to its beginning.
+  (should
+   (org-test-with-temp-text "* <point>H"
+     (org-backward-paragraph)
      (bobp))))
 
 (ert-deftest test-org/forward-element ()

+ 70 - 0
testing/lisp/test-ox.el

@@ -4320,6 +4320,76 @@ Another text. (ref:text)
 	(let ((scope (org-element-map tree 'headline #'identity info t)))
 	  (length (org-export-collect-headlines info 1 scope)))))))
 
+(ert-deftest test-org-export/toc-entry-backend ()
+  "Test `org-export-toc-entry-backend' specifications."
+  ;; Ignore targets.
+  (should
+   (equal "H \n"
+	  (org-test-with-temp-text "* H <<target>>"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test)
+					   i)))))
+	      (org-export-as 'test)))))
+  ;; Ignore footnote references.
+  (should
+   (equal "H \n"
+	  (org-test-with-temp-text "[fn:1] Definition\n* H [fn:1]"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test)
+					   i)))))
+	      (org-export-as 'test)))))
+  ;; Replace plain links with contents, or with path.
+  (should
+   (equal "H Org mode\n"
+	  (org-test-with-temp-text "* H [[http://orgmode.org][Org mode]]"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test)
+					   i)))))
+	      (org-export-as 'test)))))
+  (should
+   (equal "H http://orgmode.org\n"
+	  (org-test-with-temp-text "* H [[http://orgmode.org]]"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test)
+					   i)))))
+	      (org-export-as 'test)))))
+  ;; Replace radio targets with contents.
+  (should
+   (equal "H radio\n"
+	  (org-test-with-temp-text "* H <<<radio>>>"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test)
+					   i)))))
+	      (org-export-as 'test)))))
+  ;; With optional argument TRANSCODERS, specify other
+  ;; transformations.
+  (should
+   (equal "H bold\n"
+	  (org-test-with-temp-text "* H *bold*"
+	    (let (org-export-registered-backends)
+	      (org-export-define-backend 'test
+		'((headline . (lambda (h _c i) (org-export-data-with-backend
+					   (org-element-property :title h)
+					   (org-export-toc-entry-backend 'test
+					     '(bold . (lambda (_b c _i) c)))
+					   i)))))
+	      (org-export-as 'test))))))
+
 
 
 ;;; Templates