Browse Source

ox: Add #+SUBTITLE property in some backends

* ox-texinfo.el (texinfo, org-texinfo-template): Parse subtitle.
* ox-s5.el (org-s5-title-slide-template):
* ox-deck.el (org-deck-title-slide-template):
* ox-odt.el (odt, org-odt-template):
* ox-latex.el (latex, org-latex-template):
* ox-html.el (html, org-html-format-spec, org-html-template):
* ox-ascii.el (ascii, org-ascii-template--document-title):
* ox-beamer.el (beamer, org-beamer-template): Support #+SUBTITLE.
* ox-html.el (org-html-postamble-format)
(org-html-preamble-format):
* ox-latex.el (org-latex-title-command)
(org-latex-hyperref-template): Update docstring.
* ox-html.el (org-html-style-default): New .subtitle css property.
* ox-beamer.el (org-beamer-subtitle-format):
* ox-latex.el (org-latex-subtitle-format)
(org-latex-subtitle-separate): New variable.
* org.texi (ASCII/Latin-1/UTF-8 export)
(Beamer specific export settings)
(HTML Specific export settings)
(@LaTeX{} specific export settings, CSS support)
(ODT specific export settings)
(Texinfo specific export settings, Document preamble)
(Publishing options, Publishing options): Document #+SUBTITLE.

The patch adds a #+SUBTITLE keyword to ox-ascii, ox-latex, ox-html and
ox-odt.
Rasmus 10 years ago
parent
commit
a780080fcf
10 changed files with 175 additions and 23 deletions
  1. 7 0
      contrib/lisp/ox-deck.el
  2. 7 0
      contrib/lisp/ox-s5.el
  3. 43 2
      doc/org.texi
  4. 3 0
      etc/ORG-NEWS
  5. 13 5
      lisp/ox-ascii.el
  6. 18 1
      lisp/ox-beamer.el
  7. 25 5
      lisp/ox-html.el
  8. 35 4
      lisp/ox-latex.el
  9. 20 2
      lisp/ox-odt.el
  10. 4 4
      lisp/ox-texinfo.el

+ 7 - 0
contrib/lisp/ox-deck.el

@@ -38,6 +38,12 @@
 ;; See ox.el and ox-html.el for more details on how this exporter
 ;; works (it is derived from ox-html.)
 
