From: Ihor Radchenko <yantar92@posteo.net>
To: Joseph Turner <joseph@breatheoutbreathe.in>
Cc: Christian Moe <mail@christianmoe.com>,
Org Mode Mailing List <emacs-orgmode@gnu.org>,
Bohong Huang <bohonghuang@qq.com>
Subject: Re: Form feed characters break odt export
Date: Fri, 27 Dec 2024 10:21:02 +0000 [thread overview]
Message-ID: <87plld5svl.fsf@localhost> (raw)
In-Reply-To: <878qs4oyyh.fsf@breatheoutbreathe.in>
[-- Attachment #1: Type: text/plain, Size: 443 bytes --]
Joseph Turner <joseph@breatheoutbreathe.in> writes:
> Thanks, Ihor! Tested working on my machine.
>
> Here's another potential solution to consider, which adds a defcustom to
> let the user decide how to handle forbidden characters:
>
> https://github.com/kjambunathan/org-mode-ox-odt/commit/07fde1e9b7cdda3e3ef8136f5b1d478499dfd780
Good idea!
I went even further and used a proper export setting.
See the attached 2nd version of the fix.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v2-0001-ox-odt-Avoid-putting-forbidden-characters-into-OD.patch --]
[-- Type: text/x-patch, Size: 4293 bytes --]
From de015e4a3b98bc975c2dcd1dfce7adcf77eb537c Mon Sep 17 00:00:00 2001
Message-ID: <de015e4a3b98bc975c2dcd1dfce7adcf77eb537c.1735294805.git.yantar92@posteo.net>
From: Ihor Radchenko <yantar92@posteo.net>
Date: Tue, 24 Dec 2024 15:11:22 +0100
Subject: [PATCH v2] ox-odt: Avoid putting forbidden characters into ODT xml
* lisp/ox-odt.el (org-odt-with-forbidden-chars): New export option to
control how to handle forbidden XML characters.
(org-odt--remove-forbidden): New filter removing/replacing forbidden
characters.
Reported-by: Joseph Turner <joseph@breatheoutbreathe.in>
Link: https://orgmode.org/list/87o711l4u4.fsf@christianmoe.com
---
lisp/ox-odt.el | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index ec81637ef0..635bf38971 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -94,7 +94,8 @@ (org-export-define-backend 'odt
. (org-odt--translate-latex-fragments
org-odt--translate-description-lists
org-odt--translate-list-tables
- org-odt--translate-image-links)))
+ org-odt--translate-image-links))
+ (:filter-final-output . org-odt--remove-forbidden))
:menu-entry
'(?o "Export to ODT"
((?o "As ODT file" org-odt-export-to-odt)
@@ -108,6 +109,7 @@ (org-export-define-backend 'odt
(:keywords "KEYWORDS" nil nil space)
(:subtitle "SUBTITLE" nil nil parse)
;; Other variables.
+ (:odt-with-forbidden-chars nil nil org-odt-with-forbidden-chars)
(:odt-content-template-file nil nil org-odt-content-template-file)
(:odt-display-outline-level nil nil org-odt-display-outline-level)
(:odt-fontify-srcblocks nil nil org-odt-fontify-srcblocks)
@@ -170,6 +172,14 @@ (defconst org-odt-special-string-regexps
("\\.\\.\\." . "…")) ; hellip
"Regular expressions for special string conversion.")
+(defconst org-odt-forbidden-char-re
+ (rx (not (in ?\N{U+9} ?\N{U+A} ?\N{U+D}
+ (?\N{U+20} . ?\N{U+D7FF})
+ (?\N{U+E000} . ?\N{U+FFFD})
+ (?\N{U+10000} . ?\N{U+10FFFF}))))
+ "Regexp matching forbidden XML1.0 characters.
+https://www.w3.org/TR/REC-xml/#charsets")
+
(defconst org-odt-schema-dir-list
(list (expand-file-name "./schema/" org-odt-data-dir))
"List of directories to search for OpenDocument schema files.
@@ -364,6 +374,19 @@ (defgroup org-export-odt nil
:tag "Org Export ODT"
:group 'org-export)
+(defcustom org-odt-with-forbidden-chars ""
+ "String to replace forbidden XML characters.
+When set to t, forbidden characters are retained.
+When set to nil, an error is thrown.
+See `org-odt-forbidden-char-re' for the list of forbidden characters
+that cannot occur inside ODT documents.
+
+You may also consider export filters to perform more fine-grained
+replacements. See info node `(org)Advanced Export Configuration'."
+ :package-version '(Org . "9.8")
+ :type '(choice (const :tag "Strip forbidden characters" t)
+ (const :tag "Err when forbidden characters encountered" nil)
+ (string :tag "Replacement string")))
;;;; Debugging
@@ -2892,6 +2915,24 @@ (defun org-odt--encode-tabs-and-spaces (line)
(format " <text:s text:c=\"%d\"/>" (1- (length s)))))
line))
+(defun org-odt--remove-forbidden (text _backend info)
+ "Remove forbidden and discouraged characters from TEXT.
+INFO is the communication plist"
+ (pcase (plist-get info :odt-with-forbidden-chars)
+ ((and (pred stringp) rep)
+ (prog1 (replace-regexp-in-string org-odt-forbidden-char-re rep text)
+ (when (match-string 0 text)
+ (display-warning
+ '(ox-odt ox-odt-with-forbidden-chars)
+ (format "Replacing forbidden character '%s' with '%s'"
+ (match-string 0 text) rep)))))
+ (`nil
+ (if (string-match org-odt-forbidden-char-re text)
+ (error "Forbidden character '%s' found. See `org-odt-with-forbidden-chars'"
+ (match-string 0 text))
+ text))
+ (_ text)))
+
(defun org-odt--encode-plain-text (text &optional no-whitespace-filling)
(dolist (pair '(("&" . "&") ("<" . "<") (">" . ">")))
(setq text (replace-regexp-in-string (car pair) (cdr pair) text t t)))
--
2.47.1
[-- Attachment #3: Type: text/plain, Size: 223 bytes --]
--
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
next prev parent reply other threads:[~2024-12-27 10:20 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-21 1:48 Form feed characters break odt export Joseph Turner via General discussions about Org-mode.
2024-12-21 3:56 ` Max Nikulin
2024-12-21 6:52 ` Joseph Turner
2024-12-21 7:23 ` Max Nikulin
2024-12-21 19:06 ` Joseph Turner
2024-12-24 16:23 ` Max Nikulin
2024-12-25 10:16 ` Joseph Turner
2024-12-23 17:32 ` Ihor Radchenko
2024-12-24 11:04 ` Christian Moe
2024-12-24 14:14 ` Ihor Radchenko
2024-12-25 10:10 ` Joseph Turner
2024-12-27 10:21 ` Ihor Radchenko [this message]
2024-12-27 20:42 ` Joseph Turner
2024-12-28 8:32 ` Ihor Radchenko
2024-12-28 9:50 ` Joseph Turner
2024-12-28 15:50 ` Ihor Radchenko
2024-12-24 14:25 ` Max Nikulin
2024-12-24 14:30 ` Ihor Radchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87plld5svl.fsf@localhost \
--to=yantar92@posteo.net \
--cc=bohonghuang@qq.com \
--cc=emacs-orgmode@gnu.org \
--cc=joseph@breatheoutbreathe.in \
--cc=mail@christianmoe.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.