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