Commit | Line | Data |
---|---|---|
c8d0cf5c CD |
1 | ;;; org-html.el --- HTML export for Org-mode |
2 | ||
3ab2c837 BG |
3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
4 | ;; Free Software Foundation, Inc. | |
c8d0cf5c CD |
5 | |
6 | ;; Author: Carsten Dominik <carsten at orgmode dot org> | |
7 | ;; Keywords: outlines, hypermedia, calendar, wp | |
8 | ;; Homepage: http://orgmode.org | |
3ab2c837 | 9 | ;; Version: 7.7 |
c8d0cf5c CD |
10 | ;; |
11 | ;; This file is part of GNU Emacs. | |
12 | ;; | |
13 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
14 | ;; it under the terms of the GNU General Public License as published by | |
15 | ;; the Free Software Foundation, either version 3 of the License, or | |
16 | ;; (at your option) any later version. | |
17 | ||
18 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | ;; GNU General Public License for more details. | |
22 | ||
23 | ;; You should have received a copy of the GNU General Public License | |
24 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
25 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
26 | ;; | |
27 | ;;; Commentary: | |
28 | ||
86fbb8ca CD |
29 | ;;; Code: |
30 | ||
c8d0cf5c | 31 | (require 'org-exp) |
3ab2c837 | 32 | (require 'format-spec) |
86fbb8ca | 33 | |
54a0dee5 | 34 | (eval-when-compile (require 'cl)) |
c8d0cf5c CD |
35 | |
36 | (declare-function org-id-find-id-file "org-id" (id)) | |
37 | (declare-function htmlize-region "ext:htmlize" (beg end)) | |
3ab2c837 BG |
38 | (declare-function org-pop-to-buffer-same-window |
39 | "org-compat" (&optional buffer-or-name norecord label)) | |
c8d0cf5c CD |
40 | |
41 | (defgroup org-export-html nil | |
42 | "Options specific for HTML export of Org-mode files." | |
43 | :tag "Org Export HTML" | |
44 | :group 'org-export) | |
45 | ||
46 | (defcustom org-export-html-footnotes-section "<div id=\"footnotes\"> | |
47 | <h2 class=\"footnotes\">%s: </h2> | |
48 | <div id=\"text-footnotes\"> | |
49 | %s | |
50 | </div> | |
51 | </div>" | |
52 | "Format for the footnotes section. | |
53 | Should contain a two instances of %s. The first will be replaced with the | |
54 | language-specific word for \"Footnotes\", the second one will be replaced | |
55 | by the footnotes themselves." | |
56 | :group 'org-export-html | |
57 | :type 'string) | |
58 | ||
59 | (defcustom org-export-html-footnote-format "<sup>%s</sup>" | |
60 | "The format for the footnote reference. | |
61 | %s will be replaced by the footnote reference itself." | |
62 | :group 'org-export-html | |
63 | :type 'string) | |
64 | ||
3ab2c837 BG |
65 | |
66 | (defcustom org-export-html-footnote-separator "<sup>, </sup>" | |
67 | "Text used to separate footnotes." | |
68 | :group 'org-export-html | |
69 | :type 'string) | |
70 | ||
c8d0cf5c | 71 | (defcustom org-export-html-coding-system nil |
86fbb8ca | 72 | "Coding system for HTML export, defaults to `buffer-file-coding-system'." |
c8d0cf5c CD |
73 | :group 'org-export-html |
74 | :type 'coding-system) | |
75 | ||
76 | (defcustom org-export-html-extension "html" | |
77 | "The extension for exported HTML files." | |
78 | :group 'org-export-html | |
79 | :type 'string) | |
80 | ||
81 | (defcustom org-export-html-xml-declaration | |
82 | '(("html" . "<?xml version=\"1.0\" encoding=\"%s\"?>") | |
83 | ("php" . "<?php echo \"<?xml version=\\\"1.0\\\" encoding=\\\"%s\\\" ?>\"; ?>")) | |
84 | "The extension for exported HTML files. | |
85 | %s will be replaced with the charset of the exported file. | |
86 | This may be a string, or an alist with export extensions | |
87 | and corresponding declarations." | |
88 | :group 'org-export-html | |
89 | :type '(choice | |
90 | (string :tag "Single declaration") | |
91 | (repeat :tag "Dependent on extension" | |
92 | (cons (string :tag "Extension") | |
93 | (string :tag "Declaration"))))) | |
94 | ||
95 | (defcustom org-export-html-style-include-scripts t | |
86fbb8ca | 96 | "Non-nil means include the JavaScript snippets in exported HTML files. |
c8d0cf5c CD |
97 | The actual script is defined in `org-export-html-scripts' and should |
98 | not be modified." | |
99 | :group 'org-export-html | |
100 | :type 'boolean) | |
101 | ||
102 | (defconst org-export-html-scripts | |
103 | "<script type=\"text/javascript\"> | |
104 | <!--/*--><![CDATA[/*><!--*/ | |
105 | function CodeHighlightOn(elem, id) | |
106 | { | |
107 | var target = document.getElementById(id); | |
108 | if(null != target) { | |
109 | elem.cacheClassElem = elem.className; | |
110 | elem.cacheClassTarget = target.className; | |
111 | target.className = \"code-highlighted\"; | |
112 | elem.className = \"code-highlighted\"; | |
113 | } | |
114 | } | |
115 | function CodeHighlightOff(elem, id) | |
116 | { | |
117 | var target = document.getElementById(id); | |
118 | if(elem.cacheClassElem) | |
119 | elem.className = elem.cacheClassElem; | |
120 | if(elem.cacheClassTarget) | |
121 | target.className = elem.cacheClassTarget; | |
122 | } | |
123 | /*]]>*///--> | |
124 | </script>" | |
86fbb8ca | 125 | "Basic JavaScript that is needed by HTML files produced by Org-mode.") |
c8d0cf5c CD |
126 | |
127 | (defconst org-export-html-style-default | |
128 | "<style type=\"text/css\"> | |
129 | <!--/*--><![CDATA[/*><!--*/ | |
130 | html { font-family: Times, serif; font-size: 12pt; } | |
131 | .title { text-align: center; } | |
132 | .todo { color: red; } | |
133 | .done { color: green; } | |
134 | .tag { background-color: #add8e6; font-weight:normal } | |
135 | .target { } | |
136 | .timestamp { color: #bebebe; } | |
137 | .timestamp-kwd { color: #5f9ea0; } | |
afe98dfa CD |
138 | .right {margin-left:auto; margin-right:0px; text-align:right;} |
139 | .left {margin-left:0px; margin-right:auto; text-align:left;} | |
140 | .center {margin-left:auto; margin-right:auto; text-align:center;} | |
c8d0cf5c CD |
141 | p.verse { margin-left: 3% } |
142 | pre { | |
143 | border: 1pt solid #AEBDCC; | |
144 | background-color: #F3F5F7; | |
145 | padding: 5pt; | |
146 | font-family: courier, monospace; | |
147 | font-size: 90%; | |
148 | overflow:auto; | |
149 | } | |
150 | table { border-collapse: collapse; } | |
afe98dfa CD |
151 | td, th { vertical-align: top; } |
152 | th.right { text-align:center; } | |
153 | th.left { text-align:center; } | |
154 | th.center { text-align:center; } | |
155 | td.right { text-align:right; } | |
156 | td.left { text-align:left; } | |
157 | td.center { text-align:center; } | |
c8d0cf5c CD |
158 | dt { font-weight: bold; } |
159 | div.figure { padding: 0.5em; } | |
160 | div.figure p { text-align: center; } | |
ed21c5c8 | 161 | textarea { overflow-x: auto; } |
c8d0cf5c CD |
162 | .linenr { font-size:smaller } |
163 | .code-highlighted {background-color:#ffff00;} | |
164 | .org-info-js_info-navigation { border-style:none; } | |
165 | #org-info-js_console-label { font-size:10px; font-weight:bold; | |
166 | white-space:nowrap; } | |
167 | .org-info-js_search-highlight {background-color:#ffff00; color:#000000; | |
168 | font-weight:bold; } | |
169 | /*]]>*/--> | |
170 | </style>" | |
171 | "The default style specification for exported HTML files. | |
172 | Please use the variables `org-export-html-style' and | |
173 | `org-export-html-style-extra' to add to this style. If you wish to not | |
174 | have the default style included, customize the variable | |
175 | `org-export-html-style-include-default'.") | |
176 | ||
177 | (defcustom org-export-html-style-include-default t | |
ed21c5c8 | 178 | "Non-nil means include the default style in exported HTML files. |
c8d0cf5c CD |
179 | The actual style is defined in `org-export-html-style-default' and should |
180 | not be modified. Use the variables `org-export-html-style' to add | |
181 | your own style information." | |
182 | :group 'org-export-html | |
183 | :type 'boolean) | |
184 | ;;;###autoload | |
364bc556 | 185 | (put 'org-export-html-style-include-default 'safe-local-variable 'booleanp) |
c8d0cf5c CD |
186 | |
187 | (defcustom org-export-html-style "" | |
188 | "Org-wide style definitions for exported HTML files. | |
189 | ||
190 | This variable needs to contain the full HTML structure to provide a style, | |
191 | including the surrounding HTML tags. If you set the value of this variable, | |
192 | you should consider to include definitions for the following classes: | |
193 | title, todo, done, timestamp, timestamp-kwd, tag, target. | |
194 | ||
195 | For example, a valid value would be: | |
196 | ||
197 | <style type=\"text/css\"> | |
198 | <![CDATA[ | |
199 | p { font-weight: normal; color: gray; } | |
200 | h1 { color: black; } | |
201 | .title { text-align: center; } | |
202 | .todo, .timestamp-kwd { color: red; } | |
203 | .done { color: green; } | |
204 | ]]> | |
205 | </style> | |
206 | ||
3ab2c837 | 207 | If you'd like to refer to an external style file, use something like |
c8d0cf5c CD |
208 | |
209 | <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\"> | |
210 | ||
211 | As the value of this option simply gets inserted into the HTML <head> header, | |
212 | you can \"misuse\" it to add arbitrary text to the header. | |
213 | See also the variable `org-export-html-style-extra'." | |
214 | :group 'org-export-html | |
215 | :type 'string) | |
216 | ;;;###autoload | |
217 | (put 'org-export-html-style 'safe-local-variable 'stringp) | |
218 | ||
219 | (defcustom org-export-html-style-extra "" | |
220 | "Additional style information for HTML export. | |
221 | The value of this variable is inserted into the HTML buffer right after | |
222 | the value of `org-export-html-style'. Use this variable for per-file | |
223 | settings of style information, and do not forget to surround the style | |
224 | settings with <style>...</style> tags." | |
225 | :group 'org-export-html | |
226 | :type 'string) | |
227 | ;;;###autoload | |
228 | (put 'org-export-html-style-extra 'safe-local-variable 'stringp) | |
229 | ||
afe98dfa CD |
230 | (defcustom org-export-html-mathjax-options |
231 | '((path "http://orgmode.org/mathjax/MathJax.js") | |
232 | (scale "100") | |
233 | (align "center") | |
234 | (indent "2em") | |
235 | (mathml nil)) | |
236 | "Options for MathJax setup. | |
237 | ||
238 | path The path where to find MathJax | |
239 | scale Scaling for the HTML-CSS backend, usually between 100 and 133 | |
240 | align How to align display math: left, center, or right | |
241 | indent If align is not center, how far from the left/right side? | |
242 | mathml Should a MathML player be used if available? | |
243 | This is faster and reduces bandwidth use, but currently | |
244 | sometimes has lower spacing quality. Therefore, the default is | |
245 | nil. When browsers get better, this switch can be flipped. | |
246 | ||
247 | You can also customize this for each buffer, using something like | |
248 | ||
249 | #+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\"" | |
250 | :group 'org-export-html | |
251 | :type '(list :greedy t | |
252 | (list :tag "path (the path from where to load MathJax.js)" | |
253 | (const :format " " path) (string)) | |
254 | (list :tag "scale (scaling for the displayed math)" | |
255 | (const :format " " scale) (string)) | |
256 | (list :tag "align (alignment of displayed equations)" | |
257 | (const :format " " align) (string)) | |
258 | (list :tag "indent (indentation with left or right alignment)" | |
259 | (const :format " " indent) (string)) | |
260 | (list :tag "mathml (should MathML display be used is possible)" | |
261 | (const :format " " mathml) (boolean)))) | |
262 | ||
263 | (defun org-export-html-mathjax-config (template options in-buffer) | |
264 | "Insert the user setup into the matchjax template." | |
265 | (let (name val (yes " ") (no "// ") x) | |
266 | (mapc | |
267 | (lambda (e) | |
268 | (setq name (car e) val (nth 1 e)) | |
269 | (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer) | |
270 | (setq val (car (read-from-string | |
271 | (substring in-buffer (match-end 0)))))) | |
272 | (if (not (stringp val)) (setq val (format "%s" val))) | |
273 | (if (string-match (concat "%" (upcase (symbol-name name))) template) | |
274 | (setq template (replace-match val t t template)))) | |
275 | options) | |
276 | (setq val (nth 1 (assq 'mathml options))) | |
277 | (if (string-match (concat "\\<mathml:") in-buffer) | |
278 | (setq val (car (read-from-string | |
279 | (substring in-buffer (match-end 0)))))) | |
280 | ;; Exchange prefixes depending on mathml setting | |
281 | (if (not val) (setq x yes yes no no x)) | |
282 | ;; Replace cookies to turn on or off the config/jax lines | |
283 | (if (string-match ":MMLYES:" template) | |
284 | (setq template (replace-match yes t t template))) | |
285 | (if (string-match ":MMLNO:" template) | |
286 | (setq template (replace-match no t t template))) | |
287 | ;; Return the modified template | |
288 | template)) | |
289 | ||
290 | (defcustom org-export-html-mathjax-template | |
291 | "<script type=\"text/javascript\" src=\"%PATH\"> | |
292 | <!--/*--><![CDATA[/*><!--*/ | |
293 | MathJax.Hub.Config({ | |
294 | // Only one of the two following lines, depending on user settings | |
295 | // First allows browser-native MathML display, second forces HTML/CSS | |
296 | :MMLYES: config: [\"MMLorHTML.js\"], jax: [\"input/TeX\"], | |
297 | :MMLNO: jax: [\"input/TeX\", \"output/HTML-CSS\"], | |
298 | extensions: [\"tex2jax.js\",\"TeX/AMSmath.js\",\"TeX/AMSsymbols.js\", | |
299 | \"TeX/noUndefined.js\"], | |
300 | tex2jax: { | |
301 | inlineMath: [ [\"\\\\(\",\"\\\\)\"] ], | |
3ab2c837 | 302 | displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"], [\"\\\\begin{displaymath}\",\"\\\\end{displaymath}\"] ], |
afe98dfa CD |
303 | skipTags: [\"script\",\"noscript\",\"style\",\"textarea\",\"pre\",\"code\"], |
304 | ignoreClass: \"tex2jax_ignore\", | |
305 | processEscapes: false, | |
306 | processEnvironments: true, | |
307 | preview: \"TeX\" | |
308 | }, | |
309 | showProcessingMessages: true, | |
310 | displayAlign: \"%ALIGN\", | |
311 | displayIndent: \"%INDENT\", | |
312 | ||
313 | \"HTML-CSS\": { | |
314 | scale: %SCALE, | |
315 | availableFonts: [\"STIX\",\"TeX\"], | |
316 | preferredFont: \"TeX\", | |
317 | webFont: \"TeX\", | |
318 | imageFont: \"TeX\", | |
319 | showMathMenu: true, | |
320 | }, | |
321 | MMLorHTML: { | |
322 | prefer: { | |
323 | MSIE: \"MML\", | |
324 | Firefox: \"MML\", | |
325 | Opera: \"HTML\", | |
326 | other: \"HTML\" | |
327 | } | |
328 | } | |
329 | }); | |
330 | /*]]>*///--> | |
331 | </script>" | |
332 | "The MathJax setup for XHTML files." | |
333 | :group 'org-export-html | |
334 | :type 'string) | |
335 | ||
c8d0cf5c | 336 | (defcustom org-export-html-tag-class-prefix "" |
86fbb8ca | 337 | "Prefix to class names for TODO keywords. |
c8d0cf5c CD |
338 | Each tag gets a class given by the tag itself, with this prefix. |
339 | The default prefix is empty because it is nice to just use the keyword | |
340 | as a class name. But if you get into conflicts with other, existing | |
86fbb8ca | 341 | CSS classes, then this prefix can be very useful." |
c8d0cf5c CD |
342 | :group 'org-export-html |
343 | :type 'string) | |
344 | ||
345 | (defcustom org-export-html-todo-kwd-class-prefix "" | |
86fbb8ca | 346 | "Prefix to class names for TODO keywords. |
c8d0cf5c CD |
347 | Each TODO keyword gets a class given by the keyword itself, with this prefix. |
348 | The default prefix is empty because it is nice to just use the keyword | |
349 | as a class name. But if you get into conflicts with other, existing | |
86fbb8ca | 350 | CSS classes, then this prefix can be very useful." |
c8d0cf5c CD |
351 | :group 'org-export-html |
352 | :type 'string) | |
353 | ||
3ab2c837 BG |
354 | (defcustom org-export-html-preamble t |
355 | "Non-nil means insert a preamble in HTML export. | |
356 | ||
357 | When `t', insert a string as defined by one of the formatting | |
358 | strings in `org-export-html-preamble-format'. When set to a | |
359 | string, this string overrides `org-export-html-preamble-format'. | |
360 | When set to a function, apply this function and insert the | |
361 | returned string. The function takes the property list of export | |
362 | options as its only argument. | |
363 | ||
364 | Setting :html-preamble in publishing projects will take | |
365 | precedence over this variable." | |
366 | :group 'org-export-html | |
367 | :type '(choice (const :tag "No preamble" nil) | |
368 | (const :tag "Default preamble" t) | |
369 | (string :tag "Custom formatting string") | |
370 | (function :tag "Function (must return a string)"))) | |
371 | ||
372 | (defcustom org-export-html-preamble-format '(("en" "")) | |
373 | "The format for the HTML preamble. | |
374 | ||
375 | %t stands for the title. | |
376 | %a stands for the author's name. | |
377 | %e stands for the author's email. | |
378 | %d stands for the date. | |
379 | ||
380 | If you need to use a \"%\" character, you need to escape it | |
381 | like that: \"%%\"." | |
382 | :group 'org-export-html | |
383 | :type 'string) | |
384 | ||
385 | (defcustom org-export-html-postamble 'auto | |
386 | "Non-nil means insert a postamble in HTML export. | |
387 | ||
388 | When `t', insert a string as defined by the formatting string in | |
389 | `org-export-html-postamble-format'. When set to a string, this | |
390 | string overrides `org-export-html-postamble-format'. When set to | |
391 | 'auto, discard `org-export-html-postamble-format' and honor | |
392 | `org-export-author/email/creator-info' variables. When set to a | |
393 | function, apply this function and insert the returned string. | |
394 | The function takes the property list of export options as its | |
395 | only argument. | |
396 | ||
397 | Setting :html-postamble in publishing projects will take | |
398 | precedence over this variable." | |
399 | :group 'org-export-html | |
400 | :type '(choice (const :tag "No postamble" nil) | |
401 | (const :tag "Auto preamble" 'auto) | |
402 | (const :tag "Default formatting string" t) | |
403 | (string :tag "Custom formatting string") | |
404 | (function :tag "Function (must return a string)"))) | |
405 | ||
406 | (defcustom org-export-html-postamble-format | |
407 | '(("en" "<p class=\"author\">Author: %a (%e)</p> | |
408 | <p class=\"date\">Date: %d</p> | |
409 | <p class=\"creator\">Generated by %c</p> | |
410 | <p class=\"xhtml-validation\">%v</p> | |
411 | ")) | |
412 | "The format for the HTML postamble. | |
413 | ||
414 | %a stands for the author's name. | |
415 | %e stands for the author's email. | |
416 | %d stands for the date. | |
417 | %c will be replaced by information about Org/Emacs versions. | |
418 | %v will be replaced by `org-export-html-validation-link'. | |
419 | ||
420 | If you need to use a \"%\" character, you need to escape it | |
421 | like that: \"%%\"." | |
c8d0cf5c CD |
422 | :group 'org-export-html |
423 | :type 'string) | |
424 | ||
425 | (defcustom org-export-html-home/up-format | |
5dec9555 | 426 | "<div id=\"org-div-home-and-up\" style=\"text-align:right;font-size:70%%;white-space:nowrap;\"> |
c8d0cf5c CD |
427 | <a accesskey=\"h\" href=\"%s\"> UP </a> |
428 | | | |
429 | <a accesskey=\"H\" href=\"%s\"> HOME </a> | |
430 | </div>" | |
86fbb8ca CD |
431 | "Snippet used to insert the HOME and UP links. |
432 | This is a format string, the first %s will receive the UP link, | |
433 | the second the HOME link. If both `org-export-html-link-up' and | |
434 | `org-export-html-link-home' are empty, the entire snippet will be | |
435 | ignored." | |
c8d0cf5c CD |
436 | :group 'org-export-html |
437 | :type 'string) | |
438 | ||
439 | (defcustom org-export-html-toplevel-hlevel 2 | |
440 | "The <H> level for level 1 headings in HTML export. | |
441 | This is also important for the classes that will be wrapped around headlines | |
442 | and outline structure. If this variable is 1, the top-level headlines will | |
443 | be <h1>, and the corresponding classes will be outline-1, section-number-1, | |
444 | and outline-text-1. If this is 2, all of these will get a 2 instead. | |
445 | The default for this variable is 2, because we use <h1> for formatting the | |
446 | document title." | |
447 | :group 'org-export-html | |
448 | :type 'string) | |
449 | ||
450 | (defcustom org-export-html-link-org-files-as-html t | |
ed21c5c8 | 451 | "Non-nil means make file links to `file.org' point to `file.html'. |
c8d0cf5c CD |
452 | When org-mode is exporting an org-mode file to HTML, links to |
453 | non-html files are directly put into a href tag in HTML. | |
454 | However, links to other Org-mode files (recognized by the | |
455 | extension `.org.) should become links to the corresponding html | |
456 | file, assuming that the linked org-mode file will also be | |
457 | converted to HTML. | |
458 | When nil, the links still point to the plain `.org' file." | |
459 | :group 'org-export-html | |
460 | :type 'boolean) | |
461 | ||
462 | (defcustom org-export-html-inline-images 'maybe | |
ed21c5c8 | 463 | "Non-nil means inline images into exported HTML pages. |
c8d0cf5c CD |
464 | This is done using an <img> tag. When nil, an anchor with href is used to |
465 | link to the image. If this option is `maybe', then images in links with | |
466 | an empty description will be inlined, while images with a description will | |
467 | be linked only." | |
468 | :group 'org-export-html | |
469 | :type '(choice (const :tag "Never" nil) | |
470 | (const :tag "Always" t) | |
471 | (const :tag "When there is no description" maybe))) | |
472 | ||
473 | (defcustom org-export-html-inline-image-extensions | |
afe98dfa | 474 | '("png" "jpeg" "jpg" "gif" "svg") |
c8d0cf5c CD |
475 | "Extensions of image files that can be inlined into HTML." |
476 | :group 'org-export-html | |
477 | :type '(repeat (string :tag "Extension"))) | |
478 | ||
479 | (defcustom org-export-html-table-tag | |
480 | "<table border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\">" | |
481 | "The HTML tag that is used to start a table. | |
482 | This must be a <table> tag, but you may change the options like | |
483 | borders and spacing." | |
484 | :group 'org-export-html | |
485 | :type 'string) | |
486 | ||
afe98dfa | 487 | (defcustom org-export-table-header-tags '("<th scope=\"%s\"%s>" . "</th>") |
c8d0cf5c CD |
488 | "The opening tag for table header fields. |
489 | This is customizable so that alignment options can be specified. | |
afe98dfa CD |
490 | The first %s will be filled with the scope of the field, either row or col. |
491 | The second %s will be replaced by a style entry to align the field. | |
492 | See also the variable `org-export-html-table-use-header-tags-for-first-column'. | |
493 | See also the variable `org-export-html-table-align-individual-fields'." | |
c8d0cf5c CD |
494 | :group 'org-export-tables |
495 | :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) | |
496 | ||
afe98dfa | 497 | (defcustom org-export-table-data-tags '("<td%s>" . "</td>") |
c8d0cf5c | 498 | "The opening tag for table data fields. |
afe98dfa CD |
499 | This is customizable so that alignment options can be specified. |
500 | The first %s will be filled with the scope of the field, either row or col. | |
501 | The second %s will be replaced by a style entry to align the field. | |
502 | See also the variable `org-export-html-table-align-individual-fields'." | |
c8d0cf5c CD |
503 | :group 'org-export-tables |
504 | :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) | |
505 | ||
506 | (defcustom org-export-table-row-tags '("<tr>" . "</tr>") | |
507 | "The opening tag for table data fields. | |
508 | This is customizable so that alignment options can be specified. | |
509 | Instead of strings, these can be Lisp forms that will be evaluated | |
510 | for each row in order to construct the table row tags. During evaluation, | |
511 | the variable `head' will be true when this is a header line, nil when this | |
512 | is a body line. And the variable `nline' will contain the line number, | |
513 | starting from 1 in the first header line. For example | |
514 | ||
515 | (setq org-export-table-row-tags | |
516 | (cons '(if head | |
517 | \"<tr>\" | |
518 | (if (= (mod nline 2) 1) | |
519 | \"<tr class=\\\"tr-odd\\\">\" | |
520 | \"<tr class=\\\"tr-even\\\">\")) | |
521 | \"</tr>\")) | |
522 | ||
523 | will give even lines the class \"tr-even\" and odd lines the class \"tr-odd\"." | |
524 | :group 'org-export-tables | |
525 | :type '(cons | |
526 | (choice :tag "Opening tag" | |
527 | (string :tag "Specify") | |
528 | (sexp)) | |
529 | (choice :tag "Closing tag" | |
530 | (string :tag "Specify") | |
531 | (sexp)))) | |
532 | ||
afe98dfa CD |
533 | (defcustom org-export-html-table-align-individual-fields t |
534 | "Non-nil means attach style attributes for alignment to each table field. | |
535 | When nil, alignment will only be specified in the column tags, but this | |
536 | is ignored by some browsers (like Firefox, Safari). Opera does it right | |
537 | though." | |
538 | :group 'org-export-tables | |
539 | :type 'boolean) | |
c8d0cf5c CD |
540 | |
541 | (defcustom org-export-html-table-use-header-tags-for-first-column nil | |
ed21c5c8 | 542 | "Non-nil means format column one in tables with header tags. |
c8d0cf5c CD |
543 | When nil, also column one will use data tags." |
544 | :group 'org-export-tables | |
545 | :type 'boolean) | |
546 | ||
3ab2c837 BG |
547 | (defcustom org-export-html-validation-link |
548 | "<a href=\"http://validator.w3.org/check?uri=referer\">Validate XHTML 1.0</a>" | |
549 | "Link to HTML validation service." | |
c8d0cf5c | 550 | :group 'org-export-html |
3ab2c837 | 551 | :type 'string) |
c8d0cf5c | 552 | |
3ab2c837 BG |
553 | ;; FIXME Obsolete since Org 7.7 |
554 | ;; Use the :timestamp option or `org-export-time-stamp-file' instead | |
555 | (defvar org-export-html-with-timestamp nil | |
556 | "If non-nil, write container for HTML-helper-mode timestamp.") | |
557 | ||
558 | ;; FIXME Obsolete since Org 7.7 | |
559 | (defvar org-export-html-html-helper-timestamp | |
560 | "\n<p><br/><br/>\n<!-- hhmts start --> <!-- hhmts end --></p>\n" | |
561 | "The HTML tag used as timestamp delimiter for HTML-helper-mode.") | |
562 | ||
563 | (defcustom org-export-html-protect-char-alist | |
564 | '(("&" . "&") | |
565 | ("<" . "<") | |
566 | (">" . ">")) | |
567 | "Alist of characters to be converted by `org-html-protect'." | |
c8d0cf5c | 568 | :group 'org-export-html |
3ab2c837 BG |
569 | :type '(repeat (cons (string :tag "Character") |
570 | (string :tag "HTML equivalent")))) | |
c8d0cf5c CD |
571 | |
572 | (defgroup org-export-htmlize nil | |
573 | "Options for processing examples with htmlize.el." | |
574 | :tag "Org Export Htmlize" | |
575 | :group 'org-export-html) | |
576 | ||
577 | (defcustom org-export-htmlize-output-type 'inline-css | |
578 | "Output type to be used by htmlize when formatting code snippets. | |
3ab2c837 BG |
579 | Choices are `css', to export the CSS selectors only, or `inline-css', to |
580 | export the CSS attribute values inline in the HTML. We use as default | |
581 | `inline-css', in order to make the resulting HTML self-containing. | |
582 | ||
c8d0cf5c CD |
583 | However, this will fail when using Emacs in batch mode for export, because |
584 | then no rich font definitions are in place. It will also not be good if | |
585 | people with different Emacs setup contribute HTML files to a website, | |
586 | because the fonts will represent the individual setups. In these cases, | |
587 | it is much better to let Org/Htmlize assign classes only, and to use | |
588 | a style file to define the look of these classes. | |
589 | To get a start for your css file, start Emacs session and make sure that | |
590 | all the faces you are interested in are defined, for example by loading files | |
591 | in all modes you want. Then, use the command | |
592 | \\[org-export-htmlize-generate-css] to extract class definitions." | |
593 | :group 'org-export-htmlize | |
594 | :type '(choice (const css) (const inline-css))) | |
595 | ||
596 | (defcustom org-export-htmlize-css-font-prefix "org-" | |
597 | "The prefix for CSS class names for htmlize font specifications." | |
598 | :group 'org-export-htmlize | |
599 | :type 'string) | |
600 | ||
601 | (defcustom org-export-htmlized-org-css-url nil | |
602 | "URL pointing to a CSS file defining text colors for htmlized Emacs buffers. | |
603 | Normally when creating an htmlized version of an Org buffer, htmlize will | |
604 | create CSS to define the font colors. However, this does not work when | |
605 | converting in batch mode, and it also can look bad if different people | |
606 | with different fontification setup work on the same website. | |
607 | When this variable is non-nil, creating an htmlized version of an Org buffer | |
608 | using `org-export-as-org' will remove the internal CSS section and replace it | |
609 | with a link to this URL." | |
610 | :group 'org-export-htmlize | |
611 | :type '(choice | |
612 | (const :tag "Keep internal css" nil) | |
613 | (string :tag "URL or local href"))) | |
614 | ||
3ab2c837 BG |
615 | ;; FIXME: The following variable is obsolete since Org 7.7 but is |
616 | ;; still declared and checked within code for compatibility reasons. | |
617 | ;; Use the custom variables `org-export-html-divs' instead. | |
618 | (defvar org-export-html-content-div "content" | |
619 | "The name of the container DIV that holds all the page contents. | |
620 | ||
621 | This variable is obsolete since Org version 7.7. | |
622 | Please set `org-export-html-divs' instead.") | |
c8d0cf5c | 623 | |
3ab2c837 BG |
624 | (defcustom org-export-html-divs '("preamble" "content" "postamble") |
625 | "The name of the main divs for HTML export." | |
626 | :group 'org-export-html | |
627 | :type '(list | |
628 | (string :tag " Div for the preamble:") | |
629 | (string :tag " Div for the content:") | |
630 | (string :tag "Div for the postamble:"))) | |
c8d0cf5c CD |
631 | |
632 | ;;; Hooks | |
633 | ||
634 | (defvar org-export-html-after-blockquotes-hook nil | |
635 | "Hook run during HTML export, after blockquote, verse, center are done.") | |
636 | ||
8d642074 | 637 | (defvar org-export-html-final-hook nil |
ed21c5c8 | 638 | "Hook run at the end of HTML export, in the new buffer.") |
8d642074 | 639 | |
c8d0cf5c CD |
640 | ;;; HTML export |
641 | ||
642 | (defun org-export-html-preprocess (parameters) | |
86fbb8ca | 643 | "Convert LaTeX fragments to images." |
c8d0cf5c CD |
644 | (when (and org-current-export-file |
645 | (plist-get parameters :LaTeX-fragments)) | |
646 | (org-format-latex | |
647 | (concat "ltxpng/" (file-name-sans-extension | |
648 | (file-name-nondirectory | |
649 | org-current-export-file))) | |
86fbb8ca | 650 | org-current-export-dir nil "Creating LaTeX image %s" |
afe98dfa CD |
651 | nil nil |
652 | (cond | |
653 | ((eq (plist-get parameters :LaTeX-fragments) 'verbatim) 'verbatim) | |
654 | ((eq (plist-get parameters :LaTeX-fragments) 'mathjax ) 'mathjax) | |
655 | ((eq (plist-get parameters :LaTeX-fragments) t ) 'mathjax) | |
656 | ((eq (plist-get parameters :LaTeX-fragments) 'dvipng ) 'dvipng) | |
657 | (t nil)))) | |
ed21c5c8 CD |
658 | (goto-char (point-min)) |
659 | (let (label l1) | |
660 | (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t) | |
661 | (org-if-unprotected-at (match-beginning 1) | |
662 | (setq label (match-string 1)) | |
663 | (save-match-data | |
664 | (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label) | |
665 | (setq l1 (substring label (match-beginning 1))) | |
666 | (setq l1 label))) | |
667 | (replace-match (format "[[#%s][%s]]" label l1) t t))))) | |
c8d0cf5c CD |
668 | |
669 | ;;;###autoload | |
670 | (defun org-export-as-html-and-open (arg) | |
671 | "Export the outline as HTML and immediately open it with a browser. | |
672 | If there is an active region, export only the region. | |
673 | The prefix ARG specifies how many levels of the outline should become | |
674 | headlines. The default is 3. Lower levels will become bulleted lists." | |
675 | (interactive "P") | |
676 | (org-export-as-html arg 'hidden) | |
ed21c5c8 CD |
677 | (org-open-file buffer-file-name) |
678 | (when org-export-kill-product-buffer-when-displayed | |
86fbb8ca | 679 | (kill-buffer (current-buffer)))) |
c8d0cf5c CD |
680 | |
681 | ;;;###autoload | |
682 | (defun org-export-as-html-batch () | |
86fbb8ca CD |
683 | "Call the function `org-export-as-html'. |
684 | This function can be used in batch processing as: | |
c8d0cf5c CD |
685 | emacs --batch |
686 | --load=$HOME/lib/emacs/org.el | |
687 | --eval \"(setq org-export-headline-levels 2)\" | |
688 | --visit=MyFile --funcall org-export-as-html-batch" | |
689 | (org-export-as-html org-export-headline-levels 'hidden)) | |
690 | ||
691 | ;;;###autoload | |
692 | (defun org-export-as-html-to-buffer (arg) | |
693 | "Call `org-export-as-html` with output to a temporary buffer. | |
694 | No file is created. The prefix ARG is passed through to `org-export-as-html'." | |
695 | (interactive "P") | |
696 | (org-export-as-html arg nil nil "*Org HTML Export*") | |
697 | (when org-export-show-temporary-export-buffer | |
698 | (switch-to-buffer-other-window "*Org HTML Export*"))) | |
699 | ||
700 | ;;;###autoload | |
701 | (defun org-replace-region-by-html (beg end) | |
702 | "Assume the current region has org-mode syntax, and convert it to HTML. | |
703 | This can be used in any buffer. For example, you could write an | |
704 | itemized list in org-mode syntax in an HTML buffer and then use this | |
705 | command to convert it." | |
706 | (interactive "r") | |
707 | (let (reg html buf pop-up-frames) | |
708 | (save-window-excursion | |
709 | (if (org-mode-p) | |
710 | (setq html (org-export-region-as-html | |
711 | beg end t 'string)) | |
712 | (setq reg (buffer-substring beg end) | |
713 | buf (get-buffer-create "*Org tmp*")) | |
714 | (with-current-buffer buf | |
715 | (erase-buffer) | |
716 | (insert reg) | |
717 | (org-mode) | |
718 | (setq html (org-export-region-as-html | |
719 | (point-min) (point-max) t 'string))) | |
720 | (kill-buffer buf))) | |
721 | (delete-region beg end) | |
722 | (insert html))) | |
723 | ||
724 | ;;;###autoload | |
725 | (defun org-export-region-as-html (beg end &optional body-only buffer) | |
726 | "Convert region from BEG to END in org-mode buffer to HTML. | |
727 | If prefix arg BODY-ONLY is set, omit file header, footer, and table of | |
728 | contents, and only produce the region of converted text, useful for | |
729 | cut-and-paste operations. | |
730 | If BUFFER is a buffer or a string, use/create that buffer as a target | |
731 | of the converted HTML. If BUFFER is the symbol `string', return the | |
732 | produced HTML as a string and leave not buffer behind. For example, | |
733 | a Lisp program could call this function in the following way: | |
734 | ||
735 | (setq html (org-export-region-as-html beg end t 'string)) | |
736 | ||
737 | When called interactively, the output buffer is selected, and shown | |
738 | in a window. A non-interactive call will only return the buffer." | |
739 | (interactive "r\nP") | |
3ab2c837 | 740 | (when (org-called-interactively-p 'any) |
c8d0cf5c CD |
741 | (setq buffer "*Org HTML Export*")) |
742 | (let ((transient-mark-mode t) (zmacs-regions t) | |
743 | ext-plist rtn) | |
8bfe682a | 744 | (setq ext-plist (plist-put ext-plist :ignore-subtree-p t)) |
c8d0cf5c CD |
745 | (goto-char end) |
746 | (set-mark (point)) ;; to activate the region | |
747 | (goto-char beg) | |
748 | (setq rtn (org-export-as-html | |
749 | nil nil ext-plist | |
750 | buffer body-only)) | |
751 | (if (fboundp 'deactivate-mark) (deactivate-mark)) | |
3ab2c837 | 752 | (if (and (org-called-interactively-p 'any) (bufferp rtn)) |
c8d0cf5c CD |
753 | (switch-to-buffer-other-window rtn) |
754 | rtn))) | |
755 | ||
756 | (defvar html-table-tag nil) ; dynamically scoped into this. | |
757 | (defvar org-par-open nil) | |
86fbb8ca CD |
758 | |
759 | ;;; org-html-cvt-link-fn | |
760 | (defconst org-html-cvt-link-fn | |
761 | nil | |
762 | "Function to convert link URLs to exportable URLs. | |
763 | Takes two arguments, TYPE and PATH. | |
764 | Returns exportable url as (TYPE PATH), or nil to signal that it | |
765 | didn't handle this case. | |
766 | Intended to be locally bound around a call to `org-export-as-html'." ) | |
767 | ||
768 | (defun org-html-cvt-org-as-html (opt-plist type path) | |
769 | "Convert an org filename to an equivalent html filename. | |
770 | If TYPE is not file, just return `nil'. | |
771 | See variable `org-export-html-link-org-files-as-html'" | |
772 | ||
773 | (save-match-data | |
774 | (and | |
775 | org-export-html-link-org-files-as-html | |
776 | (string= type "file") | |
777 | (string-match "\\.org$" path) | |
778 | (progn | |
779 | (list | |
afe98dfa | 780 | "file" |
86fbb8ca CD |
781 | (concat |
782 | (substring path 0 (match-beginning 0)) | |
783 | "." | |
784 | (plist-get opt-plist :html-extension))))))) | |
785 | ||
786 | ||
787 | ;;; org-html-should-inline-p | |
788 | (defun org-html-should-inline-p (filename descp) | |
789 | "Return non-nil if link FILENAME should be inlined. | |
790 | The decision to inline the FILENAME link is based on the current | |
791 | settings. DESCP is the boolean of whether there was a link | |
792 | description. See variables `org-export-html-inline-images' and | |
793 | `org-export-html-inline-image-extensions'." | |
794 | (declare (special | |
795 | org-export-html-inline-images | |
796 | org-export-html-inline-image-extensions)) | |
afe98dfa CD |
797 | (and (or (eq t org-export-html-inline-images) |
798 | (and org-export-html-inline-images (not descp))) | |
799 | (org-file-image-p | |
800 | filename org-export-html-inline-image-extensions))) | |
86fbb8ca CD |
801 | |
802 | ;;; org-html-make-link | |
803 | (defun org-html-make-link (opt-plist type path fragment desc attr | |
804 | may-inline-p) | |
805 | "Make an HTML link. | |
806 | OPT-PLIST is an options list. | |
807 | TYPE is the device-type of the link (THIS://foo.html) | |
808 | PATH is the path of the link (http://THIS#locationx) | |
809 | FRAGMENT is the fragment part of the link, if any (foo.html#THIS) | |
810 | DESC is the link description, if any. | |
811 | ATTR is a string of other attributes of the a element. | |
812 | MAY-INLINE-P allows inlining it as an image." | |
813 | ||
814 | (declare (special org-par-open)) | |
815 | (save-match-data | |
816 | (let* ((filename path) | |
817 | ;;First pass. Just sanity stuff. | |
818 | (components-1 | |
819 | (cond | |
820 | ((string= type "file") | |
821 | (list | |
822 | type | |
823 | ;;Substitute just if original path was absolute. | |
824 | ;;(Otherwise path must remain relative) | |
825 | (if (file-name-absolute-p path) | |
afe98dfa | 826 | (concat "file://" (expand-file-name path)) |
86fbb8ca CD |
827 | path))) |
828 | ((string= type "") | |
829 | (list nil path)) | |
830 | (t (list type path)))) | |
831 | ||
832 | ;;Second pass. Components converted so they can refer | |
833 | ;;to a remote site. | |
834 | (components-2 | |
835 | (or | |
836 | (and org-html-cvt-link-fn | |
837 | (apply org-html-cvt-link-fn | |
838 | opt-plist components-1)) | |
839 | (apply #'org-html-cvt-org-as-html | |
840 | opt-plist components-1) | |
841 | components-1)) | |
842 | (type (first components-2)) | |
843 | (thefile (second components-2))) | |
844 | ||
845 | ||
846 | ;;Third pass. Build final link except for leading type | |
847 | ;;spec. | |
848 | (cond | |
849 | ((or | |
850 | (not type) | |
851 | (string= type "http") | |
afe98dfa | 852 | (string= type "https") |
3ab2c837 BG |
853 | (string= type "file") |
854 | (string= type "coderef")) | |
86fbb8ca CD |
855 | (if fragment |
856 | (setq thefile (concat thefile "#" fragment)))) | |
857 | ||
858 | (t)) | |
859 | ||
860 | ;;Final URL-build, for all types. | |
861 | (setq thefile | |
862 | (let | |
863 | ((str (org-export-html-format-href thefile))) | |
3ab2c837 BG |
864 | (if (and type (not (or (string= "file" type) |
865 | (string= "coderef" type)))) | |
86fbb8ca CD |
866 | (concat type ":" str) |
867 | str))) | |
868 | ||
869 | (if (and | |
870 | may-inline-p | |
871 | ;;Can't inline a URL with a fragment. | |
872 | (not fragment)) | |
873 | (progn | |
874 | (message "image %s %s" thefile org-par-open) | |
875 | (org-export-html-format-image thefile org-par-open)) | |
876 | (concat | |
3ab2c837 | 877 | "<a href=\"" thefile "\"" (if attr (concat " " attr)) ">" |
86fbb8ca CD |
878 | (org-export-html-format-desc desc) |
879 | "</a>"))))) | |
880 | ||
3ab2c837 BG |
881 | (defun org-html-handle-links (line opt-plist) |
882 | "Return LINE with markup of Org mode links. | |
883 | OPT-PLIST is the export options list." | |
884 | (let ((start 0) | |
885 | (current-dir (if buffer-file-name | |
886 | (file-name-directory buffer-file-name) | |
887 | default-directory)) | |
888 | (link-validate (plist-get opt-plist :link-validation-function)) | |
889 | type id-file fnc | |
890 | rpl path attr desc descp desc1 desc2 link) | |
891 | (while (string-match org-bracket-link-analytic-regexp++ line start) | |
892 | (setq start (match-beginning 0)) | |
893 | (setq path (save-match-data (org-link-unescape | |
894 | (match-string 3 line)))) | |
895 | (setq type (cond | |
896 | ((match-end 2) (match-string 2 line)) | |
897 | ((save-match-data | |
898 | (or (file-name-absolute-p path) | |
899 | (string-match "^\\.\\.?/" path))) | |
900 | "file") | |
901 | (t "internal"))) | |
902 | (setq path (org-extract-attributes (org-link-unescape path))) | |
903 | (setq attr (get-text-property 0 'org-attributes path)) | |
904 | (setq desc1 (if (match-end 5) (match-string 5 line)) | |
905 | desc2 (if (match-end 2) (concat type ":" path) path) | |
906 | descp (and desc1 (not (equal desc1 desc2))) | |
907 | desc (or desc1 desc2)) | |
908 | ;; Make an image out of the description if that is so wanted | |
909 | (when (and descp (org-file-image-p | |
910 | desc org-export-html-inline-image-extensions)) | |
911 | (save-match-data | |
912 | (if (string-match "^file:" desc) | |
913 | (setq desc (substring desc (match-end 0))))) | |
914 | (setq desc (org-add-props | |
915 | (concat "<img src=\"" desc "\" alt=\"" | |
916 | (file-name-nondirectory desc) "\"/>") | |
917 | '(org-protected t)))) | |
918 | (cond | |
919 | ((equal type "internal") | |
920 | (let | |
921 | ((frag-0 | |
922 | (if (= (string-to-char path) ?#) | |
923 | (substring path 1) | |
924 | path))) | |
925 | (setq rpl | |
926 | (org-html-make-link | |
927 | opt-plist | |
928 | "" | |
929 | "" | |
930 | (org-solidify-link-text | |
931 | (save-match-data (org-link-unescape frag-0)) | |
932 | nil) | |
933 | desc attr nil)))) | |
934 | ((and (equal type "id") | |
935 | (setq id-file (org-id-find-id-file path))) | |
936 | ;; This is an id: link to another file (if it was the same file, | |
937 | ;; it would have become an internal link...) | |
938 | (save-match-data | |
939 | (setq id-file (file-relative-name | |
940 | id-file | |
941 | (file-name-directory org-current-export-file))) | |
942 | (setq rpl | |
943 | (org-html-make-link opt-plist | |
944 | "file" id-file | |
945 | (concat (if (org-uuidgen-p path) "ID-") path) | |
946 | desc | |
947 | attr | |
948 | nil)))) | |
949 | ((member type '("http" "https")) | |
950 | ;; standard URL, can inline as image | |
951 | (setq rpl | |
952 | (org-html-make-link opt-plist | |
953 | type path nil | |
954 | desc | |
955 | attr | |
956 | (org-html-should-inline-p path descp)))) | |
957 | ((member type '("ftp" "mailto" "news")) | |
958 | ;; standard URL, can't inline as image | |
959 | (setq rpl | |
960 | (org-html-make-link opt-plist | |
961 | type path nil | |
962 | desc | |
963 | attr | |
964 | nil))) | |
965 | ||
966 | ((string= type "coderef") | |
967 | (let* | |
968 | ((coderef-str (format "coderef-%s" path)) | |
969 | (attr-1 | |
970 | (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\"" | |
971 | coderef-str coderef-str))) | |
972 | (setq rpl | |
973 | (org-html-make-link opt-plist | |
974 | type "" coderef-str | |
975 | (format | |
976 | (org-export-get-coderef-format | |
977 | path | |
978 | (and descp desc)) | |
979 | (cdr (assoc path org-export-code-refs))) | |
980 | attr-1 | |
981 | nil)))) | |
982 | ||
983 | ((functionp (setq fnc (nth 2 (assoc type org-link-protocols)))) | |
984 | ;; The link protocol has a function for format the link | |
985 | (setq rpl | |
986 | (save-match-data | |
987 | (funcall fnc (org-link-unescape path) desc1 'html)))) | |
988 | ||
989 | ((string= type "file") | |
990 | ;; FILE link | |
991 | (save-match-data | |
992 | (let* | |
993 | ((components | |
994 | (if | |
995 | (string-match "::\\(.*\\)" path) | |
996 | (list | |
997 | (replace-match "" t nil path) | |
998 | (match-string 1 path)) | |
999 | (list path nil))) | |
1000 | ||
1001 | ;;The proper path, without a fragment | |
1002 | (path-1 | |
1003 | (first components)) | |
1004 | ||
1005 | ;;The raw fragment | |
1006 | (fragment-0 | |
1007 | (second components)) | |
1008 | ||
1009 | ;;Check the fragment. If it can't be used as | |
1010 | ;;target fragment we'll pass nil instead. | |
1011 | (fragment-1 | |
1012 | (if | |
1013 | (and fragment-0 | |
1014 | (not (string-match "^[0-9]*$" fragment-0)) | |
1015 | (not (string-match "^\\*" fragment-0)) | |
1016 | (not (string-match "^/.*/$" fragment-0))) | |
1017 | (org-solidify-link-text | |
1018 | (org-link-unescape fragment-0)) | |
1019 | nil)) | |
1020 | (desc-2 | |
1021 | ;;Description minus "file:" and ".org" | |
1022 | (if (string-match "^file:" desc) | |
1023 | (let | |
1024 | ((desc-1 (replace-match "" t t desc))) | |
1025 | (if (string-match "\\.org$" desc-1) | |
1026 | (replace-match "" t t desc-1) | |
1027 | desc-1)) | |
1028 | desc))) | |
1029 | ||
1030 | (setq rpl | |
1031 | (if | |
1032 | (and | |
1033 | (functionp link-validate) | |
1034 | (not (funcall link-validate path-1 current-dir))) | |
1035 | desc | |
1036 | (org-html-make-link opt-plist | |
1037 | "file" path-1 fragment-1 desc-2 attr | |
1038 | (org-html-should-inline-p path-1 descp))))))) | |
1039 | ||
1040 | (t | |
1041 | ;; just publish the path, as default | |
1042 | (setq rpl (concat "@<i><" type ":" | |
1043 | (save-match-data (org-link-unescape path)) | |
1044 | ">@</i>")))) | |
1045 | (setq line (replace-match rpl t t line) | |
1046 | start (+ start (length rpl)))) | |
1047 | line)) | |
1048 | ||
86fbb8ca | 1049 | ;;; org-export-as-html |
c8d0cf5c CD |
1050 | ;;;###autoload |
1051 | (defun org-export-as-html (arg &optional hidden ext-plist | |
1052 | to-buffer body-only pub-dir) | |
1053 | "Export the outline as a pretty HTML file. | |
1054 | If there is an active region, export only the region. The prefix | |
1055 | ARG specifies how many levels of the outline should become | |
1056 | headlines. The default is 3. Lower levels will become bulleted | |
1057 | lists. HIDDEN is obsolete and does nothing. | |
1058 | EXT-PLIST is a property list with external parameters overriding | |
1059 | org-mode's default settings, but still inferior to file-local | |
1060 | settings. When TO-BUFFER is non-nil, create a buffer with that | |
1061 | name and export to that buffer. If TO-BUFFER is the symbol | |
1062 | `string', don't leave any buffer behind but just return the | |
1063 | resulting HTML as a string. When BODY-ONLY is set, don't produce | |
1064 | the file header and footer, simply return the content of | |
1065 | <body>...</body>, without even the body tags themselves. When | |
1066 | PUB-DIR is set, use this as the publishing directory." | |
1067 | (interactive "P") | |
ed21c5c8 | 1068 | (run-hooks 'org-export-first-hook) |
c8d0cf5c CD |
1069 | |
1070 | ;; Make sure we have a file name when we need it. | |
1071 | (when (and (not (or to-buffer body-only)) | |
1072 | (not buffer-file-name)) | |
1073 | (if (buffer-base-buffer) | |
1074 | (org-set-local 'buffer-file-name | |
1075 | (with-current-buffer (buffer-base-buffer) | |
1076 | buffer-file-name)) | |
f924a367 | 1077 | (error "Need a file name to be able to export"))) |
c8d0cf5c CD |
1078 | |
1079 | (message "Exporting...") | |
1080 | (setq-default org-todo-line-regexp org-todo-line-regexp) | |
1081 | (setq-default org-deadline-line-regexp org-deadline-line-regexp) | |
1082 | (setq-default org-done-keywords org-done-keywords) | |
1083 | (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp) | |
1084 | (let* ((opt-plist | |
1085 | (org-export-process-option-filters | |
1086 | (org-combine-plists (org-default-export-plist) | |
1087 | ext-plist | |
1088 | (org-infile-export-plist)))) | |
1089 | (body-only (or body-only (plist-get opt-plist :body-only))) | |
1090 | (style (concat (if (plist-get opt-plist :style-include-default) | |
1091 | org-export-html-style-default) | |
1092 | (plist-get opt-plist :style) | |
1093 | (plist-get opt-plist :style-extra) | |
1094 | "\n" | |
1095 | (if (plist-get opt-plist :style-include-scripts) | |
1096 | org-export-html-scripts))) | |
1097 | (html-extension (plist-get opt-plist :html-extension)) | |
c8d0cf5c CD |
1098 | valid thetoc have-headings first-heading-pos |
1099 | (odd org-odd-levels-only) | |
1100 | (region-p (org-region-active-p)) | |
1101 | (rbeg (and region-p (region-beginning))) | |
1102 | (rend (and region-p (region-end))) | |
1103 | (subtree-p | |
8bfe682a | 1104 | (if (plist-get opt-plist :ignore-subtree-p) |
c8d0cf5c CD |
1105 | nil |
1106 | (when region-p | |
1107 | (save-excursion | |
1108 | (goto-char rbeg) | |
1109 | (and (org-at-heading-p) | |
1110 | (>= (org-end-of-subtree t t) rend)))))) | |
1111 | (level-offset (if subtree-p | |
1112 | (save-excursion | |
1113 | (goto-char rbeg) | |
1114 | (+ (funcall outline-level) | |
1115 | (if org-odd-levels-only 1 0))) | |
1116 | 0)) | |
1117 | (opt-plist (setq org-export-opt-plist | |
1118 | (if subtree-p | |
1119 | (org-export-add-subtree-options opt-plist rbeg) | |
1120 | opt-plist))) | |
1121 | ;; The following two are dynamically scoped into other | |
1122 | ;; routines below. | |
1123 | (org-current-export-dir | |
1124 | (or pub-dir (org-export-directory :html opt-plist))) | |
1125 | (org-current-export-file buffer-file-name) | |
1126 | (level 0) (line "") (origline "") txt todo | |
1127 | (umax nil) | |
1128 | (umax-toc nil) | |
1129 | (filename (if to-buffer nil | |
1130 | (expand-file-name | |
1131 | (concat | |
1132 | (file-name-sans-extension | |
1133 | (or (and subtree-p | |
1134 | (org-entry-get (region-beginning) | |
1135 | "EXPORT_FILE_NAME" t)) | |
1136 | (file-name-nondirectory buffer-file-name))) | |
1137 | "." html-extension) | |
1138 | (file-name-as-directory | |
1139 | (or pub-dir (org-export-directory :html opt-plist)))))) | |
1140 | (current-dir (if buffer-file-name | |
1141 | (file-name-directory buffer-file-name) | |
1142 | default-directory)) | |
1143 | (buffer (if to-buffer | |
1144 | (cond | |
1145 | ((eq to-buffer 'string) (get-buffer-create "*Org HTML Export*")) | |
1146 | (t (get-buffer-create to-buffer))) | |
1147 | (find-file-noselect filename))) | |
1148 | (org-levels-open (make-vector org-level-max nil)) | |
1149 | (date (plist-get opt-plist :date)) | |
1150 | (author (plist-get opt-plist :author)) | |
3ab2c837 BG |
1151 | (html-validation-link (or org-export-html-validation-link "")) |
1152 | (title (org-html-expand | |
1153 | (or (and subtree-p (org-export-get-title-from-subtree)) | |
1154 | (plist-get opt-plist :title) | |
1155 | (and (not body-only) | |
1156 | (not | |
1157 | (plist-get opt-plist :skip-before-1st-heading)) | |
1158 | (org-export-grab-title-from-buffer)) | |
1159 | (and buffer-file-name | |
1160 | (file-name-sans-extension | |
1161 | (file-name-nondirectory buffer-file-name))) | |
1162 | "UNTITLED"))) | |
c8d0cf5c CD |
1163 | (link-up (and (plist-get opt-plist :link-up) |
1164 | (string-match "\\S-" (plist-get opt-plist :link-up)) | |
1165 | (plist-get opt-plist :link-up))) | |
1166 | (link-home (and (plist-get opt-plist :link-home) | |
afe98dfa CD |
1167 | (string-match "\\S-" (plist-get opt-plist :link-home)) |
1168 | (plist-get opt-plist :link-home))) | |
c8d0cf5c CD |
1169 | (dummy (setq opt-plist (plist-put opt-plist :title title))) |
1170 | (html-table-tag (plist-get opt-plist :html-table-tag)) | |
1171 | (quote-re0 (concat "^[ \t]*" org-quote-string "\\>")) | |
1172 | (quote-re (concat "^\\(\\*+\\)\\([ \t]+" org-quote-string "\\>\\)")) | |
1173 | (inquote nil) | |
1174 | (infixed nil) | |
1175 | (inverse nil) | |
c8d0cf5c CD |
1176 | (email (plist-get opt-plist :email)) |
1177 | (language (plist-get opt-plist :language)) | |
1178 | (keywords (plist-get opt-plist :keywords)) | |
1179 | (description (plist-get opt-plist :description)) | |
3ab2c837 | 1180 | (num (plist-get opt-plist :section-numbers)) |
c8d0cf5c CD |
1181 | (lang-words nil) |
1182 | (head-count 0) cnt | |
1183 | (start 0) | |
1184 | (coding-system (and (boundp 'buffer-file-coding-system) | |
1185 | buffer-file-coding-system)) | |
1186 | (coding-system-for-write (or org-export-html-coding-system | |
1187 | coding-system)) | |
1188 | (save-buffer-coding-system (or org-export-html-coding-system | |
1189 | coding-system)) | |
1190 | (charset (and coding-system-for-write | |
1191 | (fboundp 'coding-system-get) | |
1192 | (coding-system-get coding-system-for-write | |
1193 | 'mime-charset))) | |
1194 | (region | |
1195 | (buffer-substring | |
1196 | (if region-p (region-beginning) (point-min)) | |
1197 | (if region-p (region-end) (point-max)))) | |
afe98dfa | 1198 | (org-export-have-math nil) |
3ab2c837 BG |
1199 | (org-export-footnotes-seen nil) |
1200 | (org-export-footnotes-data (org-footnote-all-labels 'with-defs)) | |
c8d0cf5c CD |
1201 | (lines |
1202 | (org-split-string | |
1203 | (org-export-preprocess-string | |
1204 | region | |
1205 | :emph-multiline t | |
3ab2c837 | 1206 | :for-backend 'html |
c8d0cf5c CD |
1207 | :skip-before-1st-heading |
1208 | (plist-get opt-plist :skip-before-1st-heading) | |
1209 | :drawers (plist-get opt-plist :drawers) | |
1210 | :todo-keywords (plist-get opt-plist :todo-keywords) | |
3ab2c837 | 1211 | :tasks (plist-get opt-plist :tasks) |
c8d0cf5c CD |
1212 | :tags (plist-get opt-plist :tags) |
1213 | :priority (plist-get opt-plist :priority) | |
1214 | :footnotes (plist-get opt-plist :footnotes) | |
1215 | :timestamps (plist-get opt-plist :timestamps) | |
1216 | :archived-trees | |
1217 | (plist-get opt-plist :archived-trees) | |
1218 | :select-tags (plist-get opt-plist :select-tags) | |
1219 | :exclude-tags (plist-get opt-plist :exclude-tags) | |
1220 | :add-text | |
1221 | (plist-get opt-plist :text) | |
1222 | :LaTeX-fragments | |
1223 | (plist-get opt-plist :LaTeX-fragments)) | |
1224 | "[\r\n]")) | |
afe98dfa CD |
1225 | (mathjax |
1226 | (if (or (eq (plist-get opt-plist :LaTeX-fragments) 'mathjax) | |
1227 | (and org-export-have-math | |
1228 | (eq (plist-get opt-plist :LaTeX-fragments) t))) | |
1229 | ||
1230 | (org-export-html-mathjax-config | |
1231 | org-export-html-mathjax-template | |
1232 | org-export-html-mathjax-options | |
1233 | (or (plist-get opt-plist :mathjax) "")) | |
1234 | "")) | |
3ab2c837 | 1235 | table-open |
c8d0cf5c | 1236 | table-buffer table-orig-buffer |
3ab2c837 | 1237 | ind |
c8d0cf5c | 1238 | rpl path attr desc descp desc1 desc2 link |
3ab2c837 | 1239 | snumber fnc |
c8d0cf5c | 1240 | footnotes footref-seen |
3ab2c837 | 1241 | href |
c8d0cf5c CD |
1242 | ) |
1243 | ||
1244 | (let ((inhibit-read-only t)) | |
1245 | (org-unmodified | |
1246 | (remove-text-properties (point-min) (point-max) | |
1247 | '(:org-license-to-kill t)))) | |
1248 | ||
1249 | (message "Exporting...") | |
1250 | ||
1251 | (setq org-min-level (org-get-min-level lines level-offset)) | |
1252 | (setq org-last-level org-min-level) | |
1253 | (org-init-section-numbers) | |
1254 | ||
1255 | (cond | |
1256 | ((and date (string-match "%" date)) | |
1257 | (setq date (format-time-string date))) | |
1258 | (date) | |
1259 | (t (setq date (format-time-string "%Y-%m-%d %T %Z")))) | |
1260 | ||
1261 | ;; Get the language-dependent settings | |
1262 | (setq lang-words (or (assoc language org-export-language-setup) | |
1263 | (assoc "en" org-export-language-setup))) | |
1264 | ||
1265 | ;; Switch to the output buffer | |
1266 | (set-buffer buffer) | |
1267 | (let ((inhibit-read-only t)) (erase-buffer)) | |
1268 | (fundamental-mode) | |
1269 | (org-install-letbind) | |
1270 | ||
1271 | (and (fboundp 'set-buffer-file-coding-system) | |
1272 | (set-buffer-file-coding-system coding-system-for-write)) | |
1273 | ||
1274 | (let ((case-fold-search nil) | |
1275 | (org-odd-levels-only odd)) | |
1276 | ;; create local variables for all options, to make sure all called | |
1277 | ;; functions get the correct information | |
1278 | (mapc (lambda (x) | |
1279 | (set (make-local-variable (nth 2 x)) | |
1280 | (plist-get opt-plist (car x)))) | |
1281 | org-export-plist-vars) | |
1282 | (setq umax (if arg (prefix-numeric-value arg) | |
1283 | org-export-headline-levels)) | |
1284 | (setq umax-toc (if (integerp org-export-with-toc) | |
1285 | (min org-export-with-toc umax) | |
1286 | umax)) | |
1287 | (unless body-only | |
1288 | ;; File header | |
1289 | (insert (format | |
1290 | "%s | |
1291 | <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" | |
1292 | \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> | |
1293 | <html xmlns=\"http://www.w3.org/1999/xhtml\" | |
1294 | lang=\"%s\" xml:lang=\"%s\"> | |
1295 | <head> | |
c8d0cf5c CD |
1296 | <title>%s</title> |
1297 | <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/> | |
1298 | <meta name=\"generator\" content=\"Org-mode\"/> | |
1299 | <meta name=\"generated\" content=\"%s\"/> | |
1300 | <meta name=\"author\" content=\"%s\"/> | |
1301 | <meta name=\"description\" content=\"%s\"/> | |
1302 | <meta name=\"keywords\" content=\"%s\"/> | |
1303 | %s | |
afe98dfa | 1304 | %s |
c8d0cf5c CD |
1305 | </head> |
1306 | <body> | |
5dec9555 | 1307 | %s |
c8d0cf5c CD |
1308 | " |
1309 | (format | |
1310 | (or (and (stringp org-export-html-xml-declaration) | |
1311 | org-export-html-xml-declaration) | |
1312 | (cdr (assoc html-extension org-export-html-xml-declaration)) | |
1313 | (cdr (assoc "html" org-export-html-xml-declaration)) | |
1314 | ||
1315 | "") | |
1316 | (or charset "iso-8859-1")) | |
1317 | language language | |
86fbb8ca | 1318 | title |
5dec9555 CD |
1319 | (or charset "iso-8859-1") |
1320 | date author description keywords | |
1321 | style | |
afe98dfa | 1322 | mathjax |
c8d0cf5c CD |
1323 | (if (or link-up link-home) |
1324 | (concat | |
1325 | (format org-export-html-home/up-format | |
1326 | (or link-up link-home) | |
1327 | (or link-home link-up)) | |
1328 | "\n") | |
5dec9555 | 1329 | ""))) |
c8d0cf5c | 1330 | |
3ab2c837 BG |
1331 | ;; insert html preamble |
1332 | (when (plist-get opt-plist :html-preamble) | |
1333 | (let ((html-pre (plist-get opt-plist :html-preamble))) | |
1334 | (insert "<div id=\"" (nth 0 org-export-html-divs) "\">\n") | |
1335 | (cond ((stringp html-pre) | |
1336 | (insert | |
1337 | (format-spec html-pre `((?t . ,title) (?a . ,author) | |
1338 | (?d . ,date) (?e . ,email))))) | |
1339 | ((functionp html-pre) | |
1340 | (funcall html-pre)) | |
1341 | (t | |
1342 | (insert | |
1343 | (format-spec | |
1344 | (or (cadr (assoc (nth 0 lang-words) | |
1345 | org-export-html-preamble-format)) | |
1346 | (cadr (assoc "en" org-export-html-preamble-format))) | |
1347 | `((?t . ,title) (?a . ,author) | |
1348 | (?d . ,date) (?e . ,email)))))) | |
1349 | (insert "\n</div>\n"))) | |
1350 | ||
1351 | ;; begin wrap around body | |
1352 | (insert (format "\n<div id=\"%s\">" | |
1353 | ;; FIXME org-export-html-content-div is obsolete since 7.7 | |
1354 | (or org-export-html-content-div | |
1355 | (nth 1 org-export-html-divs))) | |
1356 | ;; FIXME this should go in the preamble but is here so | |
1357 | ;; that org-infojs can still find it | |
1358 | "\n<h1 class=\"title\">" title "</h1>\n")) | |
1359 | ||
1360 | ;; insert body | |
c8d0cf5c CD |
1361 | (if (and org-export-with-toc (not body-only)) |
1362 | (progn | |
1363 | (push (format "<h%d>%s</h%d>\n" | |
1364 | org-export-html-toplevel-hlevel | |
1365 | (nth 3 lang-words) | |
1366 | org-export-html-toplevel-hlevel) | |
1367 | thetoc) | |
1368 | (push "<div id=\"text-table-of-contents\">\n" thetoc) | |
1369 | (push "<ul>\n<li>" thetoc) | |
1370 | (setq lines | |
3ab2c837 BG |
1371 | (mapcar |
1372 | #'(lambda (line) | |
1373 | (if (and (string-match org-todo-line-regexp line) | |
1374 | (not (get-text-property 0 'org-protected line))) | |
1375 | ;; This is a headline | |
1376 | (progn | |
1377 | (setq have-headings t) | |
1378 | (setq level (- (match-end 1) (match-beginning 1) | |
1379 | level-offset) | |
1380 | level (org-tr-level level) | |
1381 | txt (save-match-data | |
1382 | (org-html-expand | |
1383 | (org-export-cleanup-toc-line | |
1384 | (match-string 3 line)))) | |
1385 | todo | |
1386 | (or (and org-export-mark-todo-in-toc | |
1387 | (match-beginning 2) | |
1388 | (not (member (match-string 2 line) | |
1389 | org-done-keywords))) | |
c8d0cf5c | 1390 | ; TODO, not DONE |
3ab2c837 BG |
1391 | (and org-export-mark-todo-in-toc |
1392 | (= level umax-toc) | |
1393 | (org-search-todo-below | |
1394 | line lines level)))) | |
1395 | (if (string-match | |
1396 | (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt) | |
1397 | (setq txt (replace-match | |
1398 | " <span class=\"tag\"> \\1</span>" t nil txt))) | |
1399 | (if (string-match quote-re0 txt) | |
1400 | (setq txt (replace-match "" t t txt))) | |
1401 | (setq snumber (org-section-number level)) | |
1402 | (if (and num (if (integerp num) | |
1403 | (>= num level) | |
1404 | num)) | |
1405 | (setq txt (concat snumber " " txt))) | |
1406 | (if (<= level (max umax umax-toc)) | |
1407 | (setq head-count (+ head-count 1))) | |
1408 | (if (<= level umax-toc) | |
1409 | (progn | |
1410 | (if (> level org-last-level) | |
1411 | (progn | |
1412 | (setq cnt (- level org-last-level)) | |
1413 | (while (>= (setq cnt (1- cnt)) 0) | |
1414 | (push "\n<ul>\n<li>" thetoc)) | |
1415 | (push "\n" thetoc))) | |
1416 | (if (< level org-last-level) | |
1417 | (progn | |
1418 | (setq cnt (- org-last-level level)) | |
1419 | (while (>= (setq cnt (1- cnt)) 0) | |
1420 | (push "</li>\n</ul>" thetoc)) | |
1421 | (push "\n" thetoc))) | |
1422 | ;; Check for targets | |
1423 | (while (string-match org-any-target-regexp line) | |
1424 | (setq line (replace-match | |
1425 | (concat "@<span class=\"target\">" | |
1426 | (match-string 1 line) "@</span> ") | |
1427 | t t line))) | |
1428 | (while (string-match "<\\(<\\)+\\|>\\(>\\)+" txt) | |
1429 | (setq txt (replace-match "" t t txt))) | |
1430 | (setq href | |
1431 | (replace-regexp-in-string | |
1432 | "\\." "-" (format "sec-%s" snumber))) | |
1433 | (setq href (org-solidify-link-text | |
1434 | (or (cdr (assoc href | |
1435 | org-export-preferred-target-alist)) href))) | |
1436 | (push | |
1437 | (format | |
1438 | (if todo | |
1439 | "</li>\n<li><a href=\"#%s\"><span class=\"todo\">%s</span></a>" | |
1440 | "</li>\n<li><a href=\"#%s\">%s</a>") | |
1441 | href txt) thetoc) | |
1442 | ||
1443 | (setq org-last-level level))))) | |
1444 | line) | |
1445 | lines)) | |
c8d0cf5c CD |
1446 | (while (> org-last-level (1- org-min-level)) |
1447 | (setq org-last-level (1- org-last-level)) | |
1448 | (push "</li>\n</ul>\n" thetoc)) | |
1449 | (push "</div>\n" thetoc) | |
1450 | (setq thetoc (if have-headings (nreverse thetoc) nil)))) | |
3ab2c837 | 1451 | |
c8d0cf5c CD |
1452 | (setq head-count 0) |
1453 | (org-init-section-numbers) | |
3ab2c837 | 1454 | |
c8d0cf5c | 1455 | (org-open-par) |
3ab2c837 | 1456 | |
c8d0cf5c CD |
1457 | (while (setq line (pop lines) origline line) |
1458 | (catch 'nextline | |
3ab2c837 | 1459 | |
c8d0cf5c | 1460 | ;; end of quote section? |
3ab2c837 | 1461 | (when (and inquote (string-match org-outline-regexp-bol line)) |
c8d0cf5c CD |
1462 | (insert "</pre>\n") |
1463 | (org-open-par) | |
1464 | (setq inquote nil)) | |
1465 | ;; inside a quote section? | |
1466 | (when inquote | |
1467 | (insert (org-html-protect line) "\n") | |
1468 | (throw 'nextline nil)) | |
1469 | ||
1470 | ;; Fixed-width, verbatim lines (examples) | |
1471 | (when (and org-export-with-fixed-width | |
1472 | (string-match "^[ \t]*:\\(\\([ \t]\\|$\\)\\(.*\\)\\)" line)) | |
1473 | (when (not infixed) | |
1474 | (setq infixed t) | |
1475 | (org-close-par-maybe) | |
1476 | ||
1477 | (insert "<pre class=\"example\">\n")) | |
1478 | (insert (org-html-protect (match-string 3 line)) "\n") | |
1479 | (when (or (not lines) | |
1480 | (not (string-match "^[ \t]*:\\(\\([ \t]\\|$\\)\\(.*\\)\\)" | |
1481 | (car lines)))) | |
1482 | (setq infixed nil) | |
1483 | (insert "</pre>\n") | |
1484 | (org-open-par)) | |
1485 | (throw 'nextline nil)) | |
1486 | ||
c8d0cf5c | 1487 | ;; Protected HTML |
acedf35c CD |
1488 | (when (and (get-text-property 0 'org-protected line) |
1489 | ;; Make sure it is the entire line that is protected | |
1490 | (not (< (or (next-single-property-change | |
1491 | 0 'org-protected line) 10000) | |
1492 | (length line)))) | |
c8d0cf5c CD |
1493 | (let (par (ind (get-text-property 0 'original-indentation line))) |
1494 | (when (re-search-backward | |
1495 | "\\(<p>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t) | |
1496 | (setq par (match-string 1)) | |
1497 | (replace-match "\\2\n")) | |
1498 | (insert line "\n") | |
1499 | (while (and lines | |
1500 | (or (= (length (car lines)) 0) | |
1501 | (not ind) | |
1502 | (equal ind (get-text-property 0 'original-indentation (car lines)))) | |
1503 | (or (= (length (car lines)) 0) | |
1504 | (get-text-property 0 'org-protected (car lines)))) | |
1505 | (insert (pop lines) "\n")) | |
1506 | (and par (insert "<p>\n"))) | |
1507 | (throw 'nextline nil)) | |
1508 | ||
1509 | ;; Blockquotes, verse, and center | |
1510 | (when (equal "ORG-BLOCKQUOTE-START" line) | |
1511 | (org-close-par-maybe) | |
1512 | (insert "<blockquote>\n") | |
1513 | (org-open-par) | |
1514 | (throw 'nextline nil)) | |
1515 | (when (equal "ORG-BLOCKQUOTE-END" line) | |
1516 | (org-close-par-maybe) | |
1517 | (insert "\n</blockquote>\n") | |
1518 | (org-open-par) | |
1519 | (throw 'nextline nil)) | |
1520 | (when (equal "ORG-VERSE-START" line) | |
1521 | (org-close-par-maybe) | |
1522 | (insert "\n<p class=\"verse\">\n") | |
86fbb8ca | 1523 | (setq org-par-open t) |
c8d0cf5c CD |
1524 | (setq inverse t) |
1525 | (throw 'nextline nil)) | |
1526 | (when (equal "ORG-VERSE-END" line) | |
1527 | (insert "</p>\n") | |
86fbb8ca | 1528 | (setq org-par-open nil) |
c8d0cf5c CD |
1529 | (org-open-par) |
1530 | (setq inverse nil) | |
1531 | (throw 'nextline nil)) | |
1532 | (when (equal "ORG-CENTER-START" line) | |
1533 | (org-close-par-maybe) | |
1534 | (insert "\n<div style=\"text-align: center\">") | |
1535 | (org-open-par) | |
1536 | (throw 'nextline nil)) | |
1537 | (when (equal "ORG-CENTER-END" line) | |
1538 | (org-close-par-maybe) | |
1539 | (insert "\n</div>") | |
1540 | (org-open-par) | |
1541 | (throw 'nextline nil)) | |
1542 | (run-hooks 'org-export-html-after-blockquotes-hook) | |
1543 | (when inverse | |
1544 | (let ((i (org-get-string-indentation line))) | |
1545 | (if (> i 0) | |
1546 | (setq line (concat (mapconcat 'identity | |
1547 | (make-list (* 2 i) "\\nbsp") "") | |
1548 | " " (org-trim line)))) | |
1549 | (unless (string-match "\\\\\\\\[ \t]*$" line) | |
1550 | (setq line (concat line "\\\\"))))) | |
1551 | ||
1552 | ;; make targets to anchors | |
8bfe682a | 1553 | (setq start 0) |
c8d0cf5c | 1554 | (while (string-match |
8bfe682a | 1555 | "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line start) |
c8d0cf5c | 1556 | (cond |
8bfe682a CD |
1557 | ((get-text-property (match-beginning 1) 'org-protected line) |
1558 | (setq start (match-end 1))) | |
c8d0cf5c CD |
1559 | ((match-end 2) |
1560 | (setq line (replace-match | |
1561 | (format | |
1562 | "@<a name=\"%s\" id=\"%s\">@</a>" | |
1563 | (org-solidify-link-text (match-string 1 line)) | |
1564 | (org-solidify-link-text (match-string 1 line))) | |
1565 | t t line))) | |
1566 | ((and org-export-with-toc (equal (string-to-char line) ?*)) | |
1567 | ;; FIXME: NOT DEPENDENT on TOC????????????????????? | |
1568 | (setq line (replace-match | |
8bfe682a CD |
1569 | (concat "@<span class=\"target\">" |
1570 | (match-string 1 line) "@</span> ") | |
1571 | ;; (concat "@<i>" (match-string 1 line) "@</i> ") | |
c8d0cf5c CD |
1572 | t t line))) |
1573 | (t | |
1574 | (setq line (replace-match | |
1575 | (concat "@<a name=\"" | |
1576 | (org-solidify-link-text (match-string 1 line)) | |
8bfe682a CD |
1577 | "\" class=\"target\">" (match-string 1 line) |
1578 | "@</a> ") | |
c8d0cf5c | 1579 | t t line))))) |
ed21c5c8 | 1580 | |
c8d0cf5c CD |
1581 | (setq line (org-html-handle-time-stamps line)) |
1582 | ||
1583 | ;; replace "&" by "&", "<" and ">" by "<" and ">" | |
1584 | ;; handle @<..> HTML tags (replace "@>..<" by "<..>") | |
1585 | ;; Also handle sub_superscripts and checkboxes | |
1586 | (or (string-match org-table-hline-regexp line) | |
3ab2c837 | 1587 | (string-match "^[ \t]*\\([+]-\\||[ ]\\)[-+ |]*[+|][ \t]*$" line) |
c8d0cf5c CD |
1588 | (setq line (org-html-expand line))) |
1589 | ||
1590 | ;; Format the links | |
3ab2c837 | 1591 | (setq line (org-html-handle-links line opt-plist)) |
c8d0cf5c CD |
1592 | |
1593 | ;; TODO items | |
1594 | (if (and (string-match org-todo-line-regexp line) | |
1595 | (match-beginning 2)) | |
1596 | ||
1597 | (setq line | |
1598 | (concat (substring line 0 (match-beginning 2)) | |
1599 | "<span class=\"" | |
1600 | (if (member (match-string 2 line) | |
1601 | org-done-keywords) | |
1602 | "done" "todo") | |
1603 | " " (match-string 2 line) | |
1604 | "\"> " (org-export-html-get-todo-kwd-class-name | |
1605 | (match-string 2 line)) | |
1606 | "</span>" (substring line (match-end 2))))) | |
1607 | ||
1608 | ;; Does this contain a reference to a footnote? | |
1609 | (when org-export-with-footnotes | |
1610 | (setq start 0) | |
54a0dee5 | 1611 | (while (string-match "\\([^* \t].*?\\)\\[\\([0-9]+\\)\\]" line start) |
3ab2c837 BG |
1612 | ;; Discard protected matches not clearly identified as |
1613 | ;; footnote markers. | |
1614 | (if (or (get-text-property (match-beginning 2) 'org-protected line) | |
1615 | (not (get-text-property (match-beginning 2) 'org-footnote line))) | |
c8d0cf5c CD |
1616 | (setq start (match-end 2)) |
1617 | (let ((n (match-string 2 line)) extra a) | |
1618 | (if (setq a (assoc n footref-seen)) | |
1619 | (progn | |
1620 | (setcdr a (1+ (cdr a))) | |
1621 | (setq extra (format ".%d" (cdr a)))) | |
1622 | (setq extra "") | |
1623 | (push (cons n 1) footref-seen)) | |
1624 | (setq line | |
1625 | (replace-match | |
3ab2c837 BG |
1626 | (concat |
1627 | (format | |
1628 | (concat "%s" | |
1629 | (format org-export-html-footnote-format | |
1630 | (concat "<a class=\"footref\" name=\"fnr.%s%s\" href=\"#fn.%s\">%s</a>"))) | |
1631 | (or (match-string 1 line) "") n extra n n) | |
1632 | ;; If another footnote is following the | |
1633 | ;; current one, add a separator. | |
1634 | (if (save-match-data | |
1635 | (string-match "\\`\\[[0-9]+\\]" | |
1636 | (substring line (match-end 0)))) | |
1637 | org-export-html-footnote-separator | |
1638 | "")) | |
c8d0cf5c CD |
1639 | t t line)))))) |
1640 | ||
1641 | (cond | |
1642 | ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line) | |
1643 | ;; This is a headline | |
1644 | (setq level (org-tr-level (- (match-end 1) (match-beginning 1) | |
1645 | level-offset)) | |
1646 | txt (match-string 2 line)) | |
1647 | (if (string-match quote-re0 txt) | |
1648 | (setq txt (replace-match "" t t txt))) | |
1649 | (if (<= level (max umax umax-toc)) | |
1650 | (setq head-count (+ head-count 1))) | |
c8d0cf5c CD |
1651 | (setq first-heading-pos (or first-heading-pos (point))) |
1652 | (org-html-level-start level txt umax | |
1653 | (and org-export-with-toc (<= level umax)) | |
3ab2c837 | 1654 | head-count opt-plist) |
c8d0cf5c CD |
1655 | |
1656 | ;; QUOTES | |
1657 | (when (string-match quote-re line) | |
1658 | (org-close-par-maybe) | |
1659 | (insert "<pre>") | |
1660 | (setq inquote t))) | |
1661 | ||
c8d0cf5c CD |
1662 | ((and org-export-with-tables |
1663 | (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line)) | |
1664 | (when (not table-open) | |
1665 | ;; New table starts | |
1666 | (setq table-open t table-buffer nil table-orig-buffer nil)) | |
1667 | ||
1668 | ;; Accumulate lines | |
1669 | (setq table-buffer (cons line table-buffer) | |
1670 | table-orig-buffer (cons origline table-orig-buffer)) | |
1671 | (when (or (not lines) | |
1672 | (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" | |
1673 | (car lines)))) | |
1674 | (setq table-open nil | |
1675 | table-buffer (nreverse table-buffer) | |
1676 | table-orig-buffer (nreverse table-orig-buffer)) | |
1677 | (org-close-par-maybe) | |
1678 | (insert (org-format-table-html table-buffer table-orig-buffer)))) | |
3ab2c837 BG |
1679 | |
1680 | ;; Normal lines | |
1681 | ||
c8d0cf5c | 1682 | (t |
3ab2c837 BG |
1683 | ;; This line either is list item or end a list. |
1684 | (when (get-text-property 0 'list-item line) | |
1685 | (setq line (org-html-export-list-line | |
1686 | line | |
1687 | (get-text-property 0 'list-item line) | |
1688 | (get-text-property 0 'list-struct line) | |
1689 | (get-text-property 0 'list-prevs line)))) | |
c8d0cf5c CD |
1690 | |
1691 | ;; Horizontal line | |
1692 | (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line) | |
1693 | (if org-par-open | |
1694 | (insert "\n</p>\n<hr/>\n<p>\n") | |
1695 | (insert "\n<hr/>\n")) | |
1696 | (throw 'nextline nil)) | |
1697 | ||
1698 | ;; Empty lines start a new paragraph. If hand-formatted lists | |
1699 | ;; are not fully interpreted, lines starting with "-", "+", "*" | |
1700 | ;; also start a new paragraph. | |
1701 | (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par)) | |
1702 | ||
1703 | ;; Is this the start of a footnote? | |
1704 | (when org-export-with-footnotes | |
1705 | (when (and (boundp 'footnote-section-tag-regexp) | |
1706 | (string-match (concat "^" footnote-section-tag-regexp) | |
1707 | line)) | |
1708 | ;; ignore this line | |
1709 | (throw 'nextline nil)) | |
1710 | (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line) | |
1711 | (org-close-par-maybe) | |
1712 | (let ((n (match-string 1 line))) | |
1713 | (setq org-par-open t | |
1714 | line (replace-match | |
54a0dee5 CD |
1715 | (format |
1716 | (concat "<p class=\"footnote\">" | |
1717 | (format org-export-html-footnote-format | |
1718 | "<a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a>")) | |
1719 | n n n) t t line))))) | |
c8d0cf5c CD |
1720 | ;; Check if the line break needs to be conserved |
1721 | (cond | |
1722 | ((string-match "\\\\\\\\[ \t]*$" line) | |
1723 | (setq line (replace-match "<br/>" t t line))) | |
1724 | (org-export-preserve-breaks | |
1725 | (setq line (concat line "<br/>")))) | |
1726 | ||
1727 | ;; Check if a paragraph should be started | |
1728 | (let ((start 0)) | |
1729 | (while (and org-par-open | |
1730 | (string-match "\\\\par\\>" line start)) | |
1731 | ;; Leave a space in the </p> so that the footnote matcher | |
1732 | ;; does not see this. | |
1733 | (if (not (get-text-property (match-beginning 0) | |
1734 | 'org-protected line)) | |
1735 | (setq line (replace-match "</p ><p >" t t line))) | |
1736 | (setq start (match-end 0)))) | |
1737 | ||
1738 | (insert line "\n"))))) | |
1739 | ||
1740 | ;; Properly close all local lists and other lists | |
1741 | (when inquote | |
1742 | (insert "</pre>\n") | |
1743 | (org-open-par)) | |
afe98dfa | 1744 | |
c8d0cf5c CD |
1745 | (org-html-level-start 1 nil umax |
1746 | (and org-export-with-toc (<= level umax)) | |
3ab2c837 | 1747 | head-count opt-plist) |
c8d0cf5c CD |
1748 | ;; the </div> to close the last text-... div. |
1749 | (when (and (> umax 0) first-heading-pos) (insert "</div>\n")) | |
1750 | ||
1751 | (save-excursion | |
1752 | (goto-char (point-min)) | |
3ab2c837 BG |
1753 | (while (re-search-forward |
1754 | "\\(\\(<p class=\"footnote\">\\)[^\000]*?\\)\\(\\(\\2\\)\\|\\'\\)" | |
1755 | nil t) | |
1756 | (push (match-string 1) footnotes) | |
1757 | (replace-match "\\4" t nil) | |
1758 | (goto-char (match-beginning 0)))) | |
c8d0cf5c CD |
1759 | (when footnotes |
1760 | (insert (format org-export-html-footnotes-section | |
1761 | (nth 4 lang-words) | |
1762 | (mapconcat 'identity (nreverse footnotes) "\n")) | |
1763 | "\n")) | |
1764 | (let ((bib (org-export-html-get-bibliography))) | |
1765 | (when bib | |
1766 | (insert "\n" bib "\n"))) | |
3ab2c837 | 1767 | |
c8d0cf5c | 1768 | (unless body-only |
3ab2c837 BG |
1769 | ;; end wrap around body |
1770 | (insert "</div>\n") | |
1771 | ||
1772 | ;; export html postamble | |
1773 | (let ((html-post (plist-get opt-plist :html-postamble)) | |
1774 | ||
1775 | (mapconcat (lambda(e) | |
1776 | (format "<a href=\"mailto:%s\">%s</a>" e e)) | |
1777 | (split-string email ",+ *") | |
1778 | ", ")) | |
1779 | (creator-info | |
1780 | (concat "Org version " org-version " with Emacs version " | |
1781 | (number-to-string emacs-major-version)))) | |
1782 | ||
1783 | (when (plist-get opt-plist :html-postamble) | |
1784 | (insert "\n<div id=\"" (nth 2 org-export-html-divs) "\">\n") | |
1785 | (cond ((stringp html-post) | |
1786 | (insert (format-spec html-post | |
1787 | `((?a . ,author) (?e . ,email) | |
1788 | (?d . ,date) (?c . ,creator-info) | |
1789 | (?v . ,html-validation-link))))) | |
1790 | ((functionp html-post) | |
1791 | (funcall html-post)) | |
1792 | ((eq html-post 'auto) | |
1793 | ;; fall back on default postamble | |
1794 | (when (plist-get opt-plist :time-stamp-file) | |
1795 | (insert "<p class=\"date\">" (nth 2 lang-words) ": " date "</p>\n")) | |
1796 | (when (and (plist-get opt-plist :author-info) author) | |
1797 | (insert "<p class=\"author\">" (nth 1 lang-words) ": " author "</p>\n")) | |
1798 | (when (and (plist-get opt-plist :email-info) email) | |
1799 | (insert "<p class=\"email\">" email "</p>\n")) | |
1800 | (when (plist-get opt-plist :creator-info) | |
1801 | (insert "<p class=\"creator\">" | |
1802 | (concat "Org version " org-version " with Emacs version " | |
1803 | (number-to-string emacs-major-version) "</p>\n"))) | |
1804 | (insert html-validation-link "\n")) | |
1805 | (t | |
1806 | (insert (format-spec | |
1807 | (or (cadr (assoc (nth 0 lang-words) | |
1808 | org-export-html-postamble-format)) | |
1809 | (cadr (assoc "en" org-export-html-postamble-format))) | |
1810 | `((?a . ,author) (?e . ,email) | |
1811 | (?d . ,date) (?c . ,creator-info) | |
1812 | (?v . ,html-validation-link)))))) | |
1813 | (insert "\n</div>")))) | |
1814 | ||
1815 | ;; FIXME `org-export-html-with-timestamp' has been declared | |
1816 | ;; obsolete since Org 7.7 -- don't forget to remove this. | |
1817 | (if org-export-html-with-timestamp | |
1818 | (insert org-export-html-html-helper-timestamp)) | |
1819 | ||
1820 | (unless body-only (insert "\n</body>\n</html>\n")) | |
c8d0cf5c CD |
1821 | |
1822 | (unless (plist-get opt-plist :buffer-will-be-killed) | |
1823 | (normal-mode) | |
54a0dee5 CD |
1824 | (if (eq major-mode (default-value 'major-mode)) |
1825 | (html-mode))) | |
c8d0cf5c CD |
1826 | |
1827 | ;; insert the table of contents | |
1828 | (goto-char (point-min)) | |
1829 | (when thetoc | |
1830 | (if (or (re-search-forward | |
1831 | "<p>\\s-*\\[TABLE-OF-CONTENTS\\]\\s-*</p>" nil t) | |
1832 | (re-search-forward | |
1833 | "\\[TABLE-OF-CONTENTS\\]" nil t)) | |
1834 | (progn | |
1835 | (goto-char (match-beginning 0)) | |
1836 | (replace-match "")) | |
1837 | (goto-char first-heading-pos) | |
1838 | (when (looking-at "\\s-*</p>") | |
1839 | (goto-char (match-end 0)) | |
1840 | (insert "\n"))) | |
1841 | (insert "<div id=\"table-of-contents\">\n") | |
3ab2c837 BG |
1842 | (let ((beg (point))) |
1843 | (mapc 'insert thetoc) | |
1844 | (insert "</div>\n") | |
1845 | (while (re-search-backward "<li>[ \r\n\t]*</li>\n?" beg t) | |
1846 | (replace-match "")))) | |
1847 | ;; remove empty paragraphs | |
c8d0cf5c CD |
1848 | (goto-char (point-min)) |
1849 | (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t) | |
1850 | (replace-match "")) | |
1851 | (goto-char (point-min)) | |
c8d0cf5c CD |
1852 | ;; Convert whitespace place holders |
1853 | (goto-char (point-min)) | |
1854 | (let (beg end n) | |
1855 | (while (setq beg (next-single-property-change (point) 'org-whitespace)) | |
1856 | (setq n (get-text-property beg 'org-whitespace) | |
1857 | end (next-single-property-change beg 'org-whitespace)) | |
1858 | (goto-char beg) | |
1859 | (delete-region beg end) | |
1860 | (insert (format "<span style=\"visibility:hidden;\">%s</span>" | |
1861 | (make-string n ?x))))) | |
ed21c5c8 CD |
1862 | ;; Remove empty lines at the beginning of the file. |
1863 | (goto-char (point-min)) | |
1864 | (when (looking-at "\\s-+\n") (replace-match "")) | |
1865 | ;; Remove display properties | |
1866 | (remove-text-properties (point-min) (point-max) '(display t)) | |
1867 | ;; Run the hook | |
8d642074 | 1868 | (run-hooks 'org-export-html-final-hook) |
c8d0cf5c CD |
1869 | (or to-buffer (save-buffer)) |
1870 | (goto-char (point-min)) | |
1871 | (or (org-export-push-to-kill-ring "HTML") | |
1872 | (message "Exporting... done")) | |
1873 | (if (eq to-buffer 'string) | |
1874 | (prog1 (buffer-substring (point-min) (point-max)) | |
1875 | (kill-buffer (current-buffer))) | |
1876 | (current-buffer))))) | |
1877 | ||
c8d0cf5c CD |
1878 | (defun org-export-html-format-href (s) |
1879 | "Make sure the S is valid as a href reference in an XHTML document." | |
1880 | (save-match-data | |
1881 | (let ((start 0)) | |
1882 | (while (string-match "&" s start) | |
1883 | (setq start (+ (match-beginning 0) 3) | |
1884 | s (replace-match "&" t t s))))) | |
1885 | s) | |
1886 | ||
1887 | (defun org-export-html-format-desc (s) | |
1888 | "Make sure the S is valid as a description in a link." | |
1889 | (if (and s (not (get-text-property 1 'org-protected s))) | |
1890 | (save-match-data | |
1891 | (org-html-do-expand s)) | |
1892 | s)) | |
1893 | ||
1894 | (defun org-export-html-format-image (src par-open) | |
1895 | "Create image tag with source and attributes." | |
1896 | (save-match-data | |
1897 | (if (string-match "^ltxpng/" src) | |
ed21c5c8 CD |
1898 | (format "<img src=\"%s\" alt=\"%s\"/>" |
1899 | src (org-find-text-property-in-string 'org-latex-src src)) | |
c8d0cf5c CD |
1900 | (let* ((caption (org-find-text-property-in-string 'org-caption src)) |
1901 | (attr (org-find-text-property-in-string 'org-attributes src)) | |
1902 | (label (org-find-text-property-in-string 'org-label src))) | |
ed21c5c8 | 1903 | (setq caption (and caption (org-html-do-expand caption))) |
8bfe682a CD |
1904 | (concat |
1905 | (if caption | |
1906 | (format "%s<div %sclass=\"figure\"> | |
1907 | <p>" | |
1908 | (if org-par-open "</p>\n" "") | |
3ab2c837 | 1909 | (if label (format "id=\"%s\" " (org-solidify-link-text label)) ""))) |
8bfe682a | 1910 | (format "<img src=\"%s\"%s />" |
c8d0cf5c CD |
1911 | src |
1912 | (if (string-match "\\<alt=" (or attr "")) | |
1913 | (concat " " attr ) | |
8bfe682a CD |
1914 | (concat " " attr " alt=\"" src "\""))) |
1915 | (if caption | |
1916 | (format "</p>%s | |
1917 | </div>%s" | |
1918 | (concat "\n<p>" caption "</p>") | |
1919 | (if org-par-open "\n<p>" "")))))))) | |
c8d0cf5c CD |
1920 | |
1921 | (defun org-export-html-get-bibliography () | |
1922 | "Find bibliography, cut it out and return it." | |
1923 | (catch 'exit | |
1924 | (let (beg end (cnt 1) bib) | |
1925 | (save-excursion | |
1926 | (goto-char (point-min)) | |
1927 | (when (re-search-forward "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t) | |
1928 | (setq beg (match-beginning 0)) | |
1929 | (while (re-search-forward "</?div\\>" nil t) | |
1930 | (setq cnt (+ cnt (if (string= (match-string 0) "<div") +1 -1))) | |
1931 | (when (= cnt 0) | |
1932 | (and (looking-at ">") (forward-char 1)) | |
1933 | (setq bib (buffer-substring beg (point))) | |
1934 | (delete-region beg (point)) | |
1935 | (throw 'exit bib)))) | |
1936 | nil)))) | |
1937 | ||
1938 | (defvar org-table-number-regexp) ; defined in org-table.el | |
afe98dfa CD |
1939 | (defun org-format-table-html (lines olines &optional no-css) |
1940 | "Find out which HTML converter to use and return the HTML code. | |
1941 | NO-CSS is passed to the exporter." | |
c8d0cf5c CD |
1942 | (if (stringp lines) |
1943 | (setq lines (org-split-string lines "\n"))) | |
1944 | (if (string-match "^[ \t]*|" (car lines)) | |
1945 | ;; A normal org table | |
afe98dfa | 1946 | (org-format-org-table-html lines nil no-css) |
3ab2c837 BG |
1947 | ;; Table made by table.el |
1948 | (or (org-format-table-table-html-using-table-generate-source | |
1949 | olines (not org-export-prefer-native-exporter-for-tables)) | |
1950 | ;; We are here only when table.el table has NO col or row | |
1951 | ;; spanning and the user prefers using org's own converter for | |
1952 | ;; exporting of such simple table.el tables. | |
1953 | (org-format-table-table-html lines)))) | |
c8d0cf5c CD |
1954 | |
1955 | (defvar org-table-number-fraction) ; defined in org-table.el | |
afe98dfa CD |
1956 | (defun org-format-org-table-html (lines &optional splice no-css) |
1957 | "Format a table into HTML. | |
1958 | LINES is a list of lines. Optional argument SPLICE means, do not | |
1959 | insert header and surrounding <table> tags, just format the lines. | |
1960 | Optional argument NO-CSS means use XHTML attributes instead of CSS | |
1961 | for formatting. This is required for the DocBook exporter." | |
c8d0cf5c CD |
1962 | (require 'org-table) |
1963 | ;; Get rid of hlines at beginning and end | |
1964 | (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) | |
1965 | (setq lines (nreverse lines)) | |
1966 | (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines))) | |
1967 | (setq lines (nreverse lines)) | |
1968 | (when org-export-table-remove-special-lines | |
1969 | ;; Check if the table has a marking column. If yes remove the | |
1970 | ;; column and the special lines | |
1971 | (setq lines (org-table-clean-before-export lines))) | |
1972 | ||
ed21c5c8 CD |
1973 | (let* ((caption (org-find-text-property-in-string 'org-caption (car lines))) |
1974 | (label (org-find-text-property-in-string 'org-label (car lines))) | |
afe98dfa CD |
1975 | (forced-aligns (org-find-text-property-in-string 'org-forced-aligns |
1976 | (car lines))) | |
ed21c5c8 CD |
1977 | (attributes (org-find-text-property-in-string 'org-attributes |
1978 | (car lines))) | |
c8d0cf5c CD |
1979 | (html-table-tag (org-export-splice-attributes |
1980 | html-table-tag attributes)) | |
1981 | (head (and org-export-highlight-first-table-line | |
1982 | (delq nil (mapcar | |
1983 | (lambda (x) (string-match "^[ \t]*|-" x)) | |
1984 | (cdr lines))))) | |
afe98dfa CD |
1985 | (nline 0) fnum nfields i (cnt 0) |
1986 | tbopen line fields html gr colgropen rowstart rowend | |
1987 | ali align aligns n) | |
ed21c5c8 | 1988 | (setq caption (and caption (org-html-do-expand caption))) |
afe98dfa CD |
1989 | (when (and forced-aligns org-table-clean-did-remove-column) |
1990 | (setq forced-aligns | |
1991 | (mapcar (lambda (x) (cons (1- (car x)) (cdr x))) forced-aligns))) | |
c8d0cf5c CD |
1992 | (if splice (setq head nil)) |
1993 | (unless splice (push (if head "<thead>" "<tbody>") html)) | |
1994 | (setq tbopen t) | |
1995 | (while (setq line (pop lines)) | |
1996 | (catch 'next-line | |
1997 | (if (string-match "^[ \t]*|-" line) | |
1998 | (progn | |
1999 | (unless splice | |
2000 | (push (if head "</thead>" "</tbody>") html) | |
2001 | (if lines (push "<tbody>" html) (setq tbopen nil))) | |
2002 | (setq head nil) ;; head ends here, first time around | |
2003 | ;; ignore this line | |
2004 | (throw 'next-line t))) | |
2005 | ;; Break the line into fields | |
2006 | (setq fields (org-split-string line "[ \t]*|[ \t]*")) | |
86fbb8ca CD |
2007 | (unless fnum (setq fnum (make-vector (length fields) 0) |
2008 | nfields (length fnum))) | |
c8d0cf5c CD |
2009 | (setq nline (1+ nline) i -1 |
2010 | rowstart (eval (car org-export-table-row-tags)) | |
2011 | rowend (eval (cdr org-export-table-row-tags))) | |
2012 | (push (concat rowstart | |
2013 | (mapconcat | |
2014 | (lambda (x) | |
afe98dfa | 2015 | (setq i (1+ i) ali (format "@@class%03d@@" i)) |
86fbb8ca | 2016 | (if (and (< i nfields) ; make sure no rogue line causes an error here |
c8d0cf5c CD |
2017 | (string-match org-table-number-regexp x)) |
2018 | (incf (aref fnum i))) | |
2019 | (cond | |
2020 | (head | |
2021 | (concat | |
afe98dfa CD |
2022 | (format (car org-export-table-header-tags) |
2023 | "col" ali) | |
c8d0cf5c CD |
2024 | x |
2025 | (cdr org-export-table-header-tags))) | |
2026 | ((and (= i 0) org-export-html-table-use-header-tags-for-first-column) | |
2027 | (concat | |
afe98dfa CD |
2028 | (format (car org-export-table-header-tags) |
2029 | "row" ali) | |
c8d0cf5c CD |
2030 | x |
2031 | (cdr org-export-table-header-tags))) | |
2032 | (t | |
afe98dfa CD |
2033 | (concat (format (car org-export-table-data-tags) ali) |
2034 | x | |
c8d0cf5c CD |
2035 | (cdr org-export-table-data-tags))))) |
2036 | fields "") | |
2037 | rowend) | |
2038 | html))) | |
2039 | (unless splice (if tbopen (push "</tbody>" html))) | |
2040 | (unless splice (push "</table>\n" html)) | |
2041 | (setq html (nreverse html)) | |
2042 | (unless splice | |
8bfe682a | 2043 | ;; Put in col tags with the alignment (unfortunately often ignored...) |
c8d0cf5c CD |
2044 | (unless (car org-table-colgroup-info) |
2045 | (setq org-table-colgroup-info | |
2046 | (cons :start (cdr org-table-colgroup-info)))) | |
afe98dfa | 2047 | (setq i 0) |
c8d0cf5c CD |
2048 | (push (mapconcat |
2049 | (lambda (x) | |
afe98dfa CD |
2050 | (setq gr (pop org-table-colgroup-info) |
2051 | i (1+ i) | |
2052 | align (if (assoc i forced-aligns) | |
2053 | (cdr (assoc (cdr (assoc i forced-aligns)) | |
2054 | '(("l" . "left") ("r" . "right") | |
2055 | ("c" . "center")))) | |
2056 | (if (> (/ (float x) nline) | |
2057 | org-table-number-fraction) | |
2058 | "right" "left"))) | |
2059 | (push align aligns) | |
2060 | (format (if no-css | |
2061 | "%s<col align=\"%s\" />%s" | |
2062 | "%s<col class=\"%s\" />%s") | |
c8d0cf5c CD |
2063 | (if (memq gr '(:start :startend)) |
2064 | (prog1 | |
afe98dfa CD |
2065 | (if colgropen |
2066 | "</colgroup>\n<colgroup>" | |
2067 | "<colgroup>") | |
c8d0cf5c CD |
2068 | (setq colgropen t)) |
2069 | "") | |
afe98dfa | 2070 | align |
c8d0cf5c CD |
2071 | (if (memq gr '(:end :startend)) |
2072 | (progn (setq colgropen nil) "</colgroup>") | |
2073 | ""))) | |
2074 | fnum "") | |
2075 | html) | |
afe98dfa CD |
2076 | (setq aligns (nreverse aligns)) |
2077 | (if colgropen (setq html (cons (car html) | |
2078 | (cons "</colgroup>" (cdr html))))) | |
c8d0cf5c CD |
2079 | ;; Since the output of HTML table formatter can also be used in |
2080 | ;; DocBook document, we want to always include the caption to make | |
2081 | ;; DocBook XML file valid. | |
2082 | (push (format "<caption>%s</caption>" (or caption "")) html) | |
3ab2c837 BG |
2083 | (when label |
2084 | (setq html-table-tag (org-export-splice-attributes html-table-tag (format "id=\"%s\"" (org-solidify-link-text label))))) | |
c8d0cf5c | 2085 | (push html-table-tag html)) |
afe98dfa CD |
2086 | (setq html (mapcar |
2087 | (lambda (x) | |
2088 | (replace-regexp-in-string | |
2089 | "@@class\\([0-9]+\\)@@" | |
2090 | (lambda (txt) | |
2091 | (if (not org-export-html-table-align-individual-fields) | |
2092 | "" | |
2093 | (setq n (string-to-number (match-string 1 txt))) | |
2094 | (format (if no-css " align=\"%s\"" " class=\"%s\"") | |
2095 | (or (nth n aligns) "left")))) | |
2096 | x)) | |
2097 | html)) | |
c8d0cf5c CD |
2098 | (concat (mapconcat 'identity html "\n") "\n"))) |
2099 | ||
2100 | (defun org-export-splice-attributes (tag attributes) | |
2101 | "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG." | |
2102 | (if (not attributes) | |
2103 | tag | |
2104 | (let (oldatt newatt) | |
2105 | (setq oldatt (org-extract-attributes-from-string tag) | |
2106 | tag (pop oldatt) | |
2107 | newatt (cdr (org-extract-attributes-from-string attributes))) | |
2108 | (while newatt | |
2109 | (setq oldatt (plist-put oldatt (pop newatt) (pop newatt)))) | |
2110 | (if (string-match ">" tag) | |
2111 | (setq tag | |
2112 | (replace-match (concat (org-attributes-to-string oldatt) ">") | |
2113 | t t tag))) | |
2114 | tag))) | |
2115 | ||
2116 | (defun org-format-table-table-html (lines) | |
2117 | "Format a table generated by table.el into HTML. | |
2118 | This conversion does *not* use `table-generate-source' from table.el. | |
2119 | This has the advantage that Org-mode's HTML conversions can be used. | |
2120 | But it has the disadvantage, that no cell- or row-spanning is allowed." | |
2121 | (let (line field-buffer | |
2122 | (head org-export-highlight-first-table-line) | |
2123 | fields html empty i) | |
2124 | (setq html (concat html-table-tag "\n")) | |
2125 | (while (setq line (pop lines)) | |
2126 | (setq empty " ") | |
2127 | (catch 'next-line | |
2128 | (if (string-match "^[ \t]*\\+-" line) | |
2129 | (progn | |
2130 | (if field-buffer | |
2131 | (progn | |
2132 | (setq | |
2133 | html | |
2134 | (concat | |
2135 | html | |
2136 | "<tr>" | |
2137 | (mapconcat | |
2138 | (lambda (x) | |
2139 | (if (equal x "") (setq x empty)) | |
2140 | (if head | |
2141 | (concat | |
afe98dfa | 2142 | (format (car org-export-table-header-tags) "col" "") |
c8d0cf5c CD |
2143 | x |
2144 | (cdr org-export-table-header-tags)) | |
afe98dfa | 2145 | (concat (format (car org-export-table-data-tags) "") x |
c8d0cf5c CD |
2146 | (cdr org-export-table-data-tags)))) |
2147 | field-buffer "\n") | |
2148 | "</tr>\n")) | |
2149 | (setq head nil) | |
2150 | (setq field-buffer nil))) | |
2151 | ;; Ignore this line | |
2152 | (throw 'next-line t))) | |
2153 | ;; Break the line into fields and store the fields | |
2154 | (setq fields (org-split-string line "[ \t]*|[ \t]*")) | |
2155 | (if field-buffer | |
2156 | (setq field-buffer (mapcar | |
2157 | (lambda (x) | |
2158 | (concat x "<br/>" (pop fields))) | |
2159 | field-buffer)) | |
2160 | (setq field-buffer fields)))) | |
2161 | (setq html (concat html "</table>\n")) | |
2162 | html)) | |
2163 | ||
3ab2c837 BG |
2164 | (defun org-format-table-table-html-using-table-generate-source (lines |
2165 | &optional | |
2166 | spanned-only) | |
c8d0cf5c | 2167 | "Format a table into html, using `table-generate-source' from table.el. |
3ab2c837 BG |
2168 | Use SPANNED-ONLY to suppress exporting of simple table.el tables. |
2169 | ||
2170 | When SPANNED-ONLY is nil, all table.el tables are exported. When | |
2171 | SPANNED-ONLY is non-nil, only tables with either row or column | |
2172 | spans are exported. | |
2173 | ||
2174 | This routine returns the generated source or nil as appropriate. | |
2175 | ||
2176 | Refer docstring of `org-export-prefer-native-exporter-for-tables' | |
2177 | for further information." | |
c8d0cf5c CD |
2178 | (require 'table) |
2179 | (with-current-buffer (get-buffer-create " org-tmp1 ") | |
2180 | (erase-buffer) | |
2181 | (insert (mapconcat 'identity lines "\n")) | |
2182 | (goto-char (point-min)) | |
2183 | (if (not (re-search-forward "|[^+]" nil t)) | |
2184 | (error "Error processing table")) | |
2185 | (table-recognize-table) | |
3ab2c837 BG |
2186 | (when (or (not spanned-only) |
2187 | (let* ((dim (table-query-dimension)) | |
2188 | (c (nth 4 dim)) (r (nth 5 dim)) (cells (nth 6 dim))) | |
2189 | (not (= (* c r) cells)))) | |
2190 | (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer)) | |
2191 | (table-generate-source 'html " org-tmp2 ") | |
2192 | (set-buffer " org-tmp2 ") | |
2193 | (buffer-substring (point-min) (point-max))))) | |
c8d0cf5c CD |
2194 | |
2195 | (defun org-export-splice-style (style extra) | |
2196 | "Splice EXTRA into STYLE, just before \"</style>\"." | |
2197 | (if (and (stringp extra) | |
2198 | (string-match "\\S-" extra) | |
2199 | (string-match "</style>" style)) | |
2200 | (concat (substring style 0 (match-beginning 0)) | |
2201 | "\n" extra "\n" | |
2202 | (substring style (match-beginning 0))) | |
2203 | style)) | |
2204 | ||
2205 | (defun org-html-handle-time-stamps (s) | |
2206 | "Format time stamps in string S, or remove them." | |
2207 | (catch 'exit | |
2208 | (let (r b) | |
2209 | (while (string-match org-maybe-keyword-time-regexp s) | |
2210 | (or b (setq b (substring s 0 (match-beginning 0)))) | |
2211 | (setq r (concat | |
2212 | r (substring s 0 (match-beginning 0)) | |
2213 | " @<span class=\"timestamp-wrapper\">" | |
2214 | (if (match-end 1) | |
2215 | (format "@<span class=\"timestamp-kwd\">%s @</span>" | |
2216 | (match-string 1 s))) | |
2217 | (format " @<span class=\"timestamp\">%s@</span>" | |
2218 | (substring | |
2219 | (org-translate-time (match-string 3 s)) 1 -1)) | |
2220 | "@</span>") | |
2221 | s (substring s (match-end 0)))) | |
2222 | ;; Line break if line started and ended with time stamp stuff | |
2223 | (if (not r) | |
2224 | s | |
2225 | (setq r (concat r s)) | |
2226 | (unless (string-match "\\S-" (concat b s)) | |
2227 | (setq r (concat r "@<br/>"))) | |
2228 | r)))) | |
2229 | ||
2230 | (defvar htmlize-buffer-places) ; from htmlize.el | |
2231 | (defun org-export-htmlize-region-for-paste (beg end) | |
2232 | "Convert the region to HTML, using htmlize.el. | |
2233 | This is much like `htmlize-region-for-paste', only that it uses | |
2234 | the settings define in the org-... variables." | |
2235 | (let* ((htmlize-output-type org-export-htmlize-output-type) | |
2236 | (htmlize-css-name-prefix org-export-htmlize-css-font-prefix) | |
2237 | (htmlbuf (htmlize-region beg end))) | |
2238 | (unwind-protect | |
2239 | (with-current-buffer htmlbuf | |
2240 | (buffer-substring (plist-get htmlize-buffer-places 'content-start) | |
2241 | (plist-get htmlize-buffer-places 'content-end))) | |
2242 | (kill-buffer htmlbuf)))) | |
2243 | ||
2244 | ;;;###autoload | |
2245 | (defun org-export-htmlize-generate-css () | |
2246 | "Create the CSS for all font definitions in the current Emacs session. | |
2247 | Use this to create face definitions in your CSS style file that can then | |
2248 | be used by code snippets transformed by htmlize. | |
2249 | This command just produces a buffer that contains class definitions for all | |
2250 | faces used in the current Emacs session. You can copy and paste the ones you | |
2251 | need into your CSS file. | |
2252 | ||
2253 | If you then set `org-export-htmlize-output-type' to `css', calls to | |
2254 | the function `org-export-htmlize-region-for-paste' will produce code | |
2255 | that uses these same face definitions." | |
2256 | (interactive) | |
2257 | (require 'htmlize) | |
2258 | (and (get-buffer "*html*") (kill-buffer "*html*")) | |
2259 | (with-temp-buffer | |
2260 | (let ((fl (face-list)) | |
2261 | (htmlize-css-name-prefix "org-") | |
2262 | (htmlize-output-type 'css) | |
2263 | f i) | |
2264 | (while (setq f (pop fl) | |
2265 | i (and f (face-attribute f :inherit))) | |
2266 | (when (and (symbolp f) (or (not i) (not (listp i)))) | |
2267 | (insert (org-add-props (copy-sequence "1") nil 'face f)))) | |
2268 | (htmlize-region (point-min) (point-max)))) | |
3ab2c837 | 2269 | (org-pop-to-buffer-same-window "*html*") |
c8d0cf5c CD |
2270 | (goto-char (point-min)) |
2271 | (if (re-search-forward "<style" nil t) | |
2272 | (delete-region (point-min) (match-beginning 0))) | |
2273 | (if (re-search-forward "</style>" nil t) | |
2274 | (delete-region (1+ (match-end 0)) (point-max))) | |
2275 | (beginning-of-line 1) | |
2276 | (if (looking-at " +") (replace-match "")) | |
2277 | (goto-char (point-min))) | |
2278 | ||
2279 | (defun org-html-protect (s) | |
3ab2c837 BG |
2280 | "Convert characters to HTML equivalent. |
2281 | Possible conversions are set in `org-export-html-protect-char-alist'." | |
2282 | (let ((cl org-export-html-protect-char-alist) c) | |
2283 | (while (setq c (pop cl)) | |
2284 | (let ((start 0)) | |
2285 | (while (string-match (car c) s start) | |
2286 | (setq s (replace-match (cdr c) t t s) | |
2287 | start (1+ (match-beginning 0)))))) | |
2288 | s)) | |
c8d0cf5c CD |
2289 | |
2290 | (defun org-html-expand (string) | |
86fbb8ca | 2291 | "Prepare STRING for HTML export. Apply all active conversions. |
c8d0cf5c CD |
2292 | If there are links in the string, don't modify these." |
2293 | (let* ((re (concat org-bracket-link-regexp "\\|" | |
afe98dfa | 2294 | (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))) |
c8d0cf5c | 2295 | m s l res) |
3ab2c837 BG |
2296 | (while (setq m (string-match re string)) |
2297 | (setq s (substring string 0 m) | |
2298 | l (match-string 0 string) | |
2299 | string (substring string (match-end 0))) | |
2300 | (push (org-html-do-expand s) res) | |
2301 | (push l res)) | |
2302 | (push (org-html-do-expand string) res) | |
2303 | (apply 'concat (nreverse res)))) | |
c8d0cf5c CD |
2304 | |
2305 | (defun org-html-do-expand (s) | |
2306 | "Apply all active conversions to translate special ASCII to HTML." | |
2307 | (setq s (org-html-protect s)) | |
2308 | (if org-export-html-expand | |
2309 | (while (string-match "@<\\([^&]*\\)>" s) | |
2310 | (setq s (replace-match "<\\1>" t nil s)))) | |
2311 | (if org-export-with-emphasize | |
2312 | (setq s (org-export-html-convert-emphasize s))) | |
2313 | (if org-export-with-special-strings | |
2314 | (setq s (org-export-html-convert-special-strings s))) | |
2315 | (if org-export-with-sub-superscripts | |
2316 | (setq s (org-export-html-convert-sub-super s))) | |
2317 | (if org-export-with-TeX-macros | |
ed21c5c8 CD |
2318 | (let ((start 0) wd rep) |
2319 | (while (setq start (string-match "\\\\\\([a-zA-Z]+[0-9]*\\)\\({}\\)?" | |
c8d0cf5c CD |
2320 | s start)) |
2321 | (if (get-text-property (match-beginning 0) 'org-protected s) | |
2322 | (setq start (match-end 0)) | |
2323 | (setq wd (match-string 1 s)) | |
ed21c5c8 CD |
2324 | (if (setq rep (org-entity-get-representation wd 'html)) |
2325 | (setq s (replace-match rep t t s)) | |
c8d0cf5c CD |
2326 | (setq start (+ start (length wd)))))))) |
2327 | s) | |
2328 | ||
c8d0cf5c CD |
2329 | (defun org-export-html-convert-special-strings (string) |
2330 | "Convert special characters in STRING to HTML." | |
2331 | (let ((all org-export-html-special-string-regexps) | |
2332 | e a re rpl start) | |
2333 | (while (setq a (pop all)) | |
2334 | (setq re (car a) rpl (cdr a) start 0) | |
2335 | (while (string-match re string start) | |
2336 | (if (get-text-property (match-beginning 0) 'org-protected string) | |
2337 | (setq start (match-end 0)) | |
2338 | (setq string (replace-match rpl t nil string))))) | |
2339 | string)) | |
2340 | ||
2341 | (defun org-export-html-convert-sub-super (string) | |
2342 | "Convert sub- and superscripts in STRING to HTML." | |
2343 | (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{}))) | |
2344 | (while (string-match org-match-substring-regexp string s) | |
2345 | (cond | |
2346 | ((and requireb (match-end 8)) (setq s (match-end 2))) | |
2347 | ((get-text-property (match-beginning 2) 'org-protected string) | |
2348 | (setq s (match-end 2))) | |
2349 | (t | |
2350 | (setq s (match-end 1) | |
2351 | key (if (string= (match-string 2 string) "_") "sub" "sup") | |
2352 | c (or (match-string 8 string) | |
2353 | (match-string 6 string) | |
2354 | (match-string 5 string)) | |
2355 | string (replace-match | |
2356 | (concat (match-string 1 string) | |
2357 | "<" key ">" c "</" key ">") | |
2358 | t t string))))) | |
2359 | (while (string-match "\\\\\\([_^]\\)" string) | |
2360 | (setq string (replace-match (match-string 1 string) t t string))) | |
2361 | string)) | |
2362 | ||
2363 | (defun org-export-html-convert-emphasize (string) | |
2364 | "Apply emphasis." | |
2365 | (let ((s 0) rpl) | |
2366 | (while (string-match org-emph-re string s) | |
2367 | (if (not (equal | |
2368 | (substring string (match-beginning 3) (1+ (match-beginning 3))) | |
2369 | (substring string (match-beginning 4) (1+ (match-beginning 4))))) | |
2370 | (setq s (match-beginning 0) | |
2371 | rpl | |
2372 | (concat | |
2373 | (match-string 1 string) | |
2374 | (nth 2 (assoc (match-string 3 string) org-emphasis-alist)) | |
2375 | (match-string 4 string) | |
2376 | (nth 3 (assoc (match-string 3 string) | |
2377 | org-emphasis-alist)) | |
2378 | (match-string 5 string)) | |
2379 | string (replace-match rpl t t string) | |
2380 | s (+ s (- (length rpl) 2))) | |
2381 | (setq s (1+ s)))) | |
2382 | string)) | |
2383 | ||
2384 | (defun org-open-par () | |
2385 | "Insert <p>, but first close previous paragraph if any." | |
2386 | (org-close-par-maybe) | |
2387 | (insert "\n<p>") | |
2388 | (setq org-par-open t)) | |
2389 | (defun org-close-par-maybe () | |
2390 | "Close paragraph if there is one open." | |
2391 | (when org-par-open | |
2392 | (insert "</p>") | |
2393 | (setq org-par-open nil))) | |
2394 | (defun org-close-li (&optional type) | |
2395 | "Close <li> if necessary." | |
2396 | (org-close-par-maybe) | |
2397 | (insert (if (equal type "d") "</dd>\n" "</li>\n"))) | |
2398 | ||
c8d0cf5c | 2399 | (defvar body-only) ; dynamically scoped into this. |
3ab2c837 | 2400 | (defun org-html-level-start (level title umax with-toc head-count &optional opt-plist) |
c8d0cf5c CD |
2401 | "Insert a new level in HTML export. |
2402 | When TITLE is nil, just close all open levels." | |
2403 | (org-close-par-maybe) | |
2404 | (let* ((target (and title (org-get-text-property-any 0 'target title))) | |
ed21c5c8 CD |
2405 | (extra-targets (and target |
2406 | (assoc target org-export-target-aliases))) | |
2407 | (extra-class (and title (org-get-text-property-any 0 'html-container-class title))) | |
2408 | (preferred (and target | |
2409 | (cdr (assoc target org-export-preferred-target-alist)))) | |
c8d0cf5c | 2410 | (l org-level-max) |
3ab2c837 | 2411 | (num (plist-get opt-plist :section-numbers)) |
86fbb8ca | 2412 | snumber snu href suffix) |
acedf35c | 2413 | (setq extra-targets (remove (or preferred target) extra-targets)) |
c8d0cf5c CD |
2414 | (setq extra-targets |
2415 | (mapconcat (lambda (x) | |
3ab2c837 BG |
2416 | (setq x (org-solidify-link-text |
2417 | (if (org-uuidgen-p x) (concat "ID-" x) x))) | |
c8d0cf5c CD |
2418 | (format "<a name=\"%s\" id=\"%s\"></a>" |
2419 | x x)) | |
2420 | extra-targets | |
2421 | "")) | |
2422 | (while (>= l level) | |
2423 | (if (aref org-levels-open (1- l)) | |
2424 | (progn | |
2425 | (org-html-level-close l umax) | |
2426 | (aset org-levels-open (1- l) nil))) | |
2427 | (setq l (1- l))) | |
2428 | (when title | |
2429 | ;; If title is nil, this means this function is called to close | |
2430 | ;; all levels, so the rest is done only if title is given | |
afe98dfa | 2431 | (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title) |
c8d0cf5c CD |
2432 | (setq title (replace-match |
2433 | (if org-export-with-tags | |
2434 | (save-match-data | |
2435 | (concat | |
2436 | " <span class=\"tag\">" | |
2437 | (mapconcat | |
2438 | (lambda (x) | |
2439 | (format "<span class=\"%s\">%s</span>" | |
2440 | (org-export-html-get-tag-class-name x) | |
2441 | x)) | |
2442 | (org-split-string (match-string 1 title) ":") | |
2443 | " ") | |
2444 | "</span>")) | |
2445 | "") | |
2446 | t t title))) | |
2447 | (if (> level umax) | |
2448 | (progn | |
2449 | (if (aref org-levels-open (1- level)) | |
2450 | (progn | |
2451 | (org-close-li) | |
2452 | (if target | |
3ab2c837 | 2453 | (insert (format "<li id=\"%s\">" (org-solidify-link-text (or preferred target))) |
acedf35c | 2454 | extra-targets title "<br/>\n") |
c8d0cf5c CD |
2455 | (insert "<li>" title "<br/>\n"))) |
2456 | (aset org-levels-open (1- level) t) | |
2457 | (org-close-par-maybe) | |
2458 | (if target | |
3ab2c837 | 2459 | (insert (format "<ul>\n<li id=\"%s\">" (org-solidify-link-text (or preferred target))) |
c8d0cf5c CD |
2460 | extra-targets title "<br/>\n") |
2461 | (insert "<ul>\n<li>" title "<br/>\n")))) | |
2462 | (aset org-levels-open (1- level) t) | |
86fbb8ca | 2463 | (setq snumber (org-section-number level) |
3ab2c837 | 2464 | snu (replace-regexp-in-string "\\." "-" snumber)) |
c8d0cf5c | 2465 | (setq level (+ level org-export-html-toplevel-hlevel -1)) |
3ab2c837 | 2466 | (if (and num (not body-only)) |
c8d0cf5c CD |
2467 | (setq title (concat |
2468 | (format "<span class=\"section-number-%d\">%s</span>" | |
3ab2c837 BG |
2469 | level |
2470 | (if (and num | |
2471 | (if (integerp num) | |
2472 | ;; fix up num to take into | |
2473 | ;; account the top-level | |
2474 | ;; heading value | |
2475 | (>= (+ num org-export-html-toplevel-hlevel -1) | |
2476 | level) | |
2477 | num)) | |
2478 | snumber | |
2479 | "")) | |
c8d0cf5c CD |
2480 | " " title))) |
2481 | (unless (= head-count 1) (insert "\n</div>\n")) | |
86fbb8ca | 2482 | (setq href (cdr (assoc (concat "sec-" snu) org-export-preferred-target-alist))) |
3ab2c837 BG |
2483 | (setq suffix (org-solidify-link-text (or href snu))) |
2484 | (setq href (org-solidify-link-text (or href (concat "sec-" snu)))) | |
ed21c5c8 CD |
2485 | (insert (format "\n<div id=\"outline-container-%s\" class=\"outline-%d%s\">\n<h%d id=\"%s\">%s%s</h%d>\n<div class=\"outline-text-%d\" id=\"text-%s\">\n" |
2486 | suffix level (if extra-class (concat " " extra-class) "") | |
2487 | level href | |
c8d0cf5c CD |
2488 | extra-targets |
2489 | title level level suffix)) | |
2490 | (org-open-par))))) | |
2491 | ||
2492 | (defun org-export-html-get-tag-class-name (tag) | |
2493 | "Turn tag into a valid class name. | |
2494 | Replaces invalid characters with \"_\" and then prepends a prefix." | |
2495 | (save-match-data | |
2496 | (while (string-match "[^a-zA-Z0-9_]" tag) | |
2497 | (setq tag (replace-match "_" t t tag)))) | |
2498 | (concat org-export-html-tag-class-prefix tag)) | |
2499 | ||
2500 | (defun org-export-html-get-todo-kwd-class-name (kwd) | |
2501 | "Turn todo keyword into a valid class name. | |
2502 | Replaces invalid characters with \"_\" and then prepends a prefix." | |
2503 | (save-match-data | |
2504 | (while (string-match "[^a-zA-Z0-9_]" kwd) | |
2505 | (setq kwd (replace-match "_" t t kwd)))) | |
2506 | (concat org-export-html-todo-kwd-class-prefix kwd)) | |
2507 | ||
2508 | (defun org-html-level-close (level max-outline-level) | |
2509 | "Terminate one level in HTML export." | |
2510 | (if (<= level max-outline-level) | |
2511 | (insert "</div>\n") | |
2512 | (org-close-li) | |
2513 | (insert "</ul>\n"))) | |
2514 | ||
3ab2c837 BG |
2515 | (defun org-html-export-list-line (line pos struct prevs) |
2516 | "Insert list syntax in export buffer. Return LINE, maybe modified. | |
2517 | ||
2518 | POS is the item position or line position the line had before | |
2519 | modifications to buffer. STRUCT is the list structure. PREVS is | |
2520 | the alist of previous items." | |
2521 | (let* ((get-type | |
2522 | (function | |
2523 | ;; Translate type of list containing POS to "d", "o" or | |
2524 | ;; "u". | |
2525 | (lambda (pos struct prevs) | |
2526 | (let ((type (org-list-get-list-type pos struct prevs))) | |
2527 | (cond | |
2528 | ((eq 'ordered type) "o") | |
2529 | ((eq 'descriptive type) "d") | |
2530 | (t "u")))))) | |
2531 | (get-closings | |
2532 | (function | |
2533 | ;; Return list of all items and sublists ending at POS, in | |
2534 | ;; reverse order. | |
2535 | (lambda (pos) | |
2536 | (let (out) | |
2537 | (catch 'exit | |
2538 | (mapc (lambda (e) | |
2539 | (let ((end (nth 6 e)) | |
2540 | (item (car e))) | |
2541 | (cond | |
2542 | ((= end pos) (push item out)) | |
2543 | ((>= item pos) (throw 'exit nil))))) | |
2544 | struct)) | |
2545 | out))))) | |
2546 | ;; First close any previous item, or list, ending at POS. | |
2547 | (mapc (lambda (e) | |
2548 | (let* ((lastp (= (org-list-get-last-item e struct prevs) e)) | |
2549 | (first-item (org-list-get-list-begin e struct prevs)) | |
2550 | (type (funcall get-type first-item struct prevs))) | |
2551 | (org-close-par-maybe) | |
2552 | ;; Ending for every item | |
2553 | (org-close-li type) | |
2554 | ;; We're ending last item of the list: end list. | |
2555 | (when lastp | |
2556 | (insert (format "</%sl>\n" type)) | |
2557 | (org-open-par)))) | |
2558 | (funcall get-closings pos)) | |
2559 | (cond | |
2560 | ;; At an item: insert appropriate tags in export buffer. | |
2561 | ((assq pos struct) | |
2562 | (string-match | |
2563 | (concat "[ \t]*\\(\\S-+[ \t]*\\)" | |
2564 | "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?" | |
2565 | "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?" | |
2566 | "\\(?:\\(.*\\)[ \t]+::\\(?:[ \t]+\\|$\\)\\)?" | |
2567 | "\\(.*\\)") line) | |
2568 | (let* ((checkbox (match-string 3 line)) | |
2569 | (desc-tag (or (match-string 4 line) "???")) | |
2570 | (body (or (match-string 5 line) "")) | |
2571 | (list-beg (org-list-get-list-begin pos struct prevs)) | |
2572 | (firstp (= list-beg pos)) | |
2573 | ;; Always refer to first item to determine list type, in | |
2574 | ;; case list is ill-formed. | |
2575 | (type (funcall get-type list-beg struct prevs)) | |
2576 | (counter (let ((count-tmp (org-list-get-counter pos struct))) | |
2577 | (cond | |
2578 | ((not count-tmp) nil) | |
2579 | ((string-match "[A-Za-z]" count-tmp) | |
2580 | (- (string-to-char (upcase count-tmp)) 64)) | |
2581 | ((string-match "[0-9]+" count-tmp) | |
2582 | count-tmp))))) | |
2583 | (when firstp | |
2584 | (org-close-par-maybe) | |
2585 | (insert (format "<%sl>\n" type))) | |
2586 | (insert (cond | |
2587 | ((equal type "d") | |
2588 | (format "<dt>%s</dt><dd>" desc-tag)) | |
2589 | ((and (equal type "o") counter) | |
2590 | (format "<li value=\"%s\">" counter)) | |
2591 | (t "<li>"))) | |
2592 | ;; If line had a checkbox, some additional modification is required. | |
2593 | (when checkbox | |
2594 | (setq body | |
2595 | (concat | |
2596 | (cond | |
2597 | ((string-match "X" checkbox) "<code>[X]</code> ") | |
2598 | ((string-match " " checkbox) "<code>[ ]</code> ") | |
2599 | (t "<code>[-]</code> ")) | |
2600 | body))) | |
2601 | ;; Return modified line | |
2602 | body)) | |
2603 | ;; At a list ender: go to next line (side-effects only). | |
2604 | ((equal "ORG-LIST-END-MARKER" line) (throw 'nextline nil)) | |
2605 | ;; Not at an item: return line unchanged (side-effects only). | |
2606 | (t line)))) | |
2607 | ||
c8d0cf5c CD |
2608 | (provide 'org-html) |
2609 | ||
5b409b39 | 2610 | |
c8d0cf5c | 2611 | ;;; org-html.el ends here |