summaryrefslogtreecommitdiffstats
path: root/emacs.d/elisp/muse/muse-journal.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/elisp/muse/muse-journal.el')
-rw-r--r--emacs.d/elisp/muse/muse-journal.el774
1 files changed, 774 insertions, 0 deletions
diff --git a/emacs.d/elisp/muse/muse-journal.el b/emacs.d/elisp/muse/muse-journal.el
new file mode 100644
index 0000000..e523b4c
--- /dev/null
+++ b/emacs.d/elisp/muse/muse-journal.el
@@ -0,0 +1,774 @@
+;;; muse-journal.el --- keep and publish a journal
+
+;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;; Free Software Foundation, Inc.
+
+;; This file is part of Emacs Muse. It is not part of GNU Emacs.
+
+;; Emacs Muse is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; Emacs Muse is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with Emacs Muse; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; The module facilitates the keeping and publication of a journal.
+;; When publishing to HTML, it assumes the form of a web log, or blog.
+;;
+;; The input format for each entry is as follows:
+;;
+;; * 20040317: Title of entry
+;;
+;; Text for the entry.
+;;
+;; <qotd>
+;; "You know who you are. It comes down to a simple gut check: You
+;; either love what you do or you don't. Period." -- P. Bronson
+;; </qotd>
+;;
+;; The "qotd", or Quote of the Day, is entirely optional. When
+;; generated to HTML, this entry is rendered as:
+;;
+;; <div class="entry">
+;; <div class="entry-qotd">
+;; <h3>Quote of the Day:</h3>
+;; <p>"You know who you are. It comes down to a simple gut
+;; check: You either love what you do or you don't. Period."
+;; -- P. Bronson</p>
+;; </div>
+;; <div class="entry-body">
+;; <div class="entry-head">
+;; <div class="entry-date">
+;; <span class="date">March 17, 2004</span>
+;; </div>
+;; <div class="entry-title">
+;; <h2>Title of entry</h2>
+;; </div>
+;; </div>
+;; <div class="entry-text">
+;; <p>Text for the entry.</p>
+;; </div>
+;; </div>
+;; </div>
+;;
+;; The plurality of "div" tags makes it possible to display the
+;; entries in any form you wish, using a CSS style.
+;;
+;; Also, an .RDF file can be generated from your journal by publishing
+;; it with the "rdf" style. It uses the first two sentences of the
+;; first paragraph of each entry as its "description", and
+;; autogenerates tags for linking to the various entries.
+
+;;; Contributors:
+
+;; René Stadler (mail AT renestadler DOT de) provided a patch that
+;; causes dates in RSS feeds to be generated in a format that RSS
+;; readers can parse.
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Muse Journal Publishing
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'muse-publish)
+(require 'muse-html)
+(require 'muse-latex)
+(require 'muse-book)
+
+(defgroup muse-journal nil
+ "Rules for transforming a journal into its final form."
+ :group 'muse-publish)
+
+(defcustom muse-journal-heading-regexp
+ "\\(?:\\([0-9]+\\)\\(?:: \\)?\\)?\\(.+?\\)?"
+ "A regexp that matches a journal heading.
+Paren group 1 is the ISO date, group 2 is the optional category,
+and group 3 is the optional heading for the entry."
+ :type 'regexp
+ :group 'muse-journal)
+
+(defcustom muse-journal-date-format "%a, %e %b %Y"
+ "Date format to use for journal entries."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-html-heading-regexp
+ (concat "^<h2[^>\n]*>" muse-journal-heading-regexp "</h2>$")
+ "A regexp that matches a journal heading from an HTML document.
+Paren group 1 is the ISO date, group 2 is the optional category,
+and group 3 is the optional heading for the entry."
+ :type 'regexp
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-heading-regexp
+ (concat "^\\* " muse-journal-heading-regexp "$")
+ "A regexp that matches a journal heading from an HTML document.
+Paren group 1 is the ISO date, group 2 is the optional category,
+and group 3 is the optional heading for the entry."
+ :type 'regexp
+ :group 'muse-journal)
+
+(defcustom muse-journal-html-entry-template
+ "<div class=\"entry\">
+ <a name=\"%anchor%\" style=\"text-decoration: none\">&nbsp;</a>
+ <div class=\"entry-body\">
+ <div class=\"entry-head\">
+ <div class=\"entry-date\">
+ <span class=\"date\">%date%</span>
+ </div>
+ <div class=\"entry-title\">
+ <h2>%title%</h2>
+ </div>
+ </div>
+ <div class=\"entry-text\">
+ <div class=\"entry-qotd\">
+ <p>%qotd%</p>
+ </div>
+%text%
+ </div>
+ </div>
+</div>\n\n"
+ "Template used to publish individual journal entries as HTML.
+This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-latex-section
+ "\\section*{%title% \\hfill {\\normalsize %date%}}
+\\addcontentsline{toc}{chapter}{%title%}"
+ "Template used to publish a LaTeX section."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-latex-subsection
+ "\\subsection*{%title%}
+\\addcontentsline{toc}{section}{%title%}"
+ "Template used to publish a LaTeX subsection."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-markup-tags
+ '(("qotd" t nil nil muse-journal-qotd-tag))
+ "A list of tag specifications, for specially marking up Journal entries.
+See `muse-publish-markup-tags' for more info.
+
+This is used by journal-latex and its related styles, as well as
+the journal-rss-entry style, which both journal-rdf and
+journal-rss use."
+ :type '(repeat (list (string :tag "Markup tag")
+ (boolean :tag "Expect closing tag" :value t)
+ (boolean :tag "Parse attributes" :value nil)
+ (boolean :tag "Nestable" :value nil)
+ function))
+ :group 'muse-journal)
+
+;; FIXME: This doesn't appear to be used.
+(defun muse-journal-generate-pages ()
+ (let ((output-dir (muse-style-element :path)))
+ (goto-char (point-min))
+ (while (re-search-forward muse-journal-heading-regexp nil t)
+ (let* ((date (match-string 1))
+ (category (match-string 1))
+ (category-file (concat output-dir category "/index.html"))
+ (heading (match-string 1)))
+ t))))
+
+(defcustom muse-journal-rdf-extension ".rdf"
+ "Default file extension for publishing RDF (RSS 1.0) files."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-base-url ""
+ "The base URL of the website referenced by the RDF file."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-header
+ "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+ xmlns=\"http://purl.org/rss/1.0/\"
+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\">
+ <channel rdf:about=\"<lisp>(concat (muse-style-element :base-url)
+ (muse-publish-link-name))</lisp>\">
+ <title><lisp>(muse-publishing-directive \"title\")</lisp></title>
+ <link><lisp>(concat (muse-style-element :base-url)
+ (concat (muse-page-name)
+ muse-html-extension))</lisp></link>
+ <description><lisp>(muse-publishing-directive \"desc\")</lisp></description>
+ <items>
+ <rdf:Seq>
+ <rdf:li resource=\"<lisp>
+ (concat (muse-style-element :base-url)
+ (concat (muse-page-name)
+ muse-html-extension))</lisp>\"/>
+ </rdf:Seq>
+ </items>
+ </channel>\n"
+ "Header used for publishing RDF (RSS 1.0) files.
+This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-footer
+ "</rdf:RDF>\n"
+ "Footer used for publishing RDF (RSS 1.0) files.
+This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-date-format
+ "%Y-%m-%dT%H:%M:%S"
+ "Date format to use for RDF entries."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-entry-template
+ "\n <item rdf:about=\"%link%#%anchor%\">
+ <title>%title%</title>
+ <description>
+ %desc%
+ </description>
+ <link>%link%#%anchor%</link>
+ <dc:date>%date%</dc:date>
+ <dc:creator>%maintainer%</dc:creator>
+ </item>\n"
+ "Template used to publish individual journal entries as RDF.
+This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rdf-summarize-entries nil
+ "If non-nil, include only summaries in the RDF file, not the full data.
+
+The default is nil, because this annoys some subscribers."
+ :type 'boolean
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-extension ".xml"
+ "Default file extension for publishing RSS 2.0 files."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-base-url ""
+ "The base URL of the website referenced by the RSS file."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-header
+ "<\?xml version=\"1.0\" encoding=\"<lisp>
+ (muse-html-encoding)</lisp>\"?>
+<rss version=\"2.0\">
+ <channel>
+ <title><lisp>(muse-publishing-directive \"title\")</lisp></title>
+ <link><lisp>(concat (muse-style-element :base-url)
+ (concat (muse-page-name)
+ muse-html-extension))</lisp></link>
+ <description><lisp>(muse-publishing-directive \"desc\")</lisp></description>
+ <language>en-us</language>
+ <generator>Emacs Muse</generator>\n\n"
+ "Header used for publishing RSS 2.0 files. This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-footer
+ "\n\n </channel>
+</rss>\n"
+ "Footer used for publishing RSS 2.0 files. This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-date-format
+ "%a, %d %b %Y %H:%M:%S %Z"
+ "Date format to use for RSS 2.0 entries."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-entry-template
+ "\n <item>
+ <title>%title%</title>
+ <link>%link%#%anchor%</link>
+ <description>%desc%</description>
+ <author><lisp>(muse-publishing-directive \"author\")</lisp></author>
+ <pubDate>%date%</pubDate>
+ <guid>%link%#%anchor%</guid>
+ %enclosure%
+ </item>\n"
+ "Template used to publish individual journal entries as RSS 2.0.
+This may be text or a filename."
+ :type 'string
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-enclosure-types-alist
+ '(("mp3" . "audio/mpeg"))
+ "File types that are accepted as RSS enclosures.
+This is an alist that maps file extension to content type.
+Useful for podcasting."
+ :type '(alist :key-type string :value-type string)
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-summarize-entries nil
+ "If non-nil, include only summaries in the RSS file, not the full data.
+
+The default is nil, because this annoys some subscribers."
+ :type 'boolean
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-markup-regexps
+ '((10000 muse-explicit-link-regexp 0 "\\2"))
+ "List of markup rules for publishing a Muse journal page to RSS 2.0.
+For more information on the structure of this list, see
+`muse-publish-markup-regexps'."
+ :type '(repeat (choice
+ (list :tag "Markup rule"
+ integer
+ (choice regexp symbol)
+ integer
+ (choice string function symbol))
+ function))
+ :group 'muse-journal)
+
+(defcustom muse-journal-rss-markup-functions
+ '((email . ignore)
+ (link . ignore)
+ (url . ignore))
+ "An alist of style types to custom functions for that kind of text.
+For more on the structure of this list, see
+`muse-publish-markup-functions'."
+ :type '(alist :key-type symbol :value-type function)
+ :group 'muse-journal)
+
+(defun muse-journal-anchorize-title (title)
+ "This strips tags from TITLE, truncates TITLE at begin parenthesis,
+and escapes any remaining non-alphanumeric characters."
+ (save-match-data
+ (if (string-match "(" title)
+ (setq title (substring title 0 (match-beginning 0))))
+ (if (string-match "<[^>]+>" title)
+ (setq title (replace-match "" nil nil title)))
+ (let (pos code len ch)
+ (while (setq pos (string-match (concat "[^" muse-regexp-alnum "_]")
+ title pos))
+ (setq ch (aref title pos)
+ code (format "%%%02X" (cond ((fboundp 'char-to-ucs)
+ (char-to-ucs ch))
+ ((fboundp 'char-to-int)
+ (char-to-int ch))
+ (t ch)))
+ len (length code)
+ title (concat (substring title 0 pos)
+ code
+ (when (< pos (length title))
+ (substring title (1+ pos) nil)))
+ pos (+ len pos)))
+ title)))
+
+(defun muse-journal-sort-entries (&optional direction)
+ (interactive "P")
+ (sort-subr
+ direction
+ (function
+ (lambda ()
+ (if (re-search-forward "^\\* [0-9]+" nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-max)))))
+ (function
+ (lambda ()
+ (if (re-search-forward "^\\* [0-9]+" nil t)
+ (goto-char (1- (match-beginning 0)))
+ (goto-char (point-max)))))
+ (function
+ (lambda ()
+ (forward-char 2)))
+ (function
+ (lambda ()
+ (end-of-line)))))
+
+(defun muse-journal-qotd-tag (beg end)
+ (muse-publish-ensure-block beg end)
+ (muse-insert-markup (muse-markup-text 'begin-quote))
+ (muse-insert-markup (muse-markup-text 'begin-quote-item))
+ (goto-char end)
+ (muse-insert-markup (muse-markup-text 'end-quote-item))
+ (muse-insert-markup (muse-markup-text 'end-quote)))
+
+(defun muse-journal-html-munge-buffer ()
+ (goto-char (point-min))
+ (let ((heading-regexp muse-journal-html-heading-regexp)
+ (inhibit-read-only t))
+ (while (re-search-forward heading-regexp nil t)
+ (let* ((date (match-string 1))
+ (orig-date date)
+ (title (match-string 2))
+ (clean-title title)
+ datestamp qotd text)
+ (delete-region (match-beginning 0) (match-end 0))
+ (if clean-title
+ (save-match-data
+ (while (string-match "\\(^<[^>]+>\\|<[^>]+>$\\)" clean-title)
+ (setq clean-title (replace-match "" nil nil clean-title)))))
+ (save-match-data
+ (when (and date
+ (string-match
+ (concat "\\`\\([1-9][0-9][0-9][0-9]\\)[./]?"
+ "\\([0-1][0-9]\\)[./]?\\([0-3][0-9]\\)") date))
+ (setq datestamp
+ (encode-time
+ 0 0 0
+ (string-to-number (match-string 3 date))
+ (string-to-number (match-string 2 date))
+ (string-to-number (match-string 1 date))
+ nil)
+ date (concat (format-time-string
+ muse-journal-date-format datestamp)
+ (substring date (match-end 0))))))
+ (save-restriction
+ (narrow-to-region
+ (point) (if (re-search-forward
+ (concat "\\(^<hr>$\\|"
+ heading-regexp "\\)") nil t)
+ (match-beginning 0)
+ (point-max)))
+ (goto-char (point-max))
+ (while (and (not (bobp))
+ (eq ?\ (char-syntax (char-before))))
+ (delete-char -1))
+ (goto-char (point-min))
+ (while (and (not (eobp))
+ (eq ?\ (char-syntax (char-after))))
+ (delete-char 1))
+ (save-excursion
+ (when (search-forward "<qotd>" nil t)
+ (let ((tag-beg (match-beginning 0))
+ (beg (match-end 0))
+ end)
+ (re-search-forward "</qotd>\n*")
+ (setq end (point-marker))
+ (save-restriction
+ (narrow-to-region beg (match-beginning 0))
+ (muse-publish-escape-specials (point-min) (point-max)
+ nil 'document)
+ (setq qotd (buffer-substring-no-properties
+ (point-min) (point-max))))
+ (delete-region tag-beg end)
+ (set-marker end nil))))
+ (setq text (buffer-string))
+ (delete-region (point-min) (point-max))
+ (let ((entry muse-journal-html-entry-template))
+ (muse-insert-file-or-string entry)
+ (muse-publish-mark-read-only (point-min) (point-max))
+ (goto-char (point-min))
+ (while (search-forward "%date%" nil t)
+ (remove-text-properties (match-beginning 0) (match-end 0)
+ '(read-only nil rear-nonsticky nil))
+ (replace-match (or date "") nil t))
+ (goto-char (point-min))
+ (while (search-forward "%title%" nil t)
+ (remove-text-properties (match-beginning 0) (match-end 0)
+ '(read-only nil rear-nonsticky nil))
+ (replace-match (or title "&nbsp;") nil t))
+ (goto-char (point-min))
+ (while (search-forward "%anchor%" nil t)
+ (replace-match (muse-journal-anchorize-title
+ (or clean-title orig-date))
+ nil t))
+ (goto-char (point-min))
+ (while (search-forward "%qotd%" nil t)
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (delete-region (point-min) (point-max))
+ (when qotd (muse-insert-markup qotd))))
+ (goto-char (point-min))
+ (while (search-forward "%text%" nil t)
+ (remove-text-properties (match-beginning 0) (match-end 0)
+ '(read-only nil rear-nonsticky nil))
+ (replace-match text nil t))
+ (when (null qotd)
+ (goto-char (point-min))
+ (when (search-forward "<div class=\"entry-qotd\">" nil t)
+ (let ((beg (match-beginning 0)))
+ (re-search-forward "</div>\n*" nil t)
+ (delete-region beg (point))))))))))
+ ;; indicate that we are to continue the :before-end processing
+ nil)
+
+(defun muse-journal-latex-munge-buffer ()
+ (goto-char (point-min))
+ (let ((heading-regexp
+ (concat "^" (regexp-quote (muse-markup-text 'section))
+ muse-journal-heading-regexp
+ (regexp-quote (muse-markup-text 'section-end)) "$"))
+ (inhibit-read-only t))
+ (when (re-search-forward heading-regexp nil t)
+ (goto-char (match-beginning 0))
+ (sort-subr nil
+ (function
+ (lambda ()
+ (if (re-search-forward heading-regexp nil t)
+ (goto-char (match-beginning 0))
+ (goto-char (point-max)))))
+ (function
+ (lambda ()
+ (if (re-search-forward heading-regexp nil t)
+ (goto-char (1- (match-beginning 0)))
+ (goto-char (point-max)))))
+ (function
+ (lambda ()
+ (forward-char 2)))
+ (function
+ (lambda ()
+ (end-of-line)))))
+ (while (re-search-forward heading-regexp nil t)
+ (let ((date (match-string 1))
+ (title (match-string 2))
+ ;; FIXME: Nothing is done with qotd
+ qotd section)
+ (save-match-data
+ (when (and date
+ (string-match
+ (concat "\\([1-9][0-9][0-9][0-9]\\)[./]?"
+ "\\([0-1][0-9]\\)[./]?\\([0-3][0-9]\\)") date))
+ (setq date (encode-time
+ 0 0 0
+ (string-to-number (match-string 3 date))
+ (string-to-number (match-string 2 date))
+ (string-to-number (match-string 1 date))
+ nil)
+ date (format-time-string
+ muse-journal-date-format date))))
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (delete-region (point-min) (point-max))
+ (muse-insert-markup muse-journal-latex-section)
+ (goto-char (point-min))
+ (while (search-forward "%title%" nil t)
+ (replace-match (or title "Untitled") nil t))
+ (goto-char (point-min))
+ (while (search-forward "%date%" nil t)
+ (replace-match (or date "") nil t))))))
+ (goto-char (point-min))
+ (let ((subheading-regexp
+ (concat "^" (regexp-quote (muse-markup-text 'subsection))
+ "\\([^\n}]+\\)"
+ (regexp-quote (muse-markup-text 'subsection-end)) "$"))
+ (inhibit-read-only t))
+ (while (re-search-forward subheading-regexp nil t)
+ (let ((title (match-string 1)))
+ (save-restriction
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (delete-region (point-min) (point-max))
+ (muse-insert-markup muse-journal-latex-subsection)
+ (goto-char (point-min))
+ (while (search-forward "%title%" nil t)
+ (replace-match title nil t))))))
+ ;; indicate that we are to continue the :before-end processing
+ nil)
+
+(defun muse-journal-rss-munge-buffer ()
+ (goto-char (point-min))
+ (let ((heading-regexp muse-journal-rss-heading-regexp)
+ (inhibit-read-only t))
+ (while (re-search-forward heading-regexp nil t)
+ (let* ((date (match-string 1))
+ (orig-date date)
+ (title (match-string 2))
+ ;; FIXME: Nothing is done with qotd
+ enclosure qotd desc)
+ (if title
+ (save-match-data
+ (if (string-match muse-explicit-link-regexp title)
+ (setq enclosure (muse-get-link title)
+ title (muse-get-link-desc title)))))
+ (save-match-data
+ (when (and date
+ (string-match
+ (concat "\\([1-9][0-9][0-9][0-9]\\)[./]?"
+ "\\([0-1][0-9]\\)[./]?\\([0-3][0-9]\\)") date))
+ (setq date (encode-time 0 0 0
+ (string-to-number (match-string 3 date))
+ (string-to-number (match-string 2 date))
+ (string-to-number (match-string 1 date))
+ nil)
+ ;; make sure that date is in a format that RSS
+ ;; readers can handle
+ date (let ((system-time-locale "C"))
+ (format-time-string
+ (muse-style-element :date-format) date)))))
+ (save-restriction
+ (narrow-to-region
+ (match-beginning 0)
+ (if (re-search-forward heading-regexp nil t)
+ (match-beginning 0)
+ (if (re-search-forward "^Footnotes:" nil t)
+ (match-beginning 0)
+ (point-max))))
+ (goto-char (point-min))
+ (delete-region (point) (muse-line-end-position))
+ (re-search-forward "</qotd>\n+" nil t)
+ (while (and (char-after)
+ (eq ?\ (char-syntax (char-after))))
+ (delete-char 1))
+ (let ((beg (point)))
+ (if (muse-style-element :summarize)
+ (progn
+ (forward-sentence 2)
+ (setq desc (concat (buffer-substring beg (point)) "...")))
+ (save-restriction
+ (muse-publish-markup-buffer "rss-entry" "journal-rss-entry")
+ (goto-char (point-min))
+ (if (re-search-forward "Page published by Emacs Muse" nil t)
+ (goto-char (muse-line-end-position))
+ (muse-display-warning
+ (concat
+ "Cannot find 'Page published by Emacs Muse begins here'.\n"
+ "You will probably need this text in your header."))
+ (goto-char (point-min)))
+ (setq beg (point))
+ (if (re-search-forward "Page published by Emacs Muse" nil t)
+ (goto-char (muse-line-beginning-position))
+ (muse-display-warning
+ (concat
+ "Cannot find 'Page published by Emacs Muse ends here'.\n"
+ "You will probably need this text in your footer."))
+ (goto-char (point-max)))
+ (setq desc (buffer-substring beg (point))))))
+ (unless (string= desc "")
+ (setq desc (concat "<![CDATA[" desc "]]>")))
+ (delete-region (point-min) (point-max))
+ (let ((entry (muse-style-element :entry-template)))
+ (muse-insert-file-or-string entry)
+ (goto-char (point-min))
+ (while (search-forward "%date%" nil t)
+ (replace-match (or date "") nil t))
+ (goto-char (point-min))
+ (while (search-forward "%title%" nil t)
+ (replace-match "")
+ (save-restriction
+ (narrow-to-region (point) (point))
+ (insert (or title "Untitled"))
+ (remove-text-properties (match-beginning 0) (match-end 0)
+ '(read-only nil rear-nonsticky nil))
+ (let ((muse-publishing-current-style (muse-style "html")))
+ (muse-publish-escape-specials (point-min) (point-max)
+ nil 'document))))
+ (goto-char (point-min))
+ (while (search-forward "%desc%" nil t)
+ (replace-match desc nil t))
+ (goto-char (point-min))
+ (while (search-forward "%enclosure%" nil t)
+ (replace-match
+ (if (null enclosure)
+ ""
+ (save-match-data
+ (format
+ "<enclosure url=\"%s\" %stype=\"%s\"/>"
+ (if (string-match "//" enclosure)
+ enclosure
+ (concat (muse-style-element :base-url)
+ enclosure))
+ (let ((file
+ (expand-file-name enclosure
+ (muse-style-element :path))))
+ (if (file-readable-p file)
+ (format "length=\"%d\" "
+ (nth 7 (file-attributes file)))
+ ""))
+ (if (string-match "\\.\\([^.]+\\)$" enclosure)
+ (let* ((ext (match-string 1 enclosure))
+ (type
+ (assoc
+ ext muse-journal-rss-enclosure-types-alist)))
+ (if type
+ (cdr type)
+ "application/octet-stream"))))))
+ nil t))
+ (goto-char (point-min))
+ (while (search-forward "%link%" nil t)
+ (replace-match
+ (concat (muse-style-element :base-url)
+ (concat (muse-page-name)
+ muse-html-extension))
+ nil t))
+ (goto-char (point-min))
+ (while (search-forward "%anchor%" nil t)
+ (replace-match
+ (muse-journal-anchorize-title (or title orig-date))
+ nil t))
+ (goto-char (point-min))
+ (while (search-forward "%maintainer%" nil t)
+ (replace-match
+ (or (muse-style-element :maintainer)
+ (concat "webmaster@" (system-name)))
+ nil t)))))))
+ ;; indicate that we are to continue the :before-end processing
+ nil)
+
+
+;;; Register the Muse Journal Publishers
+
+(muse-derive-style "journal-html" "html"
+ :before-end 'muse-journal-html-munge-buffer)
+
+(muse-derive-style "journal-xhtml" "xhtml"
+ :before-end 'muse-journal-html-munge-buffer)
+
+(muse-derive-style "journal-latex" "latex"
+ :tags 'muse-journal-markup-tags
+ :before-end 'muse-journal-latex-munge-buffer)
+
+(muse-derive-style "journal-pdf" "pdf"
+ :tags 'muse-journal-markup-tags
+ :before-end 'muse-journal-latex-munge-buffer)
+
+(muse-derive-style "journal-book-latex" "book-latex"
+ ;;:nochapters
+ :tags 'muse-journal-markup-tags
+ :before-end 'muse-journal-latex-munge-buffer)
+
+(muse-derive-style "journal-book-pdf" "book-pdf"
+ ;;:nochapters
+ :tags 'muse-journal-markup-tags
+ :before-end 'muse-journal-latex-munge-buffer)
+
+(muse-define-style "journal-rdf"
+ :suffix 'muse-journal-rdf-extension
+ :regexps 'muse-journal-rss-markup-regexps
+ :functions 'muse-journal-rss-markup-functions
+ :before 'muse-journal-rss-munge-buffer
+ :header 'muse-journal-rdf-header
+ :footer 'muse-journal-rdf-footer
+ :date-format 'muse-journal-rdf-date-format
+ :entry-template 'muse-journal-rdf-entry-template
+ :base-url 'muse-journal-rdf-base-url
+ :summarize 'muse-journal-rdf-summarize-entries)
+
+(muse-define-style "journal-rss"
+ :suffix 'muse-journal-rss-extension
+ :regexps 'muse-journal-rss-markup-regexps
+ :functions 'muse-journal-rss-markup-functions
+ :before 'muse-journal-rss-munge-buffer
+ :header 'muse-journal-rss-header
+ :footer 'muse-journal-rss-footer
+ :date-format 'muse-journal-rss-date-format
+ :entry-template 'muse-journal-rss-entry-template
+ :base-url 'muse-journal-rss-base-url
+ :summarize 'muse-journal-rss-summarize-entries)
+
+;; Used by `muse-journal-rss-munge-buffer' to mark up individual entries
+(muse-derive-style "journal-rss-entry" "html"
+ :tags 'muse-journal-markup-tags)
+
+(provide 'muse-journal)
+
+;;; muse-journal.el ends here