1
;;; muse-docbook.el --- publish DocBook files
3
;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5
;; This file is not part of GNU Emacs.
7
;; This is free software; you can redistribute it and/or modify it under
8
;; the terms of the GNU General Public License as published by the Free
9
;; Software Foundation; either version 2, or (at your option) any later
12
;; This is distributed in the hope that it will be useful, but WITHOUT
13
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17
;; You should have received a copy of the GNU General Public License
18
;; along with GNU Emacs; see the file COPYING. If not, write to the
19
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
;; Boston, MA 02110-1301, USA.
26
;; Dale P. Smith (dpsm AT en DOT com) improved the markup
27
;; significantly and made many valuable suggestions.
31
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33
;; Muse DocBook XML Publishing
35
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37
(require 'muse-publish)
38
(require 'muse-regexps)
40
(defgroup muse-docbook nil
41
"Options controlling the behavior of Muse DocBook XML publishing.
42
See `muse-docbook' for more information."
45
(defcustom muse-docbook-extension ".xml"
46
"Default file extension for publishing DocBook XML files."
50
(defcustom muse-docbook-header
51
"<?xml version=\"1.0\" encoding=\"<lisp>
52
(muse-docbook-encoding)</lisp>\"?>
53
<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"
54
\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">
57
<title><lisp>(muse-publishing-directive \"title\")</lisp></title>
58
<author><lisp>(muse-docbook-get-author
59
(muse-publishing-directive \"author\"))</lisp></author>
60
<pubdate><lisp>(muse-publishing-directive \"date\")</lisp></pubdate>
62
<!-- Page published by Emacs Muse begins here -->\n"
63
"Header used for publishing DocBook XML files.
64
This may be text or a filename."
68
(defcustom muse-docbook-footer "
69
<!-- Page published by Emacs Muse ends here -->
71
"Footer used for publishing DocBook XML files.
72
This may be text or a filename."
76
(defcustom muse-docbook-markup-regexps
77
`(;; Join together the parts of a table
78
(10000 ,(concat " </t\\(body\\|head\\|foot\\)>\\s-*"
79
"</tgroup>\\s-*</informaltable>"
80
"\\([" muse-regexp-blank "]*\n\\)\\{0,2\\}"
81
"[" muse-regexp-blank "]*"
82
"<informaltable[^>]*>\\s-*<tgroup[^>]*>\\s-*"
85
(10100 ,(concat " </tgroup>\\s-*</informaltable>"
86
"\\([" muse-regexp-blank "]*\n\\)\\{0,2\\}"
87
"[" muse-regexp-blank "]*"
88
"<informaltable[^>]*>\\s-*<tgroup[^>]*>\n")
91
;; Join together the parts of a list
92
(10200 ,(concat "</\\(itemized\\|ordered\\|variable\\)list>"
93
"\\([" muse-regexp-blank "]*\n\\)\\{0,2\\}"
94
"[" muse-regexp-blank "]*"
95
"<\\1list" "[^>]*>\\s-*")
98
;; Beginning of doc, end of doc, or plain paragraph separator
99
(10300 ,(concat "\\(\n</\\(blockquote\\|center\\)>\\)?"
102
"]*\n\\)+\\)\\|\\`\\s-*\\|\\s-*\\'\\)"
103
"\\(<\\(blockquote\\|center\\)>\n\\)?")
104
0 muse-docbook-markup-paragraph))
105
"List of markup rules for publishing a Muse page to DocBook XML.
106
For more on the structure of this list, see `muse-publish-markup-regexps'."
107
:type '(repeat (choice
108
(list :tag "Markup rule"
110
(choice regexp symbol)
112
(choice string function symbol))
114
:group 'muse-docbook)
116
(defcustom muse-docbook-markup-functions
117
'((anchor . muse-docbook-markup-anchor)
118
(table . muse-docbook-markup-table))
119
"An alist of style types to custom functions for that kind of text.
120
For more on the structure of this list, see
121
`muse-publish-markup-functions'."
122
:type '(alist :key-type symbol :value-type function)
123
:group 'muse-docbook)
125
(defcustom muse-docbook-markup-strings
126
'((url-link . "<ulink url=\"%s\">%s</ulink>")
127
(internal-link . "<link linkend=\"%s\">%s</link>")
128
(email-addr . "<email>%s</email>")
129
(emdash . " — ")
130
(comment-begin . "<!-- ")
131
(comment-end . " -->")
135
(section . "<section><title>")
136
(section-end . "</title>")
137
(subsection . "<section><title>")
138
(subsection-end . "</title>")
139
(subsubsection . "<section><title>")
140
(subsubsection-end . "</title>")
141
(section-other . "<section><title>")
142
(section-other-end . "</title>")
143
(section-close . "</section>")
144
(footnote . "<footnote><para>")
145
(footnote-end . "</para></footnote>")
146
(begin-underline . "")
148
(begin-literal . "<systemitem>")
149
(end-literal . "</systemitem>")
150
(begin-emph . "<emphasis>")
151
(end-emph . "</emphasis>")
152
(begin-more-emph . "<emphasis role=\"strong\">")
153
(end-more-emph . "</emphasis>")
154
(begin-most-emph . "<emphasis role=\"strong\"><emphasis>")
155
(end-most-emph . "</emphasis></emphasis>")
156
(begin-verse . "<literallayout>\n")
158
(end-verse . "</literallayout>")
159
(begin-example . "<programlisting>")
160
(end-example . "</programlisting>")
161
(begin-center . "<para role=\"centered\">\n")
162
(end-center . "\n</para>")
163
(begin-quote . "<blockquote>\n")
164
(end-quote . "\n</blockquote>")
165
(begin-uli . "<itemizedlist mark=\"bullet\">\n<listitem><para>")
166
(end-uli . "</para></listitem>\n</itemizedlist>")
167
(begin-oli . "<orderedlist>\n<listitem><para>")
168
(end-oli . "</para></listitem>\n</orderedlist>")
169
(begin-ddt . "<variablelist>\n<varlistentry>\n<term>")
170
(start-dde . "</term>\n<listitem><para>")
171
(end-ddt . "</para></listitem>\n</varlistentry>\n</variablelist>"))
172
"Strings used for marking up text.
173
These cover the most basic kinds of markup, the handling of which
174
differs little between the various styles."
175
:type '(alist :key-type symbol :value-type string)
176
:group 'muse-docbook)
178
(defcustom muse-docbook-markup-specials
183
"A table of characters which must be represented specially."
184
:type '(alist :key-type character :value-type string)
185
:group 'muse-docbook)
187
(defcustom muse-docbook-encoding-default 'utf-8
188
"The default Emacs buffer encoding to use in published files.
189
This will be used if no special characters are found."
191
:group 'muse-docbook)
193
(defcustom muse-docbook-charset-default "utf-8"
194
"The default DocBook XML charset to use if no translation is
195
found in `muse-docbook-encoding-map'."
197
:group 'muse-docbook)
199
(defcustom muse-docbook-encoding-map
200
'((iso-8859-1 . "iso-8859-1")
201
(iso-2022-jp . "iso-2022-jp")
203
(japanese-iso-8bit . "euc-jp")
204
(chinese-big5 . "big5")
205
(mule-utf-8 . "utf-8")
206
(chinese-iso-8bit . "gb2312")
207
(chinese-gbk . "gbk"))
208
"An alist mapping emacs coding systems to appropriate DocBook charsets.
209
Use the base name of the coding system (i.e. without the -unix)."
210
:type '(alist :key-type coding-system :value-type string)
211
:group 'muse-docbook)
213
(defun muse-docbook-transform-content-type (content-type)
214
"Using `muse-docbook-encoding-map', try and resolve an emacs
215
coding system to an associated DocBook XML coding system. If no
216
match is found, `muse-docbook-charset-default' is used instead."
217
(let ((match (and (fboundp 'coding-system-base)
218
(assoc (coding-system-base content-type)
219
muse-docbook-encoding-map))))
222
muse-docbook-charset-default)))
224
(defun muse-docbook-encoding ()
225
(muse-docbook-transform-content-type
226
(or (and (boundp 'buffer-file-coding-system)
227
buffer-file-coding-system)
228
muse-docbook-encoding-default)))
230
(defun muse-docbook-markup-paragraph ()
231
(let ((end (copy-marker (match-end 0) t)))
232
(goto-char (match-beginning 0))
233
(when (save-excursion
235
(and (re-search-backward "<\\(/?\\)\\(para\\|footnote\\)[ >]"
237
(or (and (string= (match-string 2) "para")
238
(not (string= (match-string 1) "/")))
239
(and (string= (match-string 2) "footnote")
240
(string= (match-string 1) "/"))))))
247
((eq (char-after) ?\<)
248
(when (looking-at (concat "<\\(emphasis\\|systemitem"
249
"\\|u?link\\|anchor\\|email\\)[ >]"))
254
(defun muse-docbook-insert-anchor (anchor)
255
"Insert an anchor, either before the next word, or within a tag."
256
(skip-chars-forward muse-regexp-space)
257
(when (looking-at "<\\([^ />]+\\)>")
258
(goto-char (match-end 0)))
259
(insert "<anchor id=\"" anchor "\" />\n"))
261
(defun muse-docbook-markup-anchor ()
263
(muse-docbook-insert-anchor (match-string 2)))
266
(defun muse-docbook-markup-table ()
269
(delete-region (match-beginning 0) (match-end 0))))
270
(fields (split-string str "\\s-*|+\\s-*"))
271
(type (and (string-match "\\s-*\\(|+\\)\\s-*" str)
272
(length (match-string 1 str))))
273
(part (cond ((= type 1) "tbody")
275
((= type 3) "tfoot"))))
276
(insert "<informaltable>\n"
277
" <tgroup cols='" (number-to-string (length fields)) "'>\n"
280
(dolist (field fields)
281
(insert " <entry>" field "</entry>\n"))
285
"</informaltable>\n")))
287
(defun muse-docbook-get-author (&optional author)
288
"Split the AUTHOR directive into separate fields.
289
AUTHOR should be of the form: \"Firstname Other Names Lastname\",
290
and anything after `Firstname' is optional."
291
(setq author (save-match-data (split-string author)))
292
(let ((num-el (length author)))
294
(concat "<firstname>" (car author) "</firstname>"))
296
(concat "<firstname>" (nth 0 author) "</firstname>"
297
"<surname>" (nth 1 author) "</surname>"))
299
(concat "<firstname>" (nth 0 author) "</firstname>"
300
"<othername>" (nth 1 author) "</othername>"
301
"<surname>" (nth 2 author) "</surname>"))
304
(setq first (car author))
305
(setq author (nreverse (cdr author)))
306
(setq last (car author))
307
(setq author (nreverse (cdr author)))
308
(concat "<firstname>" first "</firstname>"
310
(mapconcat 'identity author " ")
312
"<surname>" last "</surname>"))))))
314
(defun muse-docbook-fixup-tables ()
316
(goto-char (point-min))
318
(while (re-search-forward "^ *<tgroup[^>]*>$" nil t)
319
(unless (get-text-property (point) 'read-only)
323
(narrow-to-region beg (and (re-search-forward "^ *</tgroup>"
325
(match-beginning 0))))
326
(goto-char (point-min))
327
(let ((inhibit-read-only t))
331
(if (re-search-forward
332
"^\\s-*<t\\(head\\|body\\|foot\\)>$" nil t)
333
(goto-char (match-beginning 0))
334
(goto-char (point-max)))))
337
(if (re-search-forward
338
"^\\s-*</t\\(head\\|body\\|foot\\)>$" nil t)
339
(goto-char (match-end 0))
340
(goto-char (point-max)))))
343
(looking-at "\\s-*<t\\(head\\|body\\|foot\\)>")
344
(cond ((string= (match-string 1) "head") 1)
345
((string= (match-string 1) "foot") 2)
348
(defun muse-docbook-finalize-buffer ()
349
(when (boundp 'buffer-file-coding-system)
350
(when (memq buffer-file-coding-system '(no-conversion undecided-unix))
351
;; make it agree with the default charset
352
(setq buffer-file-coding-system muse-docbook-encoding-default))))
354
;; Register the Muse DocBook XML Publisher
356
(unless (assoc "docbook" muse-publishing-styles)
357
(muse-define-style "docbook"
358
:suffix 'muse-docbook-extension
359
:regexps 'muse-docbook-markup-regexps
360
:functions 'muse-docbook-markup-functions
361
:strings 'muse-docbook-markup-strings
362
:specials 'muse-docbook-markup-specials
363
:before-end 'muse-docbook-fixup-tables
364
:after 'muse-docbook-finalize-buffer
365
:header 'muse-docbook-header
366
:footer 'muse-docbook-footer
367
:browser 'find-file))
369
(provide 'muse-docbook)
371
;;; muse-docbook.el ends here