X-Git-Url: https://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fshr.el;h=bacb9d9ee906c97842a730067ced892aa0ae3c96;hp=5b5ac5ffd2ad13b0cd6559a99f6ee9d79511473a;hb=76b6b2b0a969b427bb993110f6d8c05060cf5f64;hpb=eb9291ba9f99fb28283578c39ce449f4bf8ae9ba;ds=sidebyside diff --git a/lisp/shr.el b/lisp/shr.el index 5b5ac5ffd..bacb9d9ee 100644 --- a/lisp/shr.el +++ b/lisp/shr.el @@ -101,7 +101,7 @@ fit these criteria." (insert "\n")) (if (save-excursion (beginning-of-line) - (looking-at " *")) + (looking-at " *$")) (insert "\n") (insert "\n\n"))))) @@ -114,8 +114,8 @@ fit these criteria." (defun shr-tag-u (cont) (shr-fontize-cont cont 'underline)) -(defun shr-s (cont) - (shr-fontize-cont cont 'strikethru)) +(defun shr-tag-s (cont) + (shr-fontize-cont cont 'strike-through)) (defun shr-fontize-cont (cont &rest types) (let (shr-start) @@ -142,7 +142,7 @@ fit these criteria." (browse-url (widget-get widget :url))) (defun shr-tag-img (cont) - (when (and (plusp (current-column)) + (when (and (> (current-column) 0) (not (eq shr-state 'image))) (insert "\n")) (let ((start (point-marker))) @@ -214,14 +214,15 @@ fit these criteria." image))) (defun shr-tag-pre (cont) - (let ((shr-folding-mode nil)) + (let ((shr-folding-mode 'none)) (shr-ensure-newline) (shr-generic cont) (shr-ensure-newline))) (defun shr-tag-blockquote (cont) + (shr-ensure-paragraph) (let ((shr-indentation (+ shr-indentation 4))) - (shr-tag-pre cont))) + (shr-generic cont))) (defun shr-ensure-newline () (unless (zerop (current-column)) @@ -233,34 +234,41 @@ fit these criteria." (setq shr-state nil)) (cond ((eq shr-folding-mode 'none) - (insert t)) + (insert text)) (t (let ((first t) column) - (when (and (string-match "^[ \n]" text) + (when (and (string-match "\\`[ \t\n]" text) (not (bolp))) (insert " ")) (dolist (elem (split-string text)) (setq column (current-column)) - (when (plusp column) + (when (> column 0) (cond - ((> (+ column (length elem) 1) shr-width) + ((and (or (not first) + (eq shr-state 'space)) + (> (+ column (length elem) 1) shr-width)) (insert "\n")) ((not first) (insert " ")))) (setq first nil) (when (and (bolp) - (plusp shr-indentation)) - (insert (make-string shr-indentation ? ))) + (> shr-indentation 0)) + (shr-indent)) ;; The shr-start is a special variable that is used to pass ;; upwards the first point in the buffer where the text really ;; starts. (unless shr-start (setq shr-start (point))) (insert elem)) - (when (and (string-match "[ \n]$" text) + (setq shr-state nil) + (when (and (string-match "[ \t\n]\\'" text) (not (bolp))) - (insert " ")))))) + (insert " ") + (setq shr-state 'space)))))) + +(defun shr-indent () + (insert (make-string shr-indentation ? ))) (defun shr-get-image-data (url) "Get image data for URL. @@ -285,15 +293,19 @@ Return a string with image data." (defun shr-tag-li (cont) (shr-ensure-newline) - (if (numberp shr-list-mode) - (progn - (insert (format "%d " shr-list-mode)) - (setq shr-list-mode (1+ shr-list-mode))) - (insert "* ")) - (shr-generic cont)) + (let* ((bullet + (if (numberp shr-list-mode) + (prog1 + (format "%d " shr-list-mode) + (setq shr-list-mode (1+ shr-list-mode))) + "* ")) + (shr-indentation (+ shr-indentation (length bullet)))) + (insert bullet) + (shr-generic cont))) (defun shr-tag-br (cont) - (shr-ensure-newline) + (unless (bobp) + (insert "\n")) (shr-generic cont)) (defun shr-tag-h1 (cont) @@ -319,6 +331,138 @@ Return a string with image data." (apply #'shr-fontize-cont cont types) (shr-ensure-paragraph)) +(defun shr-tag-table (cont) + (shr-ensure-paragraph) + (setq cont (or (cdr (assq 'tbody cont)) + cont)) + (let* ((columns (shr-column-specs cont)) + (suggested-widths (shr-pro-rate-columns columns)) + (sketch (shr-make-table cont suggested-widths)) + (sketch-widths (shr-table-widths sketch (length suggested-widths)))) + (shr-insert-table (shr-make-table cont sketch-widths t) sketch-widths))) + +(defun shr-insert-table (table widths) + (shr-insert-table-ruler widths) + (dolist (row table) + (let ((start (point)) + (height (let ((max 0)) + (dolist (column row) + (setq max (max max (cadr column)))) + max))) + (dotimes (i height) + (shr-indent) + (insert "|\n")) + (dolist (column row) + (goto-char start) + (let ((lines (split-string (nth 2 column) "\n"))) + (dolist (line lines) + (when (> (length line) 0) + (end-of-line) + (insert line "|") + (forward-line 1))) + ;; Add blank lines at padding at the bottom of the TD, + ;; possibly. + (dotimes (i (- height (length lines))) + (end-of-line) + (insert (make-string (length (car lines)) ? ) "|") + (forward-line 1))))) + (shr-insert-table-ruler widths))) + +(defun shr-insert-table-ruler (widths) + (shr-indent) + (insert "+") + (dotimes (i (length widths)) + (insert (make-string (aref widths i) ?-) ?+)) + (insert "\n")) + +(defun shr-table-widths (table length) + (let ((widths (make-vector length 0))) + (dolist (row table) + (let ((i 0)) + (dolist (column row) + (aset widths i (max (aref widths i) + (car column))) + (incf i)))) + widths)) + +(defun shr-make-table (cons widths &optional fill) + (let ((trs nil)) + (dolist (row cont) + (when (eq (car row) 'tr) + (let ((i 0) + (tds nil)) + (dolist (column (cdr row)) + (when (memq (car column) '(td th)) + (push (shr-render-td (cdr column) (aref widths i) fill) + tds) + (setq i (1+ i)))) + (push (nreverse tds) trs)))) + (nreverse trs))) + +(defun shr-render-td (cont width fill) + (with-temp-buffer + (let ((shr-width width)) + (shr-generic cont)) + (while (re-search-backward "\n *$" nil t) + (delete-region (match-beginning 0) (match-end 0))) + (goto-char (point-min)) + (let ((max 0)) + (while (not (eobp)) + (end-of-line) + (setq max (max max (current-column))) + (forward-line 1)) + (when fill + (goto-char (point-min)) + (while (not (eobp)) + (end-of-line) + (insert (make-string (- width (current-column)) ? )) + (forward-line 1))) + (list max (count-lines (point-min) (point-max)) (buffer-string))))) + +(defun shr-pro-rate-columns (columns) + (let ((total-percentage 0) + (widths (make-vector (length columns) 0))) + (dotimes (i (length columns)) + (incf total-percentage (aref columns i))) + (setq total-percentage (/ 1.0 total-percentage)) + (dotimes (i (length columns)) + (aset widths i (max (truncate (* (aref columns i) + total-percentage + shr-width)) + 10))) + widths)) + +;; Return a summary of the number and shape of the TDs in the table. +(defun shr-column-specs (cont) + (let ((columns (make-vector (shr-max-columns cont) 1))) + (dolist (row cont) + (when (eq (car row) 'tr) + (let ((i 0)) + (dolist (column (cdr row)) + (when (memq (car column) '(td th)) + (let ((width (cdr (assq :width (cdr column))))) + (when (and width + (string-match "\\([0-9]+\\)%" width)) + (aset columns i + (/ (string-to-number (match-string 1 width)) + 100.0))))) + (setq i (1+ i)))))) + columns)) + +(defun shr-count (cont elem) + (let ((i 0)) + (dolist (sub cont) + (when (eq (car sub) elem) + (setq i (1+ i)))) + i)) + +(defun shr-max-columns (cont) + (let ((max 0)) + (dolist (row cont) + (when (eq (car row) 'tr) + (setq max (max max (shr-count (cdr row) 'td))))) + max)) + (provide 'shr) ;;; shr.el ends here