Browse Source

HTML export: Improved support for field alignment, including centering

* doc/org.texi: Document the <c> cookie.
* lisp/org-exp.el (org-store-forced-table-alignment):
(org-export-remove-special-table-lines): Allow the "c" cookie for
table alignment.
* lisp/org-html.el (org-export-table-header-tags):
(org-export-table-data-tags): Add another %s format for the alignment.
(org-export-html-table-align-individual-fields): New option.
(org-format-org-table-html): Implement field-by-field alignment and
support centering.
(org-format-table-table-html): Make sure the new table tag formats
don't break this function.
* lisp/org-table.el (org-table-cookie-line-p):
(org-table-align): Allow for the <c> cookie.
* lisp/org.el (org-set-font-lock-defaults): Allow for the <c> cookie.
Carsten Dominik 15 years ago
parent
commit
ca991d2ad4
6 changed files with 74 additions and 39 deletions
  1. 4 3
      doc/org.texi
  2. 5 5
      lisp/org-exp.el
  3. 56 21
      lisp/org-html.el
  4. 1 1
      lisp/org-latex.el
  5. 7 8
      lisp/org-table.el
  6. 1 1
      lisp/org.el

+ 4 - 3
doc/org.texi

@@ -1922,9 +1922,10 @@ on a per-file basis with:
 @end example
 @end example
 
 
 If you would like to overrule the automatic alignment of number-rich columns
 If you would like to overrule the automatic alignment of number-rich columns
-to the right and of string-rich column to the left, you and use @samp{<r>} or
-@samp{<l>} in a similar fashion.  You may also combine alignment and field
-width like this: @samp{<l10>}.
+to the right and of string-rich column to the left, you and use @samp{<r>},
+@samp{c}@footnote{Centering does not work inside Emacs, but it does have an
+effect when exporting to HTML.} or @samp{<l>} in a similar fashion.  You may
+also combine alignment and field width like this: @samp{<l10>}.
 
 
 Lines which only contain these formatting cookies will be removed
 Lines which only contain these formatting cookies will be removed
 automatically when exporting the document.
 automatically when exporting the document.

+ 5 - 5
lisp/org-exp.el

@@ -1776,19 +1776,19 @@ When it is nil, all comments will be removed."
 
 
 (defun org-store-forced-table-alignment ()
 (defun org-store-forced-table-alignment ()
   "Find table lines which force alignment, store the results in properties."
   "Find table lines which force alignment, store the results in properties."
-  (let (line)
+  (let (line cnt aligns)
     (goto-char (point-min))
     (goto-char (point-min))
-    (while (re-search-forward "|[ \t]*<[rl][0-9]*>[ \t]*|" nil t)
+    (while (re-search-forward "|[ \t]*<[lrc][0-9]*>[ \t]*|" nil t)
       ;; OK, this looks like a table line with an alignment cookie
       ;; OK, this looks like a table line with an alignment cookie
       (org-if-unprotected
       (org-if-unprotected
        (setq line (buffer-substring (point-at-bol) (point-at-eol)))
        (setq line (buffer-substring (point-at-bol) (point-at-eol)))
        (when (and (org-at-table-p)
        (when (and (org-at-table-p)
 		  (org-table-cookie-line-p line))
 		  (org-table-cookie-line-p line))
 	 (setq cnt 0 aligns nil)
 	 (setq cnt 0 aligns nil)
-	 (mapcar
+	 (mapc
 	  (lambda (x)
 	  (lambda (x)
 	    (setq cnt (1+ cnt))
 	    (setq cnt (1+ cnt))
-	    (if (string-match "\\`<\\([lr]\\)" x)
+	    (if (string-match "\\`<\\([lrc]\\)" x)
 		(push (cons cnt (downcase (match-string 1 x))) aligns)))
 		(push (cons cnt (downcase (match-string 1 x))) aligns)))
 	  (org-split-string line "[ \t]*|[ \t]*"))
 	  (org-split-string line "[ \t]*|[ \t]*"))
 	 (add-text-properties (org-table-begin) (org-table-end)
 	 (add-text-properties (org-table-begin) (org-table-end)
@@ -1810,7 +1810,7 @@ Also, store forcedalignment information found in such lines."
 		 (lambda (f)
 		 (lambda (f)
 		   (or (= (length f) 0)
 		   (or (= (length f) 0)
 		       (string-match
 		       (string-match
-			"\\`<\\([0-9]\\|[rl]\\|[rl][0-9]+\\)>\\'" f)))
+			"\\`<\\([0-9]\\|[lrc]\\|[lrc][0-9]+\\)>\\'" f)))
 		 (org-split-string ;; FIXME, can't we do without splitting???
 		 (org-split-string ;; FIXME, can't we do without splitting???
 		  (buffer-substring (point-at-bol) (point-at-eol))
 		  (buffer-substring (point-at-bol) (point-at-eol))
 		  "[ \t]*|[ \t]*")))))
 		  "[ \t]*|[ \t]*")))))

+ 56 - 21
lisp/org-html.el

@@ -400,17 +400,22 @@ borders and spacing."
   :group 'org-export-html
   :group 'org-export-html
   :type 'string)
   :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.
   "The opening tag for table header fields.
 This is customizable so that alignment options can be specified.
 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
   :group 'org-export-tables
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
   :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.
   "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
   :group 'org-export-tables
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
   :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
 
 
@@ -441,7 +446,13 @@ will give even lines the class \"tr-even\" and odd lines the class \"tr-odd\"."
 		  (string :tag "Specify")
 		  (string :tag "Specify")
 		  (sexp))))
 		  (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
 (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.
@@ -1869,9 +1880,9 @@ lang=\"%s\" xml:lang=\"%s\">
 		    (delq nil (mapcar
 		    (delq nil (mapcar
 			       (lambda (x) (string-match "^[ \t]*|-" x))
 			       (lambda (x) (string-match "^[ \t]*|-" x))
 			       (cdr lines)))))
 			       (cdr lines)))))