+;; TODOs
+;; ------
+;; The title page is formatted using format-spec.  This is error prone
+;; when details are missing and may insert empty tags, like <h2></h2>,
+;; for missing values.
+
 (require 'ox-html)
 (eval-when-compile (require 'cl))
 
@@ -261,6 +267,7 @@ Defaults to styles for the title page."
 
 (defcustom org-deck-title-slide-template
   "<h1>%t</h1>
+<h2>%s</h2>
 <h2>%a</h2>
 <h2>%e</h2>
 <h2>%d</h2>"

+ 7 - 0
contrib/lisp/ox-s5.el

@@ -48,6 +48,12 @@
 ;; in an Org mode buffer.  See ox.el and ox-html.el for more details
 ;; on how this exporter works.
 
+;; TODOs
+;; ------
+;; The title page is formatted using format-spec.  This is error prone
+;; when details are missing and may insert empty tags, like <h2></h2>,
+;; for missing values.
+
 (require 'ox-html)
 (eval-when-compile (require 'cl))
 
@@ -174,6 +180,7 @@ or an empty string."
 
 (defcustom org-s5-title-slide-template
   "<h1>%t</h1>
+<h2>%s</h2>
 <h2>%a</h2>
 <h3>%e</h3>
 <h4>%d</h4>"

+ 43 - 2
doc/org.texi

@@ -10926,6 +10926,17 @@ When the original file is @file{myfile.txt}, the resulting file becomes
 Export to a temporary buffer.  Do not create a file.
 @end table
 
+@subheading ASCII specific export settings
+
+ASCII export introduces a single of keywords, similar to the general options
+settings described in @ref{Export settings}.
+
+@table @samp
+@item SUBTITLE
+@cindex #+SUBTITLE (ASCII)
+The document subtitle.
+@end table
+
 @subheading Header and sectioning structure
 
 In the exported version, the first three outline levels become headlines,
@@ -11063,6 +11074,14 @@ inserted as metadata using @samp{hyperref}.  Document metadata can be
 configured via @code{org-latex-hyperref-template}.  Description can also be
 typeset as part of the front matter via @code{org-latex-title-command}.  You
 can use several @code{#+KEYWORDS} if the description is is long.
+
+@item SUBTITLE
+@cindex #+SUBTITLE (Beamer)
+@vindex org-beamer-subtitle-format
+The document subtitle.  This is typeset using the format string
+@code{org-beamer-subtitle-format}.  It can also access via
+@code{org-latex-hyperref-template} or typeset as part of the front
+matter via @code{org-latex-title-command}.
 @end table
 
 @node Sectioning Frames and Blocks in Beamer
@@ -11352,6 +11371,11 @@ is long.
 @cindex #+LATEX_HEADER (HTML)
 Arbitrary lines appended to the preamble used when transcoding @LaTeX{}
 fragments to images.  See @ref{Math formatting in HTML export} for details.
+
+@item SUBTITLE
+@cindex #+SUBTILE (HTML)
+The document subtitle.  The formatting depends on whether HTML5 in used
+and on the @samp{subtitle} CSS class.
 @end table
 
 These keywords are treated in details in the following sections.
@@ -11700,6 +11724,7 @@ p.author            @r{author information, including email}
 p.date              @r{publishing date}
 p.creator           @r{creator info, about org mode version}
 .title              @r{document title}
+.subtitle           @r{document subtitle}
 .todo               @r{TODO keywords, all not-done states}
 .done               @r{the DONE keywords, all states that count as done}
 .WAITING            @r{each TODO keyword also uses a class named after itself}
@@ -11921,6 +11946,16 @@ inserted as metadata using @samp{hyperref}.  Document metadata can be
 configured via @code{org-latex-hyperref-template}.  Description can also be
 typeset as part of the front matter via @code{org-latex-title-command}.  You
 can use several @code{#+KEYWORDS} if the description is is long.
+
+@item SUBTITLE
+@cindex #+SUBTITLE (@LaTeX{})
+@vindex org-latex-subtitle-separate
+@vindex org-latex-subtitle-format
+The document subtitle.  This is typeset according to
+@code{org-latex-subtitle-format}.  If @code{org-latex-subtitle-separate}
+is non-@code{nil} it is typed as part of the @samp{\title}-macro.  It
+can also access via @code{org-latex-hyperref-template} or typeset as
+part of the front matter via @code{org-latex-title-command}.
 @end table
 
 These keywords are treated in details in the following sections.
@@ -12410,6 +12445,10 @@ document metadata.  You can use several such keywords if the list is long.
 @vindex org-odt-styles-file
 The style file of the document (@code{org-odt-styles-file}).  See
 @ref{Applying custom styles} for details.
+
+@item SUBTITLE
+@cindex SUBTITLE (ODT)
+The document subtitle.
 @end table
 
 @node Extending ODT export
@@ -13321,7 +13360,7 @@ options settings described in @ref{Export settings}.
 @table @samp
 
 @item SUBTITLE
-@cindex #+SUBTITLE
+@cindex #+SUBTITLE (Texinfo)
 The document subtitle.
 
 @item SUBAUTHOR
@@ -13401,7 +13440,6 @@ to define your own class in @code{org-texinfo-classes}, which see.  Set
 @subsubheading Title and copyright page
 
 @cindex #+TEXINFO_PRINTED_TITLE
-@cindex #+SUBTITLE
 The default template includes a title page for hard copy output.  The title
 and author displayed on this page are extracted from, respectively,
 @code{#+TITLE} and @code{#+AUTHOR} keywords (@pxref{Export settings}).  It is
@@ -14207,6 +14245,7 @@ however, override everything.
 @item @code{:beamer-frame-default-options} @tab @code{org-beamer-frame-default-options}
 @item @code{:beamer-outline-frame-options} @tab @code{org-beamer-outline-frame-options}
 @item @code{:beamer-outline-frame-title}   @tab @code{org-beamer-outline-frame-title}
+@item @code{:beamer-subtitle-format}       @tab @code{org-beamer-subtitle-format}
 @end multitable
 
 @subsubheading HTML specific properties
@@ -14292,6 +14331,8 @@ however, override everything.
 @item @code{:latex-listings}                   @tab @code{org-latex-listings}
 @item @code{:latex-minted-langs}               @tab @code{org-latex-minted-langs}
 @item @code{:latex-minted-options}             @tab @code{org-latex-minted-options}
+@item @code{:latex-subtitle-format}            @tab @code{org-latex-subtitle-format}
+@item @code{:latex-subtitle-separate}          @tab @code{org-latex-subtitle-separate}
 @item @code{:latex-table-scientific-notation}  @tab @code{org-latex-table-scientific-notation}
 @item @code{:latex-tables-booktabs}            @tab @code{org-latex-tables-booktabs}
 @item @code{:latex-tables-centered}            @tab @code{org-latex-tables-centered}

+ 3 - 0
etc/ORG-NEWS

@@ -356,6 +356,9 @@ keywords and properties.
 *** Viewport support in html export
 Viewport for mobile-optimized website is now automatically inserted
 when exporting to html.  See ~org-html-viewport~ for details.
+*** New ~#+SUBTITLE~ export keyword
+Org can typeset a subtitle in some export backends.  See the manual
+for details.
 ** Miscellaneous
 *** Strip all meta data from ITEM special property
 ITEM special property does not contain TODO, priority or tags anymore.

+ 13 - 5
lisp/ox-ascii.el

@@ -119,7 +119,8 @@
 				       org-ascii-filter-comment-spacing)
 		   (:filter-section . org-ascii-filter-headline-blank-lines))
   :options-alist
-  '((:ascii-bullets nil nil org-ascii-bullets)
+  '((:subtitle "SUBTITLE" nil nil parse)
+    (:ascii-bullets nil nil org-ascii-bullets)
     (:ascii-caption-above nil nil org-ascii-caption-above)
     (:ascii-charset nil nil org-ascii-charset)
     (:ascii-global-margin nil nil org-ascii-global-margin)
@@ -967,9 +968,11 @@ INFO is a plist used as a communication channel."
 	 ;; Links in the title will not be resolved later, so we make
 	 ;; sure their path is located right after them.
 	 (info (org-combine-plists info '(:ascii-links-to-notes nil)))
-	 (title (if (plist-get info :with-title)
-		    (org-export-data (plist-get info :title) info)
-		  ""))
+	 (with-title (plist-get info :with-title))
+	 (title (org-export-data
+		 (when with-title (plist-get info :title)) info))
+	 (subtitle (org-export-data
+		    (when with-title (plist-get info :subtitle)) info))
 	 (author (and (plist-get info :with-author)
 		      (let ((auth (plist-get info :author)))
 			(and auth (org-export-data auth info)))))
@@ -1013,9 +1016,13 @@ INFO is a plist used as a communication channel."
 	     ;; Format TITLE.  It may be filled if it is too wide,
 	     ;; that is wider than the two thirds of the total width.
 	     (title-len (min (apply #'max
-				    (mapcar #'length (org-split-string title "\n")))
+				    (mapcar #'length
+					    (org-split-string
+					     (concat title "\n" subtitle) "\n")))
 			     (/ (* 2 text-width) 3)))
 	     (formatted-title (org-ascii--fill-string title title-len info))
+	     (formatted-subtitle (when (org-string-nw-p subtitle)
+				   (org-ascii--fill-string subtitle title-len info)))
 	     (line
 	      (make-string
 	       (min (+ (max title-len
@@ -1027,6 +1034,7 @@ INFO is a plist used as a communication channel."
 	 (concat line "\n"
 		 (unless utf8p "\n")
 		 (upcase formatted-title)
+		 (and formatted-subtitle (concat "\n" formatted-subtitle))
 		 (cond
 		  ((and (org-string-nw-p author) (org-string-nw-p email))
 		   (concat "\n\n" author "\n" email))

+ 18 - 1
lisp/ox-beamer.el

@@ -133,6 +133,15 @@ You might want to put e.g. \"allowframebreaks=0.9\" here."
   :type '(string :tag "Outline frame options"))
 
 
+(defcustom org-beamer-subtitle-format "\\subtitle{%s}"
+  "Format string used for transcoded subtitle.
+The format string should have at most one \"%s\"-expression,
+which is replaced with the subtitle."
+  :group 'org-export-beamer
+  :version "25.1"
+  :package-version '(Org . "8.3")
+  :type '(string :tag "Format string"))
+
 
 ;;; Internal Variables
 
@@ -233,6 +242,7 @@ Return overlay specification, as a string, or nil."
   :options-alist
   '((:headline-levels nil "H" org-beamer-frame-level)
     (:latex-class "LATEX_CLASS" nil "beamer" t)
+    (:beamer-subtitle-format nil nil org-beamer-subtitle-format)
     (:beamer-column-view-format "COLUMNS" nil org-beamer-column-view-format)
     (:beamer-theme "BEAMER_THEME" nil org-beamer-theme)
     (:beamer-color-theme "BEAMER_COLOR_THEME" nil nil t)
@@ -810,7 +820,12 @@ information."
   "Return complete document string after Beamer conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
 holding export options."
-  (let ((title (org-export-data (plist-get info :title) info)))
+  (let ((title (org-export-data (plist-get info :title) info))
+	(subtitle (org-export-data
+		   (org-element-parse-secondary-string
+		    (plist-get info :subtitle)
+		    (org-element-restriction 'keyword))
+		   info)))
     (concat
      ;; 1. Time-stamp.
      (and (plist-get info :time-stamp-file)
@@ -877,6 +892,8 @@ holding export options."
        (format "\\date{%s}\n" (org-export-data date info)))
      ;; 7. Title
      (format "\\title{%s}\n" title)
+     (when (org-string-nw-p subtitle)
+       (concat (format (plist-get info :beamer-subtitle-format) subtitle) "\n"))
      ;; 8. Beamer-header
      (let ((beamer-header (plist-get info :beamer-header)))
        (when beamer-header

+ 25 - 5
lisp/ox-html.el

@@ -122,6 +122,7 @@
     (:html-preamble nil "html-preamble" org-html-preamble)
     (:html-head "HTML_HEAD" nil org-html-head newline)
     (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline)
+    (:subtitle "SUBTITLE" nil nil parse)
     (:html-head-include-default-style
      nil "html-style" org-html-head-include-default-style)
     (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts)
@@ -272,7 +273,12 @@ for the JavaScript code in this tag.
 (defconst org-html-style-default
   "<style type=\"text/css\">
  <!--/*--><![CDATA[/*><!--*/
-  .title  { text-align: center; }
+  .title  { text-align: center;
+             margin-bottom: .2em; }
+  .subtitle { text-align: center;
+              font-size: medium;
+              font-weight: bold;
+              margin-top:0; }
   .todo   { font-family: monospace; color: red; }
   .done   { font-family: monospace; color: green; }
   .priority { font-family: monospace; color: orange; }
@@ -1212,6 +1218,7 @@ The second element of each list is a format string to format the
 postamble itself.  This format string can contain these elements:
 
   %t stands for the title.
+  %s stands for the subtitle.
   %a stands for the author's name.
   %e stands for the author's email.
   %d stands for the date.
@@ -1276,6 +1283,7 @@ The second element of each list is a format string to format the
 preamble itself.  This format string can contain these elements:
 
   %t stands for the title.
+  %s stands for the subtitle.
   %a stands for the author's name.
   %e stands for the author's email.
   %d stands for the date.
@@ -1788,6 +1796,7 @@ INFO is a plist used as a communication channel."
   "Return format specification for elements that can be
 used in the preamble or postamble."
   `((?t . ,(org-export-data (plist-get info :title) info))
+    (?s . ,(org-export-data (plist-get info :subtitle) info))
     (?d . ,(org-export-data (org-export-get-date info) info))
     (?T . ,(format-time-string
 	    (plist-get info :html-metadata-timestamp-format)))
@@ -1928,10 +1937,21 @@ holding export options."
      (format "<%s id=\"%s\">\n" (nth 1 div) (nth 2 div)))
    ;; Document title.
    (when (plist-get info :with-title)
-     (let ((title (org-export-data
-		   (or (plist-get info :title) "") info)))
-       (when (org-string-nw-p title)
-	 (format "<h1 class=\"title\">%s</h1>\n" title))))
+     (let ((title (plist-get info :title))
+	   (subtitle (plist-get info :subtitle)))
+       (when title
+	 (format
+	  (if (plist-get info :html-html5-fancy)
+	      "<header>\n<h1 class=\"title\">%s</h1>\n%s</header>"
+	    "<h1 class=\"title\">%s%s</h1>\n")
+	  (org-export-data title info)
+	  (if subtitle
+	      (format
+	       (if (plist-get info :html-html5-fancy)
+		   "<p class=\"subtitle\">%s</p>\n"
+		 "\n<br>\n<span class=\"subtitle\">%s</span>\n")
+	       (org-export-data subtitle info))
+	    "")))))
    contents
    (format "</%s>\n" (nth 1 (assq 'content (plist-get info :html-divs))))
    ;; Postamble.

+ 35 - 4
lisp/ox-latex.el

@@ -108,8 +108,9 @@
     (:latex-class-options "LATEX_CLASS_OPTIONS" nil nil t)
     (:latex-header "LATEX_HEADER" nil nil newline)
     (:latex-header-extra "LATEX_HEADER_EXTRA" nil nil newline)
-    (:description "DESCRIPTION" nil nil parse)
-    (:keywords "KEYWORDS" nil nil parse)
+    (:description "DESCRIPTION" nil nil newline)
+    (:keywords "KEYWORDS" nil nil space)
+    (:subtitle "SUBTITLE" nil nil space)
     ;; Other variables.
     (:latex-active-timestamp-format nil nil org-latex-active-timestamp-format)
     (:latex-caption-above nil nil org-latex-caption-above)
@@ -135,6 +136,8 @@
     (:latex-listings-options nil nil org-latex-listings-options)
     (:latex-minted-langs nil nil org-latex-minted-langs)
     (:latex-minted-options nil nil org-latex-minted-options)
+    (:latex-subtitle-format nil nil org-latex-subtitle-format)
+    (:latex-subtitle-separate nil nil org-latex-subtitle-separate)
     (:latex-table-scientific-notation nil nil org-latex-table-scientific-notation)
     (:latex-tables-booktabs nil nil org-latex-tables-booktabs)
     (:latex-tables-centered nil nil org-latex-tables-centered)
@@ -388,6 +391,7 @@ This format string may contain these elements:
 
   %a for AUTHOR keyword
   %t for TITLE keyword
+  %s for SUBTITLE keyword
   %k for KEYWORDS line
   %d for DESCRIPTION line
   %c for CREATOR line
@@ -403,6 +407,22 @@ precedence over this variable."
   :group 'org-export-latex
   :type '(string :tag "Format string"))
 
+(defcustom org-latex-subtitle-format "\\\\\\medskip\n\\large %s"
+  "Format string used for transcoded subtitle.
+The format string should have at most one \"%s\"-expression,
+which is replaced with the subtitle."
+  :group 'org-export-latex
+  :version "25.1"
+  :package-version '(Org . "8.3")
+  :type '(string :tag "Format string"))
+
+(defcustom org-latex-subtitle-separate nil
+  "Non-nil means the subtitle is not typeset as part of title."
+  :group 'org-export-latex
+  :version "25.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean)
+
 (defcustom org-latex-toc-command "\\tableofcontents\n\n"
   "LaTeX command to set the table of contents, list of figures, etc.
 This command only applies to the table of contents generated with
@@ -419,6 +439,7 @@ This format string may contain these elements:
 
   %a for AUTHOR keyword
   %t for TITLE keyword
+  %s for SUBTITLE keyword
   %k for KEYWORDS line
   %d for DESCRIPTION line
   %c for CREATOR line
@@ -1288,8 +1309,18 @@ holding export options."
      ;; Date.
      (let ((date (and (plist-get info :with-date) (org-export-get-date info))))
        (format "\\date{%s}\n" (org-export-data date info)))
-     ;; Title
-     (format "\\title{%s}\n" title)
+     ;; Title and subtitle.
+     (let* ((subtitle (plist-get info :subtitle))
+	    (formatted-subtitle
+	     (when subtitle
+	       (format (plist-get info :latex-subtitle-format)
+		       (org-export-data subtitle info))))
+	    (separate (plist-get info :latex-subtitle-separate)))
+       (concat
+	(format "\\title{%s%s}\n" title
+		(if separate "" formatted-subtitle))
+	(when (and separate subtitle)
+	  (concat formatted-subtitle "\n"))))
      ;; Hyperref options.
      (let ((template (plist-get info :latex-hyperref-template)))
        (and (stringp template)

+ 20 - 2
lisp/ox-odt.el

@@ -99,6 +99,7 @@
   '((:odt-styles-file "ODT_STYLES_FILE" nil nil t)
     (:description "DESCRIPTION" nil nil newline)
     (:keywords "KEYWORDS" nil nil space)
+    (:subtitle "SUBTITLE" nil nil parse)
     ;; Other variables.
     (:odt-content-template-file nil nil org-odt-content-template-file)
     (:odt-display-outline-level nil nil org-odt-display-outline-level)
@@ -1328,6 +1329,7 @@ CONTENTS is the transcoded contents string.  RAW-DATA is the
 original parsed data.  INFO is a plist holding export options."
   ;; Write meta file.
   (let ((title (org-export-data (plist-get info :title) info))
+	(subtitle (org-export-data (plist-get info :subtitle) info))
 	(author (let ((author (plist-get info :author)))
 		  (if (not author) "" (org-export-data author info))))
 	(email (plist-get info :email))
@@ -1365,6 +1367,10 @@ original parsed data.  INFO is a plist holding export options."
       (format "<meta:keyword>%s</meta:keyword>\n" keywords)
       (format "<dc:subject>%s</dc:subject>\n" description)
       (format "<dc:title>%s</dc:title>\n" title)
+      (when (org-string-nw-p subtitle)
+	(format
+	 "<meta:user-defined meta:name=\"subtitle\">%s</meta:user-defined>\n"
+	 subtitle))
       "\n"
       "  </office:meta>\n" "</office:document-meta>")
      nil (concat org-odt-zip-dir "meta.xml"))
@@ -1510,6 +1516,8 @@ original parsed data.  INFO is a plist holding export options."
       (insert
        (let* ((title (and (plist-get info :with-title)
 			  (org-export-data (plist-get info :title) info)))
+	      (subtitle (when title
+			  (org-export-data (plist-get info :subtitle) info)))
 	      (author (and (plist-get info :with-author)
 			   (let ((auth (plist-get info :author)))
 			     (and auth (org-export-data auth info)))))
@@ -1521,10 +1529,20 @@ original parsed data.  INFO is a plist holding export options."
 	  ;; Title.
 	  (when (org-string-nw-p title)
 	    (concat
-	     (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
+	     (format "\n<text:p text:style-name=\"%s\">%s</text:p>\n"
 		     "OrgTitle" (format "\n<text:title>%s</text:title>" title))
 	     ;; Separator.
-	     "\n<text:p text:style-name=\"OrgTitle\"/>"))
+	     "\n<text:p text:style-name=\"OrgTitle\"/>\n"
+	     ;; Subtitle.
+	     (when (org-string-nw-p subtitle)
+	       (concat
+		(format "<text:p text:style-name=\"OrgSubtitle\">\n%s\n</text:p>\n"
+			(concat
+			 "<text:user-defined style:data-style-name=\"N0\" text:name=\"subtitle\">\n"
+			 subtitle
+			 "</text:user-defined>\n"))
+		;; Separator.
+		"<text:p text:style-name=\"OrgSubtitle\"/>\n"))))
 	  (cond
 	   ((and author (not email))
 	    ;; Author only.

+ 4 - 4
lisp/ox-texinfo.el

@@ -92,7 +92,7 @@
     (:texinfo-class "TEXINFO_CLASS" nil org-texinfo-default-class t)
     (:texinfo-header "TEXINFO_HEADER" nil nil newline)
     (:texinfo-post-header "TEXINFO_POST_HEADER" nil nil newline)
-    (:subtitle "SUBTITLE" nil nil newline)
+    (:subtitle "SUBTITLE" nil nil parse)
     (:subauthor "SUBAUTHOR" nil nil newline)
     (:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t)
     (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t)
@@ -570,9 +570,9 @@ holding export options."
        (concat
 	(format "@title %s\n" (or (plist-get info :texinfo-printed-title) title ""))
 	(let ((subtitle (plist-get info :subtitle)))
-	  (and subtitle
-	       (org-element-normalize-string
-		(replace-regexp-in-string "^" "@subtitle " subtitle))))))
+	  (when subtitle
+	    (format "@subtitle %s\n"
+		    (org-export-data subtitle info))))))
      (when (plist-get info :with-author)
        (concat
 	;; Primary author.