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