Emacs-Wiki Tricks

I use, or more accurately planning to use, the excellent EmacsWiki to create my web pages. I also use HtmlFontify to generate nice looking HTML pages out of source code that I want to put up on the web. So I wrote a couple of functions that allows me to include emacs fontified text on a web page. In fact this page itself was created from: http://www.stanford.edu/~satyakid/EmacsWikiTricks

First add the following code to your .emacs:

;;; Load everything ...
(require 'emacs-wiki)
(require 'htmlfontify)
(require 'cl)

;;; Style sheet for HTML output. To use your own colors/fonts etc you should
;;; change the pre.fontlock and span.* styles.
(setq emacs-wiki-style-sheet
       "<style type=\"text/css\">
a.nonexistent {
  font-weight: bold; background-color: white; color: #FF2222;
}
a.nonexistent:visited {
  background-color: white; color: #FF2222;
}
body {
  background: white; color: rgb(47,79,79);
  margin-left: 5%; margin-right: 5%; margin-top: 3%
}

em { font-style: italic; }
strong { font-weight: bold }
ul { list-style-type: disc }
dl.contents { margin-top: 0 }
dt.contents { margin-bottom: 0 }
p.verse { white-space: pre; margin-left: 5% }
pre { white-space: pre; margin-left: 5% }
pre.fontlock {
  white-space: pre; margin-left: 5%;
  border-color: black; border-width: 1px; border-style: solid;
  background: rgb(255,228,196);
  margin: 1em; padding: 1em;
  text-align: left;
}

span.default {
  background: rgb(255,228,196); color: rgb(47,79,79);
  font-style: normal; font-weight: 500;  font-stretch: semi-condensed;
  font-family: misc-fixed; font-size: 9pt;
  text-decoration: none;
}
span.default a {
  background: rgb(255,228,196); color: rgb(47,79,79);
  font-style: normal; font-weight: 500;  font-stretch: semi-condensed;
  font-family: misc-fixed; font-size: 9pt;
  text-decoration: underline;
}

span.builtin { color: rgb(186,85,211) }
span.builtin a { color: rgb(186,85,211) }
span.type { color: rgb(0,139,139) }
span.type a { color: rgb(0,139,139) }
span.keyword { color: rgb(205,0,0) }
span.keyword a { color: rgb(205,0,0) }
span.comment { color: rgb(79,148,205) }
span.comment a { color: rgb(79,148,205) }
span.constant { background: rgb(255,218,185); color: rgb(205,133,0) }
span.constant a { background: rgb(255,218,185); color: rgb(205,133,0) }
span.warning { color: rgb(255,0,0) }
span.warning a { color: rgb(255,0,0) }
span.function-name { color: rgb(0,0,205) }
span.function-name a { color: rgb(0,0,205) }
span.variable-name { color: rgb(145,44,238) }
span.variable-name a { color: rgb(145,44,238) }
span.string { background: rgb(255,218,185); color: rgb(34,139,34) }
span.string a { background: rgb(255,218,185); color: rgb(34,139,34) }
</style>")

(defun sd-htmlfontify-insert-region (buffer begin end)
  "Insert into BUFFER the htmlified text between BEGIN and END."
  (save-excursion
    (let* ((hfy-optimisations (cons 'skip-refontification hfy-optimisations))
           (input-text (buffer-substring begin end))
           (temp-file (make-temp-file "html-input"))
           output-buffer)
      (with-temp-buffer
        (insert input-text)
        (setq buffer-file-name temp-file)
        (save-excursion (setq output-buffer (htmlfontify-buffer nil nil)))
        (set-buffer-modified-p nil))

      (unwind-protect
          (let (b e yanked-output)
            (set-buffer output-buffer)
            (goto-char (point-min))
            (search-forward "<pre>\n")
            (setq b (line-beginning-position))
            (goto-char (point-max))
            (search-backward "</pre>")
            (forward-line -1)
            (setq e (line-beginning-position))
            (setq yanked-output (buffer-substring-no-properties b e))
            (set-buffer buffer)
            (insert yanked-output))
        (set-buffer output-buffer)
        (set-buffer-modified-p nil)
        (delete-file temp-file)
        (kill-buffer output-buffer)))))

(defun sd-emacs-wiki-fontlock-tag (beg end attrs highlight-p)
  (if highlight-p
      (goto-char end)
    ;; I don't know what would happen if you don't have
    ;; htmlfontify. I guess if you are installing this you
    ;; should have it...
    (let ((end-marker (set-marker (make-marker) (1+ end))))
      (save-restriction
        (narrow-to-region beg end)
        (let* ((mode (cdr (assoc "mode" attrs)))
               (start (progn (forward-line) (point)))
               (stop (progn (goto-char end) (beginning-of-line) (point)))
               (text (buffer-substring-no-properties start stop))
               (buffer (current-buffer)))
          (delete-region beg end)
          (with-temp-buffer
            (insert text)
            (when (and mode (and (stringp mode) (functionp (intern mode))))
              (funcall (intern mode))
              (font-lock-fontify-buffer))
            (sd-htmlfontify-insert-region buffer (point-min) (point-max)))
          (goto-char (point-min))
          (insert "<pre class=\"fontlock\">\n")
          (goto-char (point-max))
          (insert "</pre>\n")
          (add-text-properties (point-min) (point-max)
                               '(rear-nonsticky (read-only) read-only t))))
      (goto-char end-marker))))

(push '("fontlock" t t t sd-emacs-wiki-fontlock-tag) emacs-wiki-markup-tags)
Now you are done. You should be able to insert the following (but note that there is an extra space after the < in the closing tag, since I couldn't figure out how to get the tags to show up properly in the HTML output) in a emacs wiki page and see nicely colorized HTML output when you publish it. Enjoy!

<fontlock mode="emacs-lisp-mode">
;; Factorial function
(defun factorial (n)
  "Compute n!"
  (if (eql n 0) 1 (* n (factorial (1- n)))))
< /fontlock>

Satyaki Das
Last modified: Sun May 11 10:44:00 PDT 2003