-
 	 (nline 0) fnum nfields i (cnt 0)
 	 (nline 0) fnum nfields i (cnt 0)
-	 tbopen line fields html gr colgropen rowstart rowend)
+	 tbopen line fields html gr colgropen rowstart rowend
+	 ali align aligns n)
     (setq caption (and caption (org-html-do-expand caption)))
     (setq caption (and caption (org-html-do-expand caption)))
     (when (and forced-aligns org-table-clean-did-remove-column)
     (when (and forced-aligns org-table-clean-did-remove-column)
     (setq forced-aligns
     (setq forced-aligns
@@ -1899,23 +1910,26 @@ lang=\"%s\" xml:lang=\"%s\">
 	(push (concat rowstart
 	(push (concat rowstart
 		      (mapconcat
 		      (mapconcat
 		       (lambda (x)
 		       (lambda (x)
-			 (setq i (1+ i))
+			 (setq i (1+ i) ali (format "@@align%03d@@" i))
 			 (if (and (< i nfields) ; make sure no rogue line causes an error here
 			 (if (and (< i nfields) ; make sure no rogue line causes an error here
 				  (string-match org-table-number-regexp x))
 				  (string-match org-table-number-regexp x))
 			     (incf (aref fnum i)))
 			     (incf (aref fnum i)))
 			 (cond
 			 (cond
 			  (head
 			  (head
 			   (concat
 			   (concat
-			    (format (car org-export-table-header-tags) "col")
+			    (format (car org-export-table-header-tags)
+				    "col" ali)
 			    x
 			    x
 			    (cdr org-export-table-header-tags)))
 			    (cdr org-export-table-header-tags)))
 			  ((and (= i 0) org-export-html-table-use-header-tags-for-first-column)
 			  ((and (= i 0) org-export-html-table-use-header-tags-for-first-column)
 			   (concat
 			   (concat
-			    (format (car org-export-table-header-tags) "row")
+			    (format (car org-export-table-header-tags)
+				    "row" ali)
 			    x
 			    x
 			    (cdr org-export-table-header-tags)))
 			    (cdr org-export-table-header-tags)))
 			  (t
 			  (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)))))
 				   (cdr org-export-table-data-tags)))))
 		       fields "")
 		       fields "")
 		      rowend)
 		      rowend)
@@ -1932,23 +1946,32 @@ lang=\"%s\" xml:lang=\"%s\">
       (push (mapconcat
       (push (mapconcat
 	     (lambda (x)
 	     (lambda (x)
 	       (setq gr (pop org-table-colgroup-info)
 	       (setq gr (pop org-table-colgroup-info)
-		     i (1+ i))
+		     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 "%s<col align=\"%s\" />%s"
 	       (format "%s<col align=\"%s\" />%s"
 		       (if (memq gr '(:start :startend))
 		       (if (memq gr '(:start :startend))
 			   (prog1
 			   (prog1
-			       (if colgropen "</colgroup>\n<colgroup>" "<colgroup>")
+			       (if colgropen
+				   "</colgroup>\n<colgroup>"
+				 "<colgroup>")
 			     (setq colgropen t))
 			     (setq colgropen t))
 			 "")
 			 "")
-		       (if (assoc i forced-aligns)
-			   (cdr (assoc (cdr (assoc i forced-aligns)) '(("l" . "left") ("r" . "right"))))
-			 (if (> (/ (float x) nline) org-table-number-fraction)
-			     "right" "left"))
+		       align
 		       (if (memq gr '(:end :startend))
 		       (if (memq gr '(:end :startend))
 			   (progn (setq colgropen nil) "</colgroup>")
 			   (progn (setq colgropen nil) "</colgroup>")
 			 "")))
 			 "")))
 	     fnum "")
 	     fnum "")
 	    html)
 	    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
       ;; Since the output of HTML table formatter can also be used in
       ;; DocBook document, we want to always include the caption to make
       ;; DocBook document, we want to always include the caption to make
       ;; DocBook XML file valid.
       ;; DocBook XML file valid.
@@ -1956,6 +1979,18 @@ lang=\"%s\" xml:lang=\"%s\">
       (when label (push (format "<a name=\"%s\" id=\"%s\"></a>" label label)
       (when label (push (format "<a name=\"%s\" id=\"%s\"></a>" label label)
 			html))
 			html))
       (push html-table-tag html))
       (push html-table-tag html))
+    (setq html (mapcar
+		(lambda (x)
+		  (replace-regexp-in-string
+		   "@@align\\([0-9]+\\)@@"
+		   (lambda (txt)
+		     (if (not org-export-html-table-align-individual-fields)
+			 ""
+		       (setq n (string-to-number (match-string 1 txt)))
+		       (format " style=\"text-align:%s\""
+			       (or (nth n aligns) "left"))))
+		   x))
+		html))
     (concat (mapconcat 'identity html "\n") "\n")))
     (concat (mapconcat 'identity html "\n") "\n")))
 
 
 (defun org-export-splice-attributes (tag attributes)
 (defun org-export-splice-attributes (tag attributes)
@@ -2000,10 +2035,10 @@ But it has the disadvantage, that no cell- or row-spanning is allowed."
 			 (if (equal x "") (setq x empty))
 			 (if (equal x "") (setq x empty))
 			 (if head
 			 (if head
 			     (concat
 			     (concat
-			      (format (car org-export-table-header-tags) "col")
+			      (format (car org-export-table-header-tags) "col" "")
 			      x
 			      x
 			      (cdr org-export-table-header-tags))
 			      (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))))
 				   (cdr org-export-table-data-tags))))
 		       field-buffer "\n")
 		       field-buffer "\n")
 		      "</tr>\n"))
 		      "</tr>\n"))

+ 1 - 1
lisp/org-latex.el

@@ -1277,7 +1277,7 @@ OPT-PLIST is the options plist for current buffer."
        (plist-get opt-plist :latex-header-extra)))
        (plist-get opt-plist :latex-header-extra)))
      ;; append another special variable
      ;; append another special variable
      (org-export-apply-macros-in-string org-export-latex-append-header)
      (org-export-apply-macros-in-string org-export-latex-append-header)
-     ;; define align if not yet defined
+     ;; define alert if not yet defined
      "\n\\providecommand{\\alert}[1]{\\textbf{#1}}"
      "\n\\providecommand{\\alert}[1]{\\textbf{#1}}"
      ;; insert the title
      ;; insert the title
      (format
      (format

+ 7 - 8
lisp/org-table.el

@@ -342,19 +342,18 @@ available parameters."
 
 
 (defun org-table-cookie-line-p (line)
 (defun org-table-cookie-line-p (line)
   "Is this a table line with only alignment/width cookies?"
   "Is this a table line with only alignment/width cookies?"
-
   (save-match-data
   (save-match-data
     (and (string-match "[<>]\\|&[lg]t;" line)
     (and (string-match "[<>]\\|&[lg]t;" line)
 	 (or (string-match
 	 (or (string-match
-	      "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lgt&;]+\\)\\'" line)
-	     (string-match "\\(\\`[ \t<>lr0-9|gt&;]+\\'\\)" line))
+	      "\\`[ \t]*|[ \t]*/[ \t]*\\(|[ \t<>0-9|lrcgt&;]+\\)\\'" line)
+	     (string-match "\\(\\`[ \t<>lrc0-9|gt&;]+\\'\\)" line))
 	 (not (delq nil (mapcar
 	 (not (delq nil (mapcar
 			 (lambda (s)
 			 (lambda (s)
 			   (not (or (equal s "")
 			   (not (or (equal s "")
 				    (string-match
 				    (string-match
-				     "\\`<\\([lr]?[0-9]+\\|[lr]\\)>\\'" s)
+				     "\\`<\\([lrc]?[0-9]+\\|[lrc]\\)>\\'" s)
 				    (string-match
 				    (string-match
-				     "\\`&lt;\\([lr]?[0-9]+\\|[lr]\\)&gt;\\'"
+				     "\\`&lt;\\([lrc]?[0-9]+\\|[lrc]\\)&gt;\\'"
 				     s))))
 				     s))))
 			 (org-split-string (match-string 1 line)
 			 (org-split-string (match-string 1 line)
 					   "[ \t]*|[ \t]*")))))))
 					   "[ \t]*|[ \t]*")))))))
@@ -662,9 +661,9 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
     (goto-char beg)
     (goto-char beg)
     (setq narrow (and org-table-do-narrow
     (setq narrow (and org-table-do-narrow
 		      org-format-transports-properties-p
 		      org-format-transports-properties-p
-		      (re-search-forward "<[rl]?[0-9]+>" end t)))
+		      (re-search-forward "<[lrc]?[0-9]+>" end t)))
     (goto-char beg)
     (goto-char beg)
-    (setq falign (re-search-forward "<[rl][0-9]*>" end t))
+    (setq falign (re-search-forward "<[lrc][0-9]*>" end t))
     (goto-char beg)
     (goto-char beg)
     ;; Get the rows
     ;; Get the rows
     (setq lines (org-split-string
     (setq lines (org-split-string
@@ -705,7 +704,7 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
 	(setq c column fmax nil falign1 nil)
 	(setq c column fmax nil falign1 nil)
 	(while c
 	(while c
 	  (setq e (pop c))
 	  (setq e (pop c))
-	  (when (and (stringp e) (string-match "^<\\([rl]\\)?\\([0-9]+\\)?>$" e))
+	  (when (and (stringp e) (string-match "^<\\([lrc]\\)?\\([0-9]+\\)?>$" e))
 	    (if (match-end 1) (setq falign1 (match-string 1 e)))
 	    (if (match-end 1) (setq falign1 (match-string 1 e)))
 	    (if (and org-table-do-narrow (match-end 2))
 	    (if (and org-table-do-narrow (match-end 2))
 		(setq fmax (string-to-number (match-string 2 e)) c nil))))
 		(setq fmax (string-to-number (match-string 2 e)) c nil))))

+ 1 - 1
lisp/org.el

@@ -5457,7 +5457,7 @@ needs to be inserted at a specific position in the font-lock sequence.")
 	   '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
 	   '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
 	   '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
 	   '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
 	   '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
 	   '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
-	   '("| *\\(<[lr]?[0-9]*>\\)" (1 'org-formula t))
+	   '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t))
 	   ;; Drawers
 	   ;; Drawers
 	   (list org-drawer-regexp '(0 'org-special-keyword t))
 	   (list org-drawer-regexp '(0 'org-special-keyword t))
 	   (list "^[ \t]*:END:" '(0 'org-special-keyword t))
 	   (list "^[ \t]*:END:" '(0 'org-special-keyword t))