Advertisement
txe

fixxing-org-blog.el

txe
Jun 8th, 2017
375
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 11.17 KB | None | 0 0
  1. ;;; seen at https://www.emacswiki.org/emacs/download/org-blog.el
  2. ;;; org-blog.el --- create and publish a blog with org-mode
  3.  
  4. ;; Copyright (C) 2006  David O'Toole
  5.  
  6. ;; Author: David O'Toole <dto@gnu.org>
  7. ;; Keywords: hypermedia, tools
  8. ;; $Id: org-blog.el,v 1.18 2007/06/13 16:21:24 dto Exp dto $   
  9.  
  10. ;; This file is free software; you can redistribute it and/or modify
  11. ;; it under the terms of the GNU General Public License as published by
  12. ;; the Free Software Foundation; either version 2, or (at your option)
  13. ;; any later version.
  14.  
  15. ;; This file is distributed in the hope that it will be useful,
  16. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;; GNU General Public License for more details.
  19.  
  20. ;; You should have received a copy of the GNU General Public License
  21. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  22. ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  23. ;; Boston, MA 02110-1301, USA.
  24.  
  25. ;;; Commentary:
  26.  
  27. ;; This program adds simple blog publishing support to org-mode. It is
  28. ;; built on top of org-publish.el.
  29.  
  30. ;; You should read the documentation for org-publish.el before
  31. ;; continuing.
  32.  
  33. ;; The latest version of this program, and of org-publish.el, can be
  34. ;; found at: http://dto.freeshell.org/notebook/OrgMode.html
  35.  
  36. ;;;; 1. Basic configuration
  37. ;;
  38. ;;    First add (require 'org-blog) to your emacs initialization file.
  39. ;;
  40. ;;    Then set the variable org-blog-directory (you can also leave it
  41. ;;    as the default, "~/blog/"). This directory should be different
  42. ;;    from the directory where your normal *.org files are stored,
  43. ;;    otherwise they will get "posted".
  44. ;;
  45. ;;    You should also set the variable
  46. ;;    org-blog-unfinished-directory. The default is
  47. ;;    "~/blog/unfinished". This is the directory where unfinished
  48. ;;    posts are stored. You can leave posts in the unfinished
  49. ;;    directory while you are working on them, and they won't be
  50. ;;    published.
  51.  
  52. ;;;; 2. Create a post
  53. ;;
  54. ;;    Use M-x org-blog-new-post. You'll be prompted for a
  55. ;;    filename. Enter a short name for this post (without the ".org")
  56. ;;    and press RET. You'll see a new buffer with a blank TITLE field.
  57.  
  58. ;;    You can work on more than one post at once. They'll all be
  59. ;;    stored in your `org-blog-unfinished-directory'. To view a list
  60. ;;    of posts in progress, use M-x
  61. ;;    org-blog-find-unfinished-posts. You'll see the directory listing
  62. ;;    of `org-blog-unfinished-directory', and you can use RET to
  63. ;;    select a post to edit.
  64.  
  65. ;;;; 3. Finish a post
  66. ;;
  67. ;;    When your post is ready, visit the file and hit M-x
  68. ;;    org-blog-finish-post. This does not mean the post is published
  69. ;;    on your website, only that the post is "finished" and given a
  70. ;;    timestamped filename. Your blog post and updated index will be
  71. ;;    published when you execute M-x org-publish-all.
  72. ;;
  73. ;;    But first, let's take a detour to make sure blog publishing is
  74. ;;    set up properly.
  75.  
  76. ;;;; 4. Configure blog publishing
  77. ;;
  78. ;;    Org-blog contains an index function to publish a front page for
  79. ;;    your blog. This index can be configured to display the most
  80. ;;    recent posts, and your "blogroll" or list of links to other
  81. ;;    blogs. The newest post will always be at the top.
  82. ;;    
  83. ;;    You should add a project called "blog" to your
  84. ;;    org-publish-project-alist. Here is an example project
  85. ;;    configuration you can adapt to your needs:
  86.  
  87. ;; '("blog" :base-directory "~/blog/"
  88. ;;      :base-extension "org"
  89. ;;      :publishing-directory "/protocol:user@host:~/html/blog/"
  90. ;;      :publishing-function org-publish-org-to-html
  91. ;;      :auto-index t
  92. ;;          :blog-base-url "http://dto.freeshell.org/blog/"
  93. ;;      :blog-title "dto.freeshell.org blog"
  94. ;;      :blog-description "David O'Toole's web log."
  95. ;;      :blog-export-rss t
  96. ;;      :index-function org-publish-blog-index
  97. ;;      :index-filename "index.org"
  98. ;;      :index-title "Title of my Blog"
  99. ;;      :index-posts 2
  100. ;;          :preamble my-blogroll-html
  101. ;;          :postamble my-footer-html)
  102.  
  103. ;;    Most of these keywords are documented along with
  104. ;;    org-publish-project-alist. Before moving on, we'll explain
  105. ;;    usages specific to blogging support.
  106.  
  107. ;;    The keyword :index-posts controls how many posts will be shown
  108. ;;    on the blog's front page. Set its value to an integer. Remaining
  109. ;;    posts will be shown as a list of links at the bottom of the
  110. ;;    page.
  111.  
  112. ;;    The :index-title should be used to set the title of your blog.
  113. ;;    You can use the standard :preamble and :postamble keywords to
  114. ;;    set the header and footer of your blog posts and front page.
  115. ;;    This is a great place to include your HTML blogroll and
  116. ;;    copyright notices.
  117.  
  118. ;;;;  5. Now publish!
  119. ;;
  120. ;;    After you've updated your org-publish-project-alist and created
  121. ;;    a post or two, hit M-x org-publish-all. Your posts should be
  122. ;;    uploaded, and an index frontpage generated.
  123.  
  124.  
  125. ;;; Code:
  126.  
  127. (require 'org-publish)
  128.  
  129. (defgroup org-blog nil
  130.   "Options for keeping and publishing a blog with org-mode."
  131.   :tag "Org Blog"
  132.   :group 'org-publish)
  133.  
  134. (defcustom org-blog-directory "~/blog/"
  135.   "Directory where finished blog posts are stored."
  136.   :group 'org-blog)
  137.  
  138. (defcustom org-blog-unfinished-directory "~/blog/unfinished"
  139.   "Directory where unfinished posts are stored."
  140.   :group 'org-blog)
  141.  
  142. (defcustom org-blog-time-format "%Y-%m-%d %I:%M%p -- "
  143.   "Format string used when timestamping posts."
  144.   :group 'org-blog)
  145.  
  146. (defun org-blog-new-post-file ()
  147.   (concat (file-name-as-directory org-blog-directory) (format-time-string "blog-%Y-%m-%d-%H%M.org")))
  148.  
  149. (defun org-blog-new-post (filename)
  150.   "Create a new post in FILENAME.
  151. Post is stored in `org-blog-unfinished-directory'."
  152.   (interactive "sFilename for new post: ")
  153.   (find-file (concat (file-name-as-directory org-blog-unfinished-directory)
  154.              filename ".org"))
  155.   (insert "#+TITLE: \n")
  156.   (insert "#+DESCRIPTION: "))
  157.  
  158. (defun org-blog-find-unfinished-posts ()
  159.   "Open `org-blog-unfinished-directory'."
  160.   (interactive)
  161.   (let ((dir (file-name-as-directory org-blog-unfinished-directory)))
  162.     (when (not (file-exists-p dir))
  163.       (make-directory dir t))
  164.     (find-file dir)))
  165.  
  166. (defun org-blog-finish-post ()
  167.   "Complete and timestamp the unfinished post in the current buffer.
  168. Follow up with org-publish-all to upload to the site."
  169.   (interactive)
  170.   (write-file (org-blog-new-post-file)))
  171.  
  172. ;; pluggable index generation function for org-publish.
  173.  
  174. (defun org-publish-blog-index (plist &optional index-filename)
  175.   "Publish an index of all finished blog posts.
  176. This function is suitable for use in the :index-function keyword
  177. of org-publish-project-alist."
  178.   (let* ((posts (nreverse (sort (org-publish-get-base-files plist "*~") 'string<)))
  179.      (base-directory (file-name-as-directory (or org-blog-directory (plist-get plist :base-directory))))
  180.      (blog-base-url (file-name-as-directory (plist-get plist :blog-base-url)))
  181.      (blog-title (plist-get plist :blog-title))
  182.      (publishing-directory (file-name-as-directory
  183.                 (plist-get plist :publishing-directory)))
  184.      (blog-description (plist-get plist :blog-description))
  185.      (blog-rss-feed nil)
  186.      (rss (plist-get plist :blog-export-rss))
  187.      (post-content nil)
  188.      (index-file (concat base-directory (or index-filename "index.org")))
  189.      (index-buffer (find-buffer-visiting index-file))
  190.      (num-posts (or (plist-get plist :index-posts) 5))
  191.      (index-title (plist-get plist :index-title))
  192.      (count 0)
  193.      (p nil))
  194.  
  195.     (message "RSS = %S" rss)
  196.     ;;
  197.     ;; if buffer is already open, kill it
  198.     (if index-buffer
  199.     (kill-buffer index-buffer))
  200.     ;;
  201.     ;; start the RSS feed
  202.     (when rss
  203.       (push (org-blog-rss-preamble blog-title blog-base-url blog-description)
  204.         blog-rss-feed))
  205.     ;;
  206.     (with-temp-buffer
  207.       ;;
  208.       ;; process each post
  209.       (while (setq p (pop posts))
  210.     (let ((basename (file-name-nondirectory p))
  211.           (post-title nil)
  212.           (post-time (format-time-string
  213.               "%a, %d %b %Y %H:%M:00 %z"
  214.               (nth 5 (file-attributes p))))      
  215.           (post-description nil))
  216.       ;;
  217.       ;; grab post details
  218.       (with-temp-buffer
  219.         (insert-file-contents p)
  220.         ;;
  221.         ;; make sure we are in org-mode (otherwise export won't work properly)
  222.         (let ((org-inhibit-startup t)) (org-mode))
  223.         (goto-char (point-min))
  224.         (re-search-forward "#\\+TITLE: \\(.*\\)$" nil t)
  225.         (setf post-title (match-string 1))
  226.         (re-search-forward "#\\+DESCRIPTION: \\(.*\\)$" nil t)
  227.         (setf post-description (match-string 1))
  228.         (setf post-content (buffer-substring-no-properties
  229.                 (match-end 1) (point-max))))
  230.       ;;
  231.       ;; avoid inserting existing index; this would be a loop!
  232.       (when (not (string= basename index-filename))
  233.         ;;
  234.         ;; add rss item
  235.         (when rss
  236.           (push (org-blog-rss-item post-title
  237.                        (concat blog-base-url
  238.                            (file-name-sans-extension
  239.                         (file-name-nondirectory p))
  240.                            ".html")
  241.                        post-content
  242.                        post-time)          
  243.             blog-rss-feed))
  244.         (if (< count num-posts)
  245.         ;;
  246.         ;; insert full text of post
  247.         (progn (insert-file-contents p)
  248.                ;; permalink
  249.                (goto-char (point-max))
  250.                (insert (with-temp-buffer
  251.                  (insert (concat "\n\n [[file:" basename "][Permalink]]\n\n"))
  252.                  (buffer-substring-no-properties (point-min) (point-max)))))
  253.          
  254.           ;;
  255.           ;; or, just insert link with title
  256.           (progn
  257.         (goto-char (point-max))
  258.         (when (= count num-posts)
  259.           (insert "\n** Older posts\n"))
  260.         (insert (concat " - [[file:"
  261.                 basename "]["
  262.                 post-title "]]\n")))))
  263.       (setq count (+ 1 count))))
  264.       ;;
  265.       ;; finish rss feed and write
  266.       (when rss
  267.     (push (org-blog-rss-postamble) blog-rss-feed)
  268.     (with-temp-buffer
  269.       (apply 'insert (nreverse blog-rss-feed))
  270.       (message "%S - %S"
  271.            (concat publishing-directory "blog.rss")
  272.            blog-rss-feed)
  273.      
  274.       (write-file (concat publishing-directory "blog.xml"))))
  275.       ;;
  276.       ;; turn pasted titles into headings
  277.       (goto-char (point-min))
  278.       (while (search-forward "#+TITLE: " nil t)
  279.     (replace-match "** " nil t))
  280.       ;;
  281.       ;; insert index title, if any
  282.       (when index-title
  283.     (goto-char (point-min))
  284.     (insert (concat "#+TITLE: " index-title "\n\n")))
  285.       (write-file index-file)
  286.       (kill-buffer (current-buffer)))))
  287.    
  288.  
  289. ;;;; minimal RSS 2.0 support
  290.  
  291.  
  292. (defun org-blog-rss-preamble (title link description)
  293.   (format
  294. "<rss version=\"2.0\">
  295.   <channel>
  296.      <title>%s</title>
  297.      <link>%s</link>
  298.      <description>%s</description>
  299.      <generator>OrgBlog</generator>"
  300.  title link description))
  301.  
  302.  
  303. (defun org-blog-rss-postamble ()
  304.   "</channel></rss>")
  305.  
  306.  
  307. (defun org-blog-rss-item (title permalink description pubdate)
  308.   (let ((description-html (with-temp-buffer
  309.                 (insert description)
  310.                 (org-export-region-as-html (point-min) (point-max)
  311.                                :body-only 'string))))
  312.     (format
  313.      " <item>
  314. <title>%s</title>
  315. <description>%s</description>
  316. <pubDate>%s</pubDate>
  317. <guid isPermaLink=\"true\">%s</guid>
  318. </item>\n" title description-html pubdate permalink)))
  319.  
  320.  
  321.  
  322.  
  323. (provide 'org-blog)
  324. ;;; org-blog.el ends here
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement