]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-html.el
Merge from emacs-23
[gnu-emacs] / lisp / org / org-html.el
index 85fb0c8d798fb7979006a83832201e7340ca1a0e..8be5709e1de4158a5e5f1e152c450d16ed5acf10 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.33x
+;; Version: 7.4
 ;;
 ;; This file is part of GNU Emacs.
 ;;
 ;;
 ;;; Commentary:
 
+;;; Code:
+
 (require 'org-exp)
+
 (eval-when-compile (require 'cl))
 
 (declare-function org-id-find-id-file "org-id" (id))
@@ -57,7 +60,7 @@ by the footnotes themselves."
   :type 'string)
 
 (defcustom org-export-html-coding-system nil
-  "Coding system for HTML export, defaults to buffer-file-coding-system."
+  "Coding system for HTML export, defaults to `buffer-file-coding-system'."
   :group 'org-export-html
   :type 'coding-system)
 
@@ -81,7 +84,7 @@ and corresponding declarations."
                        (string :tag "Declaration")))))
 
 (defcustom org-export-html-style-include-scripts t
-  "Non-nil means, include the javascript snippets in exported HTML files.
+  "Non-nil means include the JavaScript snippets in exported HTML files.
 The actual script is defined in `org-export-html-scripts' and should
 not be modified."
   :group 'org-export-html
@@ -110,7 +113,7 @@ not be modified."
  }
 /*]]>*///-->
 </script>"
-"Basic javascript that is needed by HTML files produced by Org-mode.")
+"Basic JavaScript that is needed by HTML files produced by Org-mode.")
 
 (defconst org-export-html-style-default
 "<style type=\"text/css\">
@@ -123,6 +126,9 @@ not be modified."
   .target { }
   .timestamp { color: #bebebe; }
   .timestamp-kwd { color: #5f9ea0; }
+  .right  {margin-left:auto; margin-right:0px;  text-align:right;}
+  .left   {margin-left:0px;  margin-right:auto; text-align:left;}
+  .center {margin-left:auto; margin-right:auto; text-align:center;}
   p.verse { margin-left: 3% }
   pre {
        border: 1pt solid #AEBDCC;
@@ -133,10 +139,17 @@ not be modified."
         overflow:auto;
   }
   table { border-collapse: collapse; }
-  td, th { vertical-align: top; }
+  td, th { vertical-align: top;  }
+  th.right  { text-align:center;  }
+  th.left   { text-align:center;   }
+  th.center { text-align:center; }
+  td.right  { text-align:right;  }
+  td.left   { text-align:left;   }
+  td.center { text-align:center; }
   dt { font-weight: bold; }
   div.figure { padding: 0.5em; }
   div.figure p { text-align: center; }
+  textarea { overflow-x: auto; }
   .linenr { font-size:smaller }
   .code-highlighted {background-color:#ffff00;}
   .org-info-js_info-navigation { border-style:none; }
@@ -153,7 +166,7 @@ have the default style included, customize the variable
 `org-export-html-style-include-default'.")
 
 (defcustom org-export-html-style-include-default t
-  "Non-nil means, include the default style in exported HTML files.
+  "Non-nil means include the default style in exported HTML files.
 The actual style is defined in `org-export-html-style-default' and should
 not be modified.  Use the variables `org-export-html-style' to add
 your own style information."
@@ -205,21 +218,127 @@ settings with <style>...</style> tags."
 ;;;###autoload
 (put 'org-export-html-style-extra 'safe-local-variable 'stringp)
 
+(defcustom org-export-html-mathjax-options
+  '((path  "http://orgmode.org/mathjax/MathJax.js")
+    (scale "100")
+    (align "center")
+    (indent "2em")
+    (mathml nil))
+  "Options for MathJax setup.
+
+path        The path where to find MathJax
+scale       Scaling for the HTML-CSS backend, usually between 100 and 133
+align       How to align display math: left, center, or right
+indent      If align is not center, how far from the left/right side?
+mathml      Should a MathML player be used if available?
+            This is faster and reduces bandwidth use, but currently
+            sometimes has lower spacing quality.  Therefore, the default is
+            nil.  When browsers get better, this switch can be flipped.
+
+You can also customize this for each buffer, using something like
+
+#+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\""
+  :group 'org-export-html
+  :type '(list :greedy t
+             (list :tag "path   (the path from where to load MathJax.js)"
+                   (const :format "       " path) (string))
+             (list :tag "scale  (scaling for the displayed math)"
+                   (const :format "       " scale) (string))
+             (list :tag "align  (alignment of displayed equations)"
+                   (const :format "       " align) (string))
+             (list :tag "indent (indentation with left or right alignment)"
+                   (const :format "       " indent) (string))
+             (list :tag "mathml (should MathML display be used is possible)"
+                   (const :format "       " mathml) (boolean))))
+
+(defun org-export-html-mathjax-config (template options in-buffer)
+  "Insert the user setup into the matchjax template."
+  (let (name val (yes "   ") (no "// ") x)
+    (mapc
+     (lambda (e)
+       (setq name (car e) val (nth 1 e))
+       (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer)
+          (setq val (car (read-from-string
+                          (substring in-buffer (match-end 0))))))
+       (if (not (stringp val)) (setq val (format "%s" val)))
+       (if (string-match (concat "%" (upcase (symbol-name name))) template)
+          (setq template (replace-match val t t template))))
+     options)
+    (setq val (nth 1 (assq 'mathml options)))
+    (if (string-match (concat "\\<mathml:") in-buffer)
+       (setq val (car (read-from-string
+                       (substring in-buffer (match-end 0))))))
+    ;; Exchange prefixes depending on mathml setting
+    (if (not val) (setq x yes yes no no x))
+    ;; Replace cookies to turn on or off the config/jax lines
+    (if (string-match ":MMLYES:" template)
+       (setq template (replace-match yes t t template)))
+    (if (string-match ":MMLNO:" template)
+       (setq template (replace-match no t t template)))
+    ;; Return the modified template
+    template))
+
+(defcustom org-export-html-mathjax-template
+  "<script type=\"text/javascript\" src=\"%PATH\">
+<!--/*--><![CDATA[/*><!--*/
+    MathJax.Hub.Config({
+        // Only one of the two following lines, depending on user settings
+        // First allows browser-native MathML display, second forces HTML/CSS
+        :MMLYES: config: [\"MMLorHTML.js\"], jax: [\"input/TeX\"],
+        :MMLNO: jax: [\"input/TeX\", \"output/HTML-CSS\"],
+        extensions: [\"tex2jax.js\",\"TeX/AMSmath.js\",\"TeX/AMSsymbols.js\",
+                     \"TeX/noUndefined.js\"],
+        tex2jax: {
+            inlineMath: [ [\"\\\\(\",\"\\\\)\"] ],
+            displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ],
+            skipTags: [\"script\",\"noscript\",\"style\",\"textarea\",\"pre\",\"code\"],
+            ignoreClass: \"tex2jax_ignore\",
+            processEscapes: false,
+            processEnvironments: true,
+            preview: \"TeX\"
+        },
+        showProcessingMessages: true,
+        displayAlign: \"%ALIGN\",
+        displayIndent: \"%INDENT\",
+
+        \"HTML-CSS\": {
+             scale: %SCALE,
+             availableFonts: [\"STIX\",\"TeX\"],
+             preferredFont: \"TeX\",
+             webFont: \"TeX\",
+             imageFont: \"TeX\",
+             showMathMenu: true,
+        },
+        MMLorHTML: {
+             prefer: {
+                 MSIE:    \"MML\",
+                 Firefox: \"MML\",
+                 Opera:   \"HTML\",
+                 other:   \"HTML\"
+             }
+        }
+    });
+/*]]>*///-->
+</script>"
+  "The MathJax setup for XHTML files."
+  :group 'org-export-html
+  :type 'string)
+
 (defcustom org-export-html-tag-class-prefix ""
-  "Prefix to clas names for TODO keywords.
+  "Prefix to class names for TODO keywords.
 Each tag gets a class given by the tag itself, with this prefix.
 The default prefix is empty because it is nice to just use the keyword
 as a class name.  But if you get into conflicts with other, existing
-CSS classes, then this prefic can be very useful."
+CSS classes, then this prefix can be very useful."
   :group 'org-export-html
   :type 'string)
 
 (defcustom org-export-html-todo-kwd-class-prefix ""
-  "Prefix to clas names for TODO keywords.
+  "Prefix to class names for TODO keywords.
 Each TODO keyword gets a class given by the keyword itself, with this prefix.
 The default prefix is empty because it is nice to just use the keyword
 as a class name.  But if you get into conflicts with other, existing
-CSS classes, then this prefic can be very useful."
+CSS classes, then this prefix can be very useful."
   :group 'org-export-html
   :type 'string)
 
@@ -234,10 +353,11 @@ CSS classes, then this prefic can be very useful."
  |
  <a accesskey=\"H\" href=\"%s\"> HOME </a>
 </div>"
-  "Snippet used to insert the HOME and UP links.  This is a format,
-the first %s will receive the UP link, the second the HOME link.
-If both `org-export-html-link-up' and `org-export-html-link-home' are
-empty, the entire snippet will be ignored."
+  "Snippet used to insert the HOME and UP links.
+This is a format string, the first %s will receive the UP link,
+the second the HOME link.  If both `org-export-html-link-up' and
+`org-export-html-link-home' are empty, the entire snippet will be
+ignored."
   :group 'org-export-html
   :type 'string)
 
@@ -253,7 +373,7 @@ document title."
   :type 'string)
 
 (defcustom org-export-html-link-org-files-as-html t
-  "Non-nil means, make file links to `file.org' point to `file.html'.
+  "Non-nil means make file links to `file.org' point to `file.html'.
 When org-mode is exporting an org-mode file to HTML, links to
 non-html files are directly put into a href tag in HTML.
 However, links to other Org-mode files (recognized by the
@@ -265,7 +385,7 @@ When nil, the links still point to the plain `.org' file."
   :type 'boolean)
 
 (defcustom org-export-html-inline-images 'maybe
-  "Non-nil means, inline images into exported HTML pages.
+  "Non-nil means inline images into exported HTML pages.
 This is done using an <img> tag.  When nil, an anchor with href is used to
 link to the image.  If this option is `maybe', then images in links with
 an empty description will be inlined, while images with a description will
@@ -276,7 +396,7 @@ be linked only."
                 (const :tag "When there is no description" maybe)))
 
 (defcustom org-export-html-inline-image-extensions
-  '("png" "jpeg" "jpg" "gif")
+  '("png" "jpeg" "jpg" "gif" "svg")
   "Extensions of image files that can be inlined into HTML."
   :group 'org-export-html
   :type '(repeat (string :tag "Extension")))
@@ -289,17 +409,22 @@ borders and spacing."
   :group 'org-export-html
   :type 'string)
 
-(defcustom org-export-table-header-tags '("<th scope=\"%s\">" . "</th>")
+(defcustom org-export-table-header-tags '("<th scope=\"%s\"%s>" . "</th>")
   "The opening tag for table header fields.
 This is customizable so that alignment options can be specified.
-%s will be filled with the scope of the field, either row or col.
-See also the variable `org-export-html-table-use-header-tags-for-first-column'."
+The first %s will be filled with the scope of the field, either row or col.
+The second %s will be replaced by a style entry to align the field.
+See also the variable `org-export-html-table-use-header-tags-for-first-column'.
+See also the variable `org-export-html-table-align-individual-fields'."
   :group 'org-export-tables
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
 
-(defcustom org-export-table-data-tags '("<td>" . "</td>")
+(defcustom org-export-table-data-tags '("<td%s>" . "</td>")
   "The opening tag for table data fields.
-This is customizable so that alignment options can be specified."
+This is customizable so that alignment options can be specified.
+The first %s will be filled with the scope of the field, either row or col.
+The second %s will be replaced by a style entry to align the field.
+See also the variable `org-export-html-table-align-individual-fields'."
   :group 'org-export-tables
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
 
@@ -330,16 +455,22 @@ will give even lines the class \"tr-even\" and odd lines the class \"tr-odd\"."
                  (string :tag "Specify")
                  (sexp))))
 
-
+(defcustom org-export-html-table-align-individual-fields t
+  "Non-nil means attach style attributes for alignment to each table field.
+When nil, alignment will only be specified in the column tags, but this
+is ignored by some browsers (like Firefox, Safari).  Opera does it right
+though."
+  :group 'org-export-tables
+  :type 'boolean)
 
 (defcustom org-export-html-table-use-header-tags-for-first-column nil
-  "Non-nil means, format column one in tables with header tags.
+  "Non-nil means format column one in tables with header tags.
 When nil, also column one will use data tags."
   :group 'org-export-tables
   :type 'boolean)
 
 (defcustom org-export-html-validation-link nil
-  "Non-nil means, add validationlink to postamble of HTML exported files."
+  "Non-nil means add validation link to postamble of HTML exported files."
   :group 'org-export-html
   :type '(choice
          (const :tag "Nothing" nil)
@@ -348,9 +479,10 @@ When nil, also column one will use data tags."
 
 
 (defcustom org-export-html-with-timestamp nil
-  "If non-nil, write `org-export-html-html-helper-timestamp'
-into the exported HTML text.  Otherwise, the buffer will just be saved
-to a file."
+  "If non-nil, write timestamp into the exported HTML text.
+If non-nil Write `org-export-html-html-helper-timestamp' into the
+exported HTML text.  Otherwise, the buffer will just be saved to
+a file."
   :group 'org-export-html
   :type 'boolean)
 
@@ -404,10 +536,10 @@ with a link to this URL."
 ;;; Variables, constants, and parameter plists
 
 (defvar org-export-html-preamble nil
-  "Preamble, to be inserted just before <body>.  Set by publishing functions.
+  "Preamble, to be inserted just after <body>.  Set by publishing functions.
 This may also be a function, building and inserting the preamble.")
 (defvar org-export-html-postamble nil
-  "Preamble, to be inserted just after </body>.  Set by publishing functions.
+  "Postamble, to be inserted just before </body>.  Set by publishing functions.
 This may also be a function, building and inserting the postamble.")
 (defvar org-export-html-auto-preamble t
   "Should default preamble be inserted?  Set by publishing functions.")
@@ -420,20 +552,36 @@ This may also be a function, building and inserting the postamble.")
   "Hook run during HTML export, after blockquote, verse, center are done.")
 
 (defvar org-export-html-final-hook nil
-  "Hook run during HTML export, after blockquote, verse, center are done.")
+  "Hook run at the end of HTML export, in the new buffer.")
 
 ;;; HTML export
 
 (defun org-export-html-preprocess (parameters)
-  ;; Convert LaTeX fragments to images
+  "Convert LaTeX fragments to images."
   (when (and org-current-export-file
             (plist-get parameters :LaTeX-fragments))
     (org-format-latex
      (concat "ltxpng/" (file-name-sans-extension
                        (file-name-nondirectory
                         org-current-export-file)))
-     org-current-export-dir nil "Creating LaTeX image %s"))
-  (message "Exporting..."))
+     org-current-export-dir nil "Creating LaTeX image %s"
+     nil nil
+     (cond
+      ((eq (plist-get parameters :LaTeX-fragments) 'verbatim) 'verbatim)
+      ((eq (plist-get parameters :LaTeX-fragments) 'mathjax ) 'mathjax)
+      ((eq (plist-get parameters :LaTeX-fragments) t        ) 'mathjax)
+      ((eq (plist-get parameters :LaTeX-fragments) 'dvipng  ) 'dvipng)
+      (t nil))))
+  (goto-char (point-min))
+  (let (label l1)
+    (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t)
+      (org-if-unprotected-at (match-beginning 1)
+       (setq label (match-string 1))
+       (save-match-data
+         (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label)
+             (setq l1 (substring label (match-beginning 1)))
+           (setq l1 label)))
+       (replace-match (format "[[#%s][%s]]" label l1) t t)))))
 
 ;;;###autoload
 (defun org-export-as-html-and-open (arg)
@@ -443,11 +591,14 @@ The prefix ARG specifies how many levels of the outline should become
 headlines.  The default is 3.  Lower levels will become bulleted lists."
   (interactive "P")
   (org-export-as-html arg 'hidden)
-  (org-open-file buffer-file-name))
+  (org-open-file buffer-file-name)
+  (when org-export-kill-product-buffer-when-displayed
+    (kill-buffer (current-buffer))))
 
 ;;;###autoload
 (defun org-export-as-html-batch ()
-  "Call `org-export-as-html', may be used in batch processing as
+  "Call the function `org-export-as-html'.
+This function can be used in batch processing as:
 emacs   --batch
         --load=$HOME/lib/emacs/org.el
         --eval \"(setq org-export-headline-levels 2)\"
@@ -521,6 +672,128 @@ in a window.  A non-interactive call will only return the buffer."
 
 (defvar html-table-tag nil) ; dynamically scoped into this.
 (defvar org-par-open nil)
+
+;;; org-html-cvt-link-fn
+(defconst org-html-cvt-link-fn
+   nil
+   "Function to convert link URLs to exportable URLs.
+Takes two arguments, TYPE and PATH.
+Returns exportable url as (TYPE PATH), or nil to signal that it
+didn't handle this case.
+Intended to be locally bound around a call to `org-export-as-html'." )
+
+(defun org-html-cvt-org-as-html (opt-plist type path)
+   "Convert an org filename to an equivalent html filename.
+If TYPE is not file, just return `nil'.
+See variable `org-export-html-link-org-files-as-html'"
+
+   (save-match-data
+      (and
+        org-export-html-link-org-files-as-html
+        (string= type "file")
+        (string-match "\\.org$" path)
+        (progn
+           (list
+              "file"
+              (concat
+                 (substring path 0 (match-beginning 0))
+                 "."
+                 (plist-get opt-plist :html-extension)))))))
+
+
+;;; org-html-should-inline-p
+(defun org-html-should-inline-p (filename descp)
+   "Return non-nil if link FILENAME should be inlined.
+The decision to inline the FILENAME link is based on the current
+settings.  DESCP is the boolean of whether there was a link
+description.  See variables `org-export-html-inline-images' and
+`org-export-html-inline-image-extensions'."
+   (declare (special
+            org-export-html-inline-images
+            org-export-html-inline-image-extensions))
+   (and (or (eq t org-export-html-inline-images)
+           (and org-export-html-inline-images (not descp)))
+       (org-file-image-p
+        filename org-export-html-inline-image-extensions)))
+
+;;; org-html-make-link
+(defun org-html-make-link (opt-plist type path fragment desc attr
+                            may-inline-p)
+   "Make an HTML link.
+OPT-PLIST is an options list.
+TYPE is the device-type of the link (THIS://foo.html)
+PATH is the path of the link (http://THIS#locationx)
+FRAGMENT is the fragment part of the link, if any (foo.html#THIS)
+DESC is the link description, if any.
+ATTR is a string of other attributes of the a element.
+MAY-INLINE-P allows inlining it as an image."
+
+   (declare (special org-par-open))
+   (save-match-data
+      (let* ((filename path)
+              ;;First pass.  Just sanity stuff.
+              (components-1
+                 (cond
+                    ((string= type "file")
+                       (list
+                          type
+                          ;;Substitute just if original path was absolute.
+                          ;;(Otherwise path must remain relative)
+                          (if (file-name-absolute-p path)
+                             (concat "file://" (expand-file-name path))
+                             path)))
+                    ((string= type "")
+                       (list nil path))
+                    (t (list type path))))
+
+              ;;Second pass.  Components converted so they can refer
+              ;;to a remote site.
+              (components-2
+                 (or
+                    (and org-html-cvt-link-fn
+                       (apply org-html-cvt-link-fn
+                          opt-plist components-1))
+                    (apply #'org-html-cvt-org-as-html
+                       opt-plist components-1)
+                    components-1))
+              (type    (first  components-2))
+              (thefile (second components-2)))
+
+
+        ;;Third pass.  Build final link except for leading type
+        ;;spec.
+        (cond
+           ((or
+               (not type)
+               (string= type "http")
+               (string= type "https")
+               (string= type "file"))
+              (if fragment
+                 (setq thefile (concat thefile "#" fragment))))
+
+           (t))
+
+        ;;Final URL-build, for all types.
+        (setq thefile
+           (let
+              ((str (org-export-html-format-href thefile)))
+             (if (and type (not (string= "file" type)))
+                 (concat type ":" str)
+                 str)))
+
+        (if (and
+               may-inline-p
+               ;;Can't inline a URL with a fragment.
+               (not fragment))
+           (progn
+              (message "image %s %s" thefile org-par-open)
+              (org-export-html-format-image thefile org-par-open))
+           (concat
+              "<a href=\"" thefile "\"" attr ">"
+              (org-export-html-format-desc desc)
+              "</a>")))))
+
+;;; org-export-as-html
 ;;;###autoload
 (defun org-export-as-html (arg &optional hidden ext-plist
                               to-buffer body-only pub-dir)
@@ -539,6 +812,7 @@ the file header and footer, simply return the content of
 <body>...</body>, without even the body tags themselves.  When
 PUB-DIR is set, use this as the publishing directory."
   (interactive "P")
+  (run-hooks 'org-export-first-hook)
 
   ;; Make sure we have a file name when we need it.
   (when (and (not (or to-buffer body-only))
@@ -624,7 +898,8 @@ PUB-DIR is set, use this as the publishing directory."
         (author      (plist-get opt-plist :author))
         (title       (or (and subtree-p (org-export-get-title-from-subtree))
                          (plist-get opt-plist :title)
-                         (and (not
+                         (and (not body-only)
+                              (not
                                (plist-get opt-plist :skip-before-1st-heading))
                               (org-export-grab-title-from-buffer))
                          (and buffer-file-name
@@ -635,8 +910,8 @@ PUB-DIR is set, use this as the publishing directory."
                       (string-match "\\S-" (plist-get opt-plist :link-up))
                       (plist-get opt-plist :link-up)))
         (link-home (and (plist-get opt-plist :link-home)
-                       (string-match "\\S-" (plist-get opt-plist :link-home))
-                       (plist-get opt-plist :link-home)))
+                        (string-match "\\S-" (plist-get opt-plist :link-home))
+                        (plist-get opt-plist :link-home)))
         (dummy (setq opt-plist (plist-put opt-plist :title title)))
         (html-table-tag (plist-get opt-plist :html-table-tag))
         (quote-re0   (concat "^[ \t]*" org-quote-string "\\>"))
@@ -669,6 +944,7 @@ PUB-DIR is set, use this as the publishing directory."
          (buffer-substring
           (if region-p (region-beginning) (point-min))
           (if region-p (region-end) (point-max))))
+        (org-export-have-math nil)
         (lines
          (org-split-string
           (org-export-preprocess-string
@@ -692,11 +968,21 @@ PUB-DIR is set, use this as the publishing directory."
            :LaTeX-fragments
            (plist-get opt-plist :LaTeX-fragments))
           "[\r\n]"))
+        (mathjax
+         (if (or (eq (plist-get opt-plist :LaTeX-fragments) 'mathjax)
+                 (and org-export-have-math
+                      (eq (plist-get opt-plist :LaTeX-fragments) t)))
+
+             (org-export-html-mathjax-config
+              org-export-html-mathjax-template
+              org-export-html-mathjax-options
+              (or (plist-get opt-plist :mathjax) ""))
+           ""))
         table-open type
         table-buffer table-orig-buffer
-        ind item-type starter didclose
+        ind item-type starter
         rpl path attr desc descp desc1 desc2 link
-        snumber fnc item-tag
+        snumber fnc item-tag item-number
         footnotes footref-seen
         id-file href
         )
@@ -761,6 +1047,7 @@ lang=\"%s\" xml:lang=\"%s\">
 <meta name=\"description\" content=\"%s\"/>
 <meta name=\"keywords\" content=\"%s\"/>
 %s
+%s
 </head>
 <body>
 <div id=\"content\">
@@ -775,10 +1062,11 @@ lang=\"%s\" xml:lang=\"%s\">
                      "")
                  (or charset "iso-8859-1"))
                 language language
-                (org-html-expand title)
+                title
                 (or charset "iso-8859-1")
                 date author description keywords
                 style
+                mathjax
                 (if (or link-up link-home)
                     (concat
                      (format org-export-html-home/up-format
@@ -804,70 +1092,73 @@ lang=\"%s\" xml:lang=\"%s\">
            (push "<ul>\n<li>" thetoc)
            (setq lines
                  (mapcar '(lambda (line)
-                   (if (string-match org-todo-line-regexp line)
-                       ;; This is a headline
-                       (progn
-                         (setq have-headings t)
-                         (setq level (- (match-end 1) (match-beginning 1)
-                                        level-offset)
-                               level (org-tr-level level)
-                               txt (save-match-data
-                                     (org-html-expand
-                                      (org-export-cleanup-toc-line
-                                       (match-string 3 line))))
-                               todo
-                               (or (and org-export-mark-todo-in-toc
-                                        (match-beginning 2)
-                                        (not (member (match-string 2 line)
-                                                     org-done-keywords)))
+                            (if (and (string-match org-todo-line-regexp line)
+                                     (not (get-text-property 0 'org-protected line)))
+                                ;; This is a headline
+                                (progn
+                                  (setq have-headings t)
+                                  (setq level (- (match-end 1) (match-beginning 1)
+                                                 level-offset)
+                                        level (org-tr-level level)
+                                        txt (save-match-data
+                                              (org-html-expand
+                                               (org-export-cleanup-toc-line
+                                                (match-string 3 line))))
+                                        todo
+                                        (or (and org-export-mark-todo-in-toc
+                                                 (match-beginning 2)
+                                                 (not (member (match-string 2 line)
+                                                              org-done-keywords)))
                                        ; TODO, not DONE
-                                   (and org-export-mark-todo-in-toc
-                                        (= level umax-toc)
-                                        (org-search-todo-below
-                                         line lines level))))
-                         (if (string-match
-                              (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt)
-                             (setq txt (replace-match  "&nbsp;&nbsp;&nbsp;<span class=\"tag\"> \\1</span>" t nil txt)))
-                         (if (string-match quote-re0 txt)
-                             (setq txt (replace-match "" t t txt)))
-                         (setq snumber (org-section-number level))
-                         (if org-export-with-section-numbers
-                             (setq txt (concat snumber " " txt)))
-                         (if (<= level (max umax umax-toc))
-                             (setq head-count (+ head-count 1)))
-                         (if (<= level umax-toc)
-                             (progn
-                               (if (> level org-last-level)
-                                   (progn
-                                     (setq cnt (- level org-last-level))
-                                     (while (>= (setq cnt (1- cnt)) 0)
-                                       (push "\n<ul>\n<li>" thetoc))
-                                     (push "\n" thetoc)))
-                               (if (< level org-last-level)
-                                   (progn
-                                     (setq cnt (- org-last-level level))
-                                     (while (>= (setq cnt (1- cnt)) 0)
-                                       (push "</li>\n</ul>" thetoc))
-                                     (push "\n" thetoc)))
-                               ;; Check for targets
-                               (while (string-match org-any-target-regexp line)
-                                 (setq line (replace-match
-                                             (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
-                                             t t line)))
-                               (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
-                                 (setq txt (replace-match "" t t txt)))
-                               (setq href (format "sec-%s" snumber))
-                               (setq href (or (cdr (assoc href org-export-preferred-target-alist)) href))
-                               (push
-                                (format
-                                 (if todo
-                                     "</li>\n<li><a href=\"#%s\"><span class=\"todo\">%s</span></a>"
-                                   "</li>\n<li><a href=\"#%s\">%s</a>")
-                                 href txt) thetoc)
-
-                               (setq org-last-level level))
-                           )))
-                   line)
+                                            (and org-export-mark-todo-in-toc
+                                                 (= level umax-toc)
+                                                 (org-search-todo-below
+                                                  line lines level))))
+                                  (if (string-match
+                                       (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") txt)
+                                      (setq txt (replace-match  "&nbsp;&nbsp;&nbsp;<span class=\"tag\"> \\1</span>" t nil txt)))
+                                  (if (string-match quote-re0 txt)
+                                      (setq txt (replace-match "" t t txt)))
+                                  (setq snumber (org-section-number level))
+                                  (if org-export-with-section-numbers
+                                      (setq txt (concat snumber " " txt)))
+                                  (if (<= level (max umax umax-toc))
+                                      (setq head-count (+ head-count 1)))
+                                  (if (<= level umax-toc)
+                                      (progn
+                                        (if (> level org-last-level)
+                                            (progn
+                                              (setq cnt (- level org-last-level))
+                                              (while (>= (setq cnt (1- cnt)) 0)
+                                                (push "\n<ul>\n<li>" thetoc))
+                                              (push "\n" thetoc)))
+                                        (if (< level org-last-level)
+                                            (progn
+                                              (setq cnt (- org-last-level level))
+                                              (while (>= (setq cnt (1- cnt)) 0)
+                                                (push "</li>\n</ul>" thetoc))
+                                              (push "\n" thetoc)))
+                                        ;; Check for targets
+                                        (while (string-match org-any-target-regexp line)
+                                          (setq line (replace-match
+                                                      (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
+                                                      t t line)))
+                                        (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
+                                          (setq txt (replace-match "" t t txt)))
+                                        (setq href
+                                              (replace-regexp-in-string
+                                               "\\." "_" (format "sec-%s" snumber)))
+                                        (setq href (or (cdr (assoc href org-export-preferred-target-alist)) href))
+                                        (push
+                                         (format
+                                          (if todo
+                                              "</li>\n<li><a href=\"#%s\"><span class=\"todo\">%s</span></a>"
+                                            "</li>\n<li><a href=\"#%s\">%s</a>")
+                                          href txt) thetoc)
+
+                                        (setq org-last-level level))
+                                    )))
+                            line)
                          lines))
            (while (> org-last-level (1- org-min-level))
              (setq org-last-level (1- org-last-level))
@@ -910,10 +1201,23 @@ lang=\"%s\" xml:lang=\"%s\">
              (org-open-par))
            (throw 'nextline nil))
 
-         (org-export-html-close-lists-maybe line)
+         ;; Explicit list closure
+         (when (equal "ORG-LIST-END" line)
+           (while local-list-indent
+             (org-close-li (car local-list-type))
+             (insert (format "</%sl>\n" (car local-list-type)))
+             (pop local-list-type)
+             (pop local-list-indent))
+           (setq in-local-list nil)
+           (org-open-par)
+           (throw 'nextline nil))
 
          ;; Protected HTML
-         (when (get-text-property 0 'org-protected line)
+         (when (and (get-text-property 0 'org-protected line)
+                    ;; Make sure it is the entire line that is protected
+                    (not (< (or (next-single-property-change
+                                 0 'org-protected line) 10000)
+                            (length line))))
            (let (par (ind (get-text-property 0 'original-indentation line)))
              (when (re-search-backward
                     "\\(<p>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t)
@@ -944,10 +1248,12 @@ lang=\"%s\" xml:lang=\"%s\">
          (when (equal "ORG-VERSE-START" line)
            (org-close-par-maybe)
            (insert "\n<p class=\"verse\">\n")
+           (setq org-par-open t)
            (setq inverse t)
            (throw 'nextline nil))
          (when (equal "ORG-VERSE-END" line)
            (insert "</p>\n")
+           (setq org-par-open nil)
            (org-open-par)
            (setq inverse nil)
            (throw 'nextline nil))
@@ -999,7 +1305,7 @@ lang=\"%s\" xml:lang=\"%s\">
                                  "\" class=\"target\">" (match-string 1 line)
                                  "@</a> ")
                          t t line)))))
-           
+
          (setq line (org-html-handle-time-stamps line))
 
          ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
@@ -1036,61 +1342,70 @@ lang=\"%s\" xml:lang=\"%s\">
              (setq desc (org-add-props
                             (concat "<img src=\"" desc "\"/>")
                             '(org-protected t))))
-           ;; FIXME: do we need to unescape here somewhere?
            (cond
             ((equal type "internal")
-             (setq rpl
-                   (concat
-                    "<a href=\""
-                    (if (= (string-to-char path) ?#) "" "#")
-                    (org-solidify-link-text
-                     (save-match-data (org-link-unescape path)) nil)
-                    "\"" attr ">"
-                    (org-export-html-format-desc desc)
-                    "</a>")))
+             (let
+                 ((frag-0
+                   (if (= (string-to-char path) ?#)
+                       (substring path 1)
+                     path)))
+               (setq rpl
+                     (org-html-make-link
+                      opt-plist
+                      ""
+                      ""
+                      (org-solidify-link-text
+                       (save-match-data (org-link-unescape frag-0))
+                       nil)
+                      desc attr nil))))
             ((and (equal type "id")
                   (setq id-file (org-id-find-id-file path)))
              ;; This is an id: link to another file (if it was the same file,
              ;; it would have become an internal link...)
              (save-match-data
                (setq id-file (file-relative-name
-                              id-file (file-name-directory org-current-export-file)))
-               (setq id-file (concat (file-name-sans-extension id-file)
-                                     "." html-extension))
-               (setq rpl (concat "<a href=\"" id-file "#"
-                                 (if (org-uuidgen-p path) "ID-")
-                                 path "\""
-                                 attr ">"
-                                 (org-export-html-format-desc desc)
-                                 "</a>"))))
+                              id-file
+                              (file-name-directory org-current-export-file)))
+               (setq rpl
+                     (org-html-make-link opt-plist
+                                         "file" id-file
+                                         (concat (if (org-uuidgen-p path) "ID-") path)
+                                         desc
+                                         attr
+                                         nil))))
             ((member type '("http" "https"))
-             ;; standard URL, just check if we need to inline an image
-             (if (and (or (eq t org-export-html-inline-images)
-                          (and org-export-html-inline-images (not descp)))
-                      (org-file-image-p
-                       path org-export-html-inline-image-extensions))
-                 (setq rpl (org-export-html-format-image
-                            (concat type ":" path) org-par-open))
-               (setq link (concat type ":" path))
-               (setq rpl (concat "<a href=\""
-                                 (org-export-html-format-href link)
-                                 "\"" attr ">"
-                                 (org-export-html-format-desc desc)
-                                 "</a>"))))
+             ;; standard URL, can inline as image
+             (setq rpl
+                   (org-html-make-link opt-plist
+                                       type path nil
+                                       desc
+                                       attr
+                                       (org-html-should-inline-p path descp))))
             ((member type '("ftp" "mailto" "news"))
-             ;; standard URL
-             (setq link (concat type ":" path))
-             (setq rpl (concat "<a href=\""
-                               (org-export-html-format-href link)
-                               "\"" attr ">"
-                               (org-export-html-format-desc desc)
-                               "</a>")))
+             ;; standard URL, can't inline as image
+             (setq rpl
+                   (org-html-make-link opt-plist
+                                       type path nil
+                                       desc
+                                       attr
+                                       nil)))
 
             ((string= type "coderef")
-             (setq rpl (format "<a href=\"#coderef-%s\" class=\"coderef\" onmouseover=\"CodeHighlightOn(this, 'coderef-%s');\" onmouseout=\"CodeHighlightOff(this, 'coderef-%s');\">%s</a>"
-                               path path path
-                               (format (org-export-get-coderef-format path (and descp desc))
-                                       (cdr (assoc path org-export-code-refs))))))
+             (let*
+                 ((coderef-str (format "coderef-%s" path))
+                  (attr-1
+                   (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\""
+                           coderef-str coderef-str)))
+               (setq rpl
+                     (org-html-make-link opt-plist
+                                         type "" coderef-str
+                                         (format
+                                          (org-export-get-coderef-format
+                                           path
+                                           (and descp desc))
+                                          (cdr (assoc path org-export-code-refs)))
+                                         attr-1
+                                         nil))))
 
             ((functionp (setq fnc (nth 2 (assoc type org-link-protocols))))
              ;; The link protocol has a function for format the link
@@ -1100,49 +1415,54 @@ lang=\"%s\" xml:lang=\"%s\">
 
             ((string= type "file")
              ;; FILE link
-             (let* ((filename path)
-                    (abs-p (file-name-absolute-p filename))
-                    thefile file-is-image-p search)
-               (save-match-data
-                 (if (string-match "::\\(.*\\)" filename)
-                     (setq search (match-string 1 filename)
-                           filename (replace-match "" t nil filename)))
-                 (setq valid
-                       (if (functionp link-validate)
-                           (funcall link-validate filename current-dir)
-                         t))
-                 (setq file-is-image-p
-                       (org-file-image-p
-                        filename org-export-html-inline-image-extensions))
-                 (setq thefile (if abs-p (expand-file-name filename) filename))
-                 (when (and org-export-html-link-org-files-as-html
-                            (string-match "\\.org$" thefile))
-                   (setq thefile (concat (substring thefile 0
-                                                    (match-beginning 0))
-                                         "." html-extension))
-                   (if (and search
-                            ;; make sure this is can be used as target search
-                            (not (string-match "^[0-9]*$" search))
-                            (not (string-match "^\\*" search))
-                            (not (string-match "^/.*/$" search)))
-                       (setq thefile (concat thefile "#"
-                                             (org-solidify-link-text
-                                              (org-link-unescape search)))))
-                   (when (string-match "^file:" desc)
-                     (setq desc (replace-match "" t t desc))
-                     (if (string-match "\\.org$" desc)
-                         (setq desc (replace-match "" t t desc))))))
-               (setq rpl (if (and file-is-image-p
-                                  (or (eq t org-export-html-inline-images)
-                                      (and org-export-html-inline-images
-                                           (not descp))))
-                             (progn
-                               (message "image %s %s" thefile org-par-open)
-                               (org-export-html-format-image thefile org-par-open))
-                           (concat "<a href=\"" thefile "\"" attr ">"
-                                   (org-export-html-format-desc desc)
-                                   "</a>")))
-               (if (not valid) (setq rpl desc))))
+             (save-match-data
+               (let*
+                   ((components
+                     (if
+                         (string-match "::\\(.*\\)" path)
+                         (list
+                          (replace-match "" t nil path)
+                          (match-string 1 path))
+                       (list path nil)))
+
+                    ;;The proper path, without a fragment
+                    (path-1
+                     (first components))
+
+                    ;;The raw fragment
+                    (fragment-0
+                     (second components))
+
+                    ;;Check the fragment.  If it can't be used as
+                    ;;target fragment we'll pass nil instead.
+                    (fragment-1
+                     (if
+                         (and fragment-0
+                              (not (string-match "^[0-9]*$" fragment-0))
+                              (not (string-match "^\\*" fragment-0))
+                              (not (string-match "^/.*/$" fragment-0)))
+                         (org-solidify-link-text
+                          (org-link-unescape fragment-0))
+                       nil))
+                    (desc-2
+                     ;;Description minus "file:" and ".org"
+                     (if (string-match "^file:" desc)
+                         (let
+                             ((desc-1 (replace-match "" t t desc)))
+                           (if (string-match "\\.org$" desc-1)
+                               (replace-match "" t t desc-1)
+                             desc-1))
+                       desc)))
+
+                 (setq rpl
+                       (if
+                           (and
+                            (functionp link-validate)
+                            (not (funcall link-validate path-1 current-dir)))
+                           desc
+                         (org-html-make-link opt-plist
+                                             "file" path-1 fragment-1 desc-2 attr
+                                             (org-html-should-inline-p path-1 descp)))))))
 
             (t
              ;; just publish the path, as default
@@ -1199,14 +1519,6 @@ lang=\"%s\" xml:lang=\"%s\">
                (setq txt (replace-match "" t t txt)))
            (if (<= level (max umax umax-toc))
                (setq head-count (+ head-count 1)))
-           (when in-local-list
-             ;; Close any local lists before inserting a new header line
-             (while local-list-type
-               (org-close-li (car local-list-type))
-               (insert (format "</%sl>\n" (car local-list-type)))
-               (pop local-list-type))
-             (setq local-list-indent nil
-                   in-local-list nil))
            (setq first-heading-pos (or first-heading-pos (point)))
            (org-html-level-start level txt umax
                                  (and org-export-with-toc (<= level umax))
@@ -1218,19 +1530,6 @@ lang=\"%s\" xml:lang=\"%s\">
              (insert "<pre>")
              (setq inquote t)))
 
-          ((string-match "^[ \t]*- __+[ \t]*$" line)
-           ;; Explicit list closure
-           (when local-list-type
-             (let ((ind (org-get-indentation line)))
-               (while (and local-list-indent
-                           (<= ind (car local-list-indent)))
-                 (org-close-li (car local-list-type))
-                 (insert (format "</%sl>\n" (car local-list-type)))
-                 (pop local-list-type)
-                 (pop local-list-indent))
-               (or local-list-indent (setq in-local-list nil))))
-           (throw 'nextline nil))
-
           ((and org-export-with-tables
                 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
            (when (not table-open)
@@ -1263,27 +1562,15 @@ lang=\"%s\" xml:lang=\"%s\">
                    starter (if (match-beginning 2)
                                (substring (match-string 2 line) 0 -1))
                    line (substring line (match-beginning 5))
+                   item-number nil
                    item-tag nil)
+             (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
+                 (setq item-number (match-string 1 line)
+                       line (replace-match "" t t line)))
              (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
                  (setq item-type "d"
                        item-tag (match-string 1 line)
                        line (substring line (match-end 0))))
-             (when (and (not (equal item-type "d"))
-                        (not (string-match "[^ \t]" line)))
-               ;; empty line.  Pretend indentation is large.
-               (setq ind (if org-empty-line-terminates-plain-lists
-                             0
-                           (1+ (or (car local-list-indent) 1)))))
-             (setq didclose nil)
-             (while (and in-local-list
-                         (or (and (= ind (car local-list-indent))
-                                  (not starter))
-                             (< ind (car local-list-indent))))
-               (setq didclose t)
-               (org-close-li (car local-list-type))
-               (insert (format "</%sl>\n" (car local-list-type)))
-               (pop local-list-type) (pop local-list-indent)
-               (setq in-local-list local-list-indent))
              (cond
               ((and starter
                     (or (not in-local-list)
@@ -1292,29 +1579,40 @@ lang=\"%s\" xml:lang=\"%s\">
                (org-close-par-maybe)
                (insert (cond
                         ((equal item-type "u") "<ul>\n<li>\n")
+                        ((and (equal item-type "o") item-number)
+                         (format "<ol>\n<li value=\"%s\">\n" item-number))
                         ((equal item-type "o") "<ol>\n<li>\n")
                         ((equal item-type "d")
                          (format "<dl>\n<dt>%s</dt><dd>\n" item-tag))))
                (push item-type local-list-type)
                (push ind local-list-indent)
                (setq in-local-list t))
+              ;; Continue list
               (starter
-               ;; continue current list
+               ;; terminate any previous sublist but first ensure
+               ;; list is not ill-formed.
+               (let ((min-ind (apply 'min local-list-indent)))
+                 (when (< ind min-ind) (setq ind min-ind)))
+               (while (< ind (car local-list-indent))
+                 (org-close-li (car local-list-type))
+                 (insert (format "</%sl>\n" (car local-list-type)))
+                 (pop local-list-type) (pop local-list-indent)
+                 (setq in-local-list local-list-indent))
+               ;; insert new item
                (org-close-li (car local-list-type))
                (insert (cond
                         ((equal (car local-list-type) "d")
                          (format "<dt>%s</dt><dd>\n" (or item-tag "???")))
-                        (t "<li>\n"))))
-              (didclose
-               ;; we did close a list, normal text follows: need <p>
-               (org-open-par)))
+                        ((and (equal item-type "o") item-number)
+                         (format "<li value=\"%s\">\n" item-number))
+                        (t "<li>\n")))))
              (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
                  (setq line
                        (replace-match
                         (if (equal (match-string 1 line) "X")
                             "<b>[X]</b>"
                           "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
-                          t t line))))
+                        t t line))))
 
            ;; Horizontal line
            (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
@@ -1369,14 +1667,7 @@ lang=\"%s\" xml:lang=\"%s\">
       (when inquote
        (insert "</pre>\n")
        (org-open-par))
-      (when in-local-list
-       ;; Close any local lists before inserting a new header line
-       (while local-list-type
-         (org-close-li (car local-list-type))
-         (insert (format "</%sl>\n" (car local-list-type)))
-         (pop local-list-type))
-       (setq local-list-indent nil
-             in-local-list nil))
+
       (org-html-level-start 1 nil umax
                            (and org-export-with-toc (<= level umax))
                            head-count)
@@ -1402,7 +1693,7 @@ lang=\"%s\" xml:lang=\"%s\">
          (when (and org-export-author-info author)
            (insert "<p class=\"author\"> "
                    (nth 1 lang-words) ": " author "\n")
-           (when email
+           (when (and org-export-email-info email (string-match "\\S-" email))
              (if (listp (split-string email ",+ *"))
                  (mapc (lambda(e)
                          (insert "<a href=\"mailto:" e "\">&lt;"
@@ -1457,8 +1748,6 @@ lang=\"%s\" xml:lang=\"%s\">
       (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
        (replace-match ""))
       (goto-char (point-min))
-      (while (re-search-forward "</ul>\\s-*<ul>\n?" nil t)
-       (replace-match ""))
       ;; Convert whitespace place holders
       (goto-char (point-min))
       (let (beg end n)
@@ -1469,6 +1758,12 @@ lang=\"%s\" xml:lang=\"%s\">
          (delete-region beg end)
          (insert (format "<span style=\"visibility:hidden;\">%s</span>"
                          (make-string n ?x)))))
+      ;; Remove empty lines at the beginning of the file.
+      (goto-char (point-min))
+      (when (looking-at "\\s-+\n") (replace-match ""))
+      ;; Remove display properties
+      (remove-text-properties (point-min) (point-max) '(display t))
+      ;; Run the hook
       (run-hooks 'org-export-html-final-hook)
       (or to-buffer (save-buffer))
       (goto-char (point-min))
@@ -1506,10 +1801,12 @@ lang=\"%s\" xml:lang=\"%s\">
   "Create image tag with source and attributes."
   (save-match-data
     (if (string-match "^ltxpng/" src)
-       (format "<img src=\"%s\"/>" src)
+       (format "<img src=\"%s\" alt=\"%s\"/>"
+                src (org-find-text-property-in-string 'org-latex-src src))
       (let* ((caption (org-find-text-property-in-string 'org-caption src))
             (attr (org-find-text-property-in-string 'org-attributes src))
             (label (org-find-text-property-in-string 'org-label src)))
+       (setq caption (and caption (org-html-do-expand caption)))
        (concat
        (if caption
            (format "%s<div %sclass=\"figure\">
@@ -1545,13 +1842,14 @@ lang=\"%s\" xml:lang=\"%s\">
        nil))))
 
 (defvar org-table-number-regexp) ; defined in org-table.el
-(defun org-format-table-html (lines olines)
-  "Find out which HTML converter to use and return the HTML code."
+(defun org-format-table-html (lines olines &optional no-css)
+  "Find out which HTML converter to use and return the HTML code.
+NO-CSS is passed to the exporter."
   (if (stringp lines)
       (setq lines (org-split-string lines "\n")))
   (if (string-match "^[ \t]*|" (car lines))
       ;; A normal org table
-      (org-format-org-table-html lines)
+      (org-format-org-table-html lines nil no-css)
     ;; Table made by table.el - test for spanning
     (let* ((hlines (delq nil (mapcar
                              (lambda (x)
@@ -1572,8 +1870,12 @@ lang=\"%s\" xml:lang=\"%s\">
        (org-format-table-table-html-using-table-generate-source olines)))))
 
 (defvar org-table-number-fraction) ; defined in org-table.el
-(defun org-format-org-table-html (lines &optional splice)
-  "Format a table into HTML."
+(defun org-format-org-table-html (lines &optional splice no-css)
+  "Format a table into HTML.
+LINES is a list of lines.  Optional argument SPLICE means, do not
+insert header and surrounding <table> tags, just format the lines.
+Optional argument NO-CSS means use XHTML attributes instead of CSS
+for formatting.  This is required for the DocBook exporter."
   (require 'org-table)
   ;; Get rid of hlines at beginning and end
   (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
@@ -1585,25 +1887,25 @@ lang=\"%s\" xml:lang=\"%s\">
     ;; column and the special lines
     (setq lines (org-table-clean-before-export lines)))
 
-  (let* ((caption (or (get-text-property 0 'org-caption (car lines))
-                     (get-text-property (or (next-single-property-change
-                                             0 'org-caption (car lines))
-                                            0)
-                                        'org-caption (car lines))))
-        (attributes (or (get-text-property 0 'org-attributes (car lines))
-                        (get-text-property (or (next-single-property-change
-                                                0 'org-attributes (car lines))
-                                               0)
-                                           'org-attributes (car lines))))
+  (let* ((caption (org-find-text-property-in-string 'org-caption (car lines)))
+        (label (org-find-text-property-in-string 'org-label (car lines)))
+        (forced-aligns (org-find-text-property-in-string 'org-forced-aligns
+                                                         (car lines)))
+        (attributes (org-find-text-property-in-string 'org-attributes
+                                                      (car lines)))
         (html-table-tag (org-export-splice-attributes
                          html-table-tag attributes))
         (head (and org-export-highlight-first-table-line
                    (delq nil (mapcar
                               (lambda (x) (string-match "^[ \t]*|-" x))
                               (cdr lines)))))
-
-        (nline 0) fnum i
-        tbopen line fields html gr colgropen rowstart rowend)
+        (nline 0) fnum nfields i (cnt 0)
+        tbopen line fields html gr colgropen rowstart rowend
+        ali align aligns n)
+    (setq caption (and caption (org-html-do-expand caption)))
+    (when (and forced-aligns org-table-clean-did-remove-column)
+    (setq forced-aligns
+         (mapcar (lambda (x) (cons (1- (car x)) (cdr x))) forced-aligns)))
     (if splice (setq head nil))
     (unless splice (push (if head "<thead>" "<tbody>") html))
     (setq tbopen t)
@@ -1619,30 +1921,34 @@ lang=\"%s\" xml:lang=\"%s\">
              (throw 'next-line t)))
        ;; Break the line into fields
        (setq fields (org-split-string line "[ \t]*|[ \t]*"))
-       (unless fnum (setq fnum (make-vector (length fields) 0)))
+       (unless fnum (setq fnum (make-vector (length fields) 0)
+                          nfields (length fnum)))
        (setq nline (1+ nline) i -1
              rowstart (eval (car org-export-table-row-tags))
              rowend (eval (cdr org-export-table-row-tags)))
        (push (concat rowstart
                      (mapconcat
                       (lambda (x)
-                        (setq i (1+ i))
-                        (if (and (< i nline)
+                        (setq i (1+ i) ali (format "@@class%03d@@" i))
+                        (if (and (< i nfields) ; make sure no rogue line causes an error here
                                  (string-match org-table-number-regexp x))
                             (incf (aref fnum i)))
                         (cond
                          (head
                           (concat
-                           (format (car org-export-table-header-tags) "col")
+                           (format (car org-export-table-header-tags)
+                                   "col" ali)
                            x
                            (cdr org-export-table-header-tags)))
                          ((and (= i 0) org-export-html-table-use-header-tags-for-first-column)
                           (concat
-                           (format (car org-export-table-header-tags) "row")
+                           (format (car org-export-table-header-tags)
+                                   "row" ali)
                            x
                            (cdr org-export-table-header-tags)))
                          (t
-                          (concat (car org-export-table-data-tags) x
+                          (concat (format (car org-export-table-data-tags) ali)
+                                  x
                                   (cdr org-export-table-data-tags)))))
                       fields "")
                      rowend)
@@ -1655,28 +1961,57 @@ lang=\"%s\" xml:lang=\"%s\">
       (unless (car org-table-colgroup-info)
        (setq org-table-colgroup-info
              (cons :start (cdr org-table-colgroup-info))))
+      (setq i 0)
       (push (mapconcat
             (lambda (x)
-              (setq gr (pop org-table-colgroup-info))
-              (format "%s<col align=\"%s\" />%s"
+              (setq gr (pop org-table-colgroup-info)
+                    i (1+ i)
+                    align (if (assoc i forced-aligns)
+                              (cdr (assoc (cdr (assoc i forced-aligns))
+                                          '(("l" . "left") ("r" . "right")
+                                            ("c" . "center"))))
+                            (if (> (/ (float x) nline)
+                                   org-table-number-fraction)
+                                "right" "left")))
+              (push align aligns)
+              (format (if no-css
+                          "%s<col align=\"%s\" />%s"
+                        "%s<col class=\"%s\" />%s")
                       (if (memq gr '(:start :startend))
                           (prog1
-                              (if colgropen "</colgroup>\n<colgroup>" "<colgroup>")
+                              (if colgropen
+                                  "</colgroup>\n<colgroup>"
+                                "<colgroup>")
                             (setq colgropen t))
                         "")
-                      (if (> (/ (float x) nline) org-table-number-fraction)
-                          "right" "left")
+                      align
                       (if (memq gr '(:end :startend))
                           (progn (setq colgropen nil) "</colgroup>")
                         "")))
             fnum "")
            html)
-      (if colgropen (setq html (cons (car html) (cons "</colgroup>" (cdr html)))))
+      (setq aligns (nreverse aligns))
+      (if colgropen (setq html (cons (car html)
+                                    (cons "</colgroup>" (cdr html)))))
       ;; Since the output of HTML table formatter can also be used in
       ;; DocBook document, we want to always include the caption to make
       ;; DocBook XML file valid.
       (push (format "<caption>%s</caption>" (or caption "")) html)
+      (when label (push (format "<a name=\"%s\" id=\"%s\"></a>" label label)
+                       html))
       (push html-table-tag html))
+    (setq html (mapcar
+               (lambda (x)
+                 (replace-regexp-in-string
+                  "@@class\\([0-9]+\\)@@"
+                  (lambda (txt)
+                    (if (not org-export-html-table-align-individual-fields)
+                        ""
+                      (setq n (string-to-number (match-string 1 txt)))
+                      (format (if no-css " align=\"%s\"" " class=\"%s\"")
+                              (or (nth n aligns) "left"))))
+                  x))
+               html))
     (concat (mapconcat 'identity html "\n") "\n")))
 
 (defun org-export-splice-attributes (tag attributes)
@@ -1721,10 +2056,10 @@ But it has the disadvantage, that no cell- or row-spanning is allowed."
                         (if (equal x "") (setq x empty))
                         (if head
                             (concat
-                             (format (car org-export-table-header-tags) "col")
+                             (format (car org-export-table-header-tags) "col" "")
                              x
                              (cdr org-export-table-header-tags))
-                          (concat (car org-export-table-data-tags) x
+                          (concat (format (car org-export-table-data-tags) "") x
                                   (cdr org-export-table-data-tags))))
                       field-buffer "\n")
                      "</tr>\n"))
@@ -1845,7 +2180,7 @@ that uses these same face definitions."
   (goto-char (point-min)))
 
 (defun org-html-protect (s)
-  ;; convert & to &amp;, < to &lt; and > to &gt;
+  "convert & to &amp;, < to &lt; and > to &gt;"
   (let ((start 0))
     (while (string-match "&" s start)
       (setq s (replace-match "&amp;" t t s)
@@ -1860,19 +2195,21 @@ that uses these same face definitions."
   s)
 
 (defun org-html-expand (string)
-  "Prepare STRING for HTML export.  Applies all active conversions.
+  "Prepare STRING for HTML export.  Apply all active conversions.
 If there are links in the string, don't modify these."
   (let* ((re (concat org-bracket-link-regexp "\\|"
-                    (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$")))
+                    (org-re "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")))
         m s l res)
-    (while (setq m (string-match re string))
-      (setq s (substring string 0 m)
-           l (match-string 0 string)
-           string (substring string (match-end 0)))
-      (push (org-html-do-expand s) res)
-      (push l res))
-    (push (org-html-do-expand string) res)
-    (apply 'concat (nreverse res))))
+    (if (string-match "^[ \t]*\\+-[-+]*\\+[ \t]*$" string)
+       string
+      (while (setq m (string-match re string))
+       (setq s (substring string 0 m)
+             l (match-string 0 string)
+             string (substring string (match-end 0)))
+       (push (org-html-do-expand s) res)
+       (push l res))
+      (push (org-html-do-expand string) res)
+      (apply 'concat (nreverse res)))))
 
 (defun org-html-do-expand (s)
   "Apply all active conversions to translate special ASCII to HTML."
@@ -1887,16 +2224,14 @@ If there are links in the string, don't modify these."
   (if org-export-with-sub-superscripts
       (setq s (org-export-html-convert-sub-super s)))
   (if org-export-with-TeX-macros
-      (let ((start 0) wd ass)
-       (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)\\({}\\)?"
+      (let ((start 0) wd rep)
+       (while (setq start (string-match "\\\\\\([a-zA-Z]+[0-9]*\\)\\({}\\)?"
                                         s start))
          (if (get-text-property (match-beginning 0) 'org-protected s)
              (setq start (match-end 0))
            (setq wd (match-string 1 s))
-           (if (setq ass (assoc wd org-html-entities))
-               (setq s (replace-match (or (cdr ass)
-                                          (concat "&" (car ass) ";"))
-                                      t t s))
+           (if (setq rep (org-entity-get-representation wd 'html))
+               (setq s (replace-match rep t t s))
              (setq start (+ start (length wd))))))))
   s)
 
@@ -1973,20 +2308,6 @@ If there are links in the string, don't modify these."
 (defvar in-local-list)
 (defvar local-list-indent)
 (defvar local-list-type)
-(defun org-export-html-close-lists-maybe (line)
-  (let ((ind (or (get-text-property 0 'original-indentation line)))
-;               (and (string-match "\\S-" line)
-;                    (org-get-indentation line))))
-       didclose)
-    (when ind
-      (while (and in-local-list
-                 (<= ind (car local-list-indent)))
-       (setq didclose t)
-       (org-close-li (car local-list-type))
-       (insert (format "</%sl>\n" (car local-list-type)))
-       (pop local-list-type) (pop local-list-indent)
-       (setq in-local-list local-list-indent))
-      (and didclose (org-open-par)))))
 
 (defvar body-only) ; dynamically scoped into this.
 (defun org-html-level-start (level title umax with-toc head-count)
@@ -1994,12 +2315,14 @@ If there are links in the string, don't modify these."
 When TITLE is nil, just close all open levels."
   (org-close-par-maybe)
   (let* ((target (and title (org-get-text-property-any 0 'target title)))
-        (extra-targets (assoc target org-export-target-aliases))
-        (preferred (cdr (assoc target org-export-preferred-target-alist)))
-        (remove (or preferred target))
+        (extra-targets (and target
+                            (assoc target org-export-target-aliases)))
+        (extra-class (and title (org-get-text-property-any 0 'html-container-class title)))
+        (preferred (and target
+                        (cdr (assoc target org-export-preferred-target-alist))))
         (l org-level-max)
-        snumber href suffix)
-    (setq extra-targets (remove remove extra-targets))
+        snumber snu href suffix)
+    (setq extra-targets (remove (or preferred target) extra-targets))
     (setq extra-targets
          (mapconcat (lambda (x)
                       (if (org-uuidgen-p x) (setq x (concat "ID-" x)))
@@ -2016,7 +2339,7 @@ When TITLE is nil, just close all open levels."
     (when title
       ;; If title is nil, this means this function is called to close
       ;; all levels, so the rest is done only if title is given
-       (when (string-match (org-re "\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
+       (when (string-match (org-re "\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") title)
          (setq title (replace-match
                       (if org-export-with-tags
                           (save-match-data
@@ -2038,16 +2361,18 @@ When TITLE is nil, just close all open levels."
                (progn
                  (org-close-li)
                  (if target
-                     (insert (format "<li id=\"%s\">" target) extra-targets title "<br/>\n")
+                     (insert (format "<li id=\"%s\">" (or preferred target))
+                             extra-targets title "<br/>\n")
                    (insert "<li>" title "<br/>\n")))
              (aset org-levels-open (1- level) t)
              (org-close-par-maybe)
              (if target
-                 (insert (format "<ul>\n<li id=\"%s\">" target)
+                 (insert (format "<ul>\n<li id=\"%s\">" (or preferred target))
                          extra-targets title "<br/>\n")
                (insert "<ul>\n<li>" title "<br/>\n"))))
        (aset org-levels-open (1- level) t)
-       (setq snumber (org-section-number level))
+       (setq snumber (org-section-number level)
+             snu (replace-regexp-in-string "\\." "_" snumber))
        (setq level (+ level org-export-html-toplevel-hlevel -1))
        (if (and org-export-with-section-numbers (not body-only))
            (setq title (concat
@@ -2055,11 +2380,12 @@ When TITLE is nil, just close all open levels."
                                 level snumber)
                         " " title)))
        (unless (= head-count 1) (insert "\n</div>\n"))
-       (setq href (cdr (assoc (concat "sec-" snumber) org-export-preferred-target-alist)))
-       (setq suffix (or href snumber))
-       (setq href (or href (concat "sec-" snumber)))
-       (insert (format "\n<div id=\"outline-container-%s\" class=\"outline-%d\">\n<h%d id=\"%s\">%s%s</h%d>\n<div class=\"outline-text-%d\" id=\"text-%s\">\n"
-                       suffix level level href
+       (setq href (cdr (assoc (concat "sec-" snu) org-export-preferred-target-alist)))
+       (setq suffix (or href snu))
+       (setq href (or href (concat "sec-" snu)))
+       (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"
+                       suffix level (if extra-class (concat " " extra-class) "")
+                       level href
                        extra-targets
                        title level level suffix))
        (org-open-par)))))