Commit 70abefc0a6
Unsigned
Layout: unified · split
elisp/ox-rss.el added +434
| @@ -0,0 +1,434 @@ | |||
| 1 | ;;; ox-rss.el --- RSS 2.0 Back-End for Org Export Engine | ||
| 2 | |||
| 3 | ;; Copyright (C) 2013-2021 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Bastien Guerry <bzg@gnu.org> | ||
| 6 | ;; Maintainer: Benedict Wang <foss@bhw.name> | ||
| 7 | ;; Version: 0.0.1 | ||
| 8 | ;; Package-Requires: ((emacs "26.1") (org "9.3")) | ||
| 9 | ;; Keywords: org, wp, blog, feed, rss | ||
| 10 | ;; Homepage: https://github.com/benedicthw/ox-rss.git | ||
| 11 | |||
| 12 | ;; This file is not part of GNU Emacs. | ||
| 13 | |||
| 14 | ;; This program is free software: you can redistribute it and/or modify | ||
| 15 | ;; it under the terms of the GNU General Public License as published by | ||
| 16 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 17 | ;; (at your option) any later version. | ||
| 18 | |||
| 19 | ;; This program is distributed in the hope that it will be useful, | ||
| 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 22 | ;; GNU General Public License for more details. | ||
| 23 | |||
| 24 | ;; You should have received a copy of the GNU General Public License | ||
| 25 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;; This library implements an RSS 2.0 back-end for Org exporter, based | ||
| 30 | ;; on the `html' back-end. | ||
| 31 | ;; | ||
| 32 | ;; It requires Emacs 24.1 at least. | ||
| 33 | ;; | ||
| 34 | ;; It provides two commands for export, depending on the desired output: | ||
| 35 | ;; `org-rss-export-as-rss' (temporary buffer) and `org-rss-export-to-rss' | ||
| 36 | ;; (as a ".xml" file). | ||
| 37 | ;; | ||
| 38 | ;; This backend understands three new option keywords: | ||
| 39 | ;; | ||
| 40 | ;; #+RSS_EXTENSION: xml | ||
| 41 | ;; #+RSS_IMAGE_URL: https://myblog.org/mypicture.jpg | ||
| 42 | ;; #+RSS_FEED_URL: https://myblog.org/feeds/blog.xml | ||
| 43 | ;; | ||
| 44 | ;; It uses #+HTML_LINK_HOME: to set the base url of the feed. | ||
| 45 | ;; | ||
| 46 | ;; Exporting an Org file to RSS modifies each top-level entry by adding a | ||
| 47 | ;; PUBDATE property. If `org-rss-use-entry-url-as-guid', it will also add | ||
| 48 | ;; an ID property, later used as the guid for the feed's item. | ||
| 49 | ;; | ||
| 50 | ;; The top-level headline is used as the title of each RSS item unless | ||
| 51 | ;; an RSS_TITLE property is set on the headline. | ||
| 52 | ;; | ||
| 53 | ;; You typically want to use it within a publishing project like this: | ||
| 54 | ;; | ||
| 55 | ;; (add-to-list | ||
| 56 | ;; 'org-publish-project-alist | ||
| 57 | ;; '("homepage_rss" | ||
| 58 | ;; :base-directory "~/myhomepage/" | ||
| 59 | ;; :base-extension "org" | ||
| 60 | ;; :rss-image-url "http://lumiere.ens.fr/~guerry/images/faces/15.png" | ||
| 61 | ;; :html-link-home "http://lumiere.ens.fr/~guerry/" | ||
| 62 | ;; :html-link-use-abs-url t | ||
| 63 | ;; :rss-extension "xml" | ||
| 64 | ;; :publishing-directory "/home/guerry/public_html/" | ||
| 65 | ;; :publishing-function (org-rss-publish-to-rss) | ||
| 66 | ;; :section-numbers nil | ||
| 67 | ;; :exclude ".*" ;; To exclude all files... | ||
| 68 | ;; :include ("index.org") ;; ... except index.org. | ||
| 69 | ;; :table-of-contents nil)) | ||
| 70 | ;; | ||
| 71 | ;; ... then rsync /home/guerry/public_html/ with your server. | ||
| 72 | ;; | ||
| 73 | ;; By default, the permalink for a blog entry points to the headline. | ||
| 74 | ;; You can specify a different one by using the :RSS_PERMALINK: | ||
| 75 | ;; property within an entry. | ||
| 76 | |||
| 77 | ;;; Code: | ||
| 78 | |||
| 79 | (require 'ox-html) | ||
| 80 | (declare-function url-encode-url "url-util" (url)) | ||
| 81 | |||
| 82 | ;;; Variables and options | ||
| 83 | |||
| 84 | (defgroup org-export-rss nil | ||
| 85 | "Options specific to RSS export back-end." | ||
| 86 | :tag "Org RSS" | ||
| 87 | :group 'org-export | ||
| 88 | :version "24.4" | ||
| 89 | :package-version '(Org . "8.0")) | ||
| 90 | |||
| 91 | (defcustom org-rss-image-url "https://orgmode.org/img/org-mode-unicorn-logo.png" | ||
| 92 | "The URL of the image for the RSS feed." | ||
| 93 | :group 'org-export-rss | ||
| 94 | :type 'string) | ||
| 95 | |||
| 96 | (defcustom org-rss-extension "xml" | ||
| 97 | "File extension for the RSS 2.0 feed." | ||
| 98 | :group 'org-export-rss | ||
| 99 | :type 'string) | ||
| 100 | |||
| 101 | (defcustom org-rss-categories 'from-tags | ||
| 102 | "Where to extract items category information from. | ||
| 103 | The default is to extract categories from the tags of the | ||
| 104 | headlines. When set to another value, extract the category | ||
| 105 | from the :CATEGORY: property of the entry." | ||
| 106 | :group 'org-export-rss | ||
| 107 | :type '(choice | ||
| 108 | (const :tag "From tags" from-tags) | ||
| 109 | (const :tag "From the category property" from-category))) | ||
| 110 | |||
| 111 | (defcustom org-rss-use-entry-url-as-guid t | ||
| 112 | "Use the URL for the <guid> metatag? | ||
| 113 | When nil, Org will create ids using `org-icalendar-create-uid'." | ||
| 114 | :group 'org-export-rss | ||
| 115 | :type 'boolean) | ||
| 116 | |||
| 117 | ;;; Define backend | ||
| 118 | |||
| 119 | (org-export-define-derived-backend 'rss 'html | ||
| 120 | :menu-entry | ||
| 121 | '(?r "Export to RSS" | ||
| 122 | ((?R "As RSS buffer" | ||
| 123 | (lambda (a s v b) (org-rss-export-as-rss a s v))) | ||
| 124 | (?r "As RSS file" (lambda (a s v b) (org-rss-export-to-rss a s v))) | ||
| 125 | (?o "As RSS file and open" | ||
| 126 | (lambda (a s v b) | ||
| 127 | (if a (org-rss-export-to-rss t s v) | ||
| 128 | (org-open-file (org-rss-export-to-rss nil s v))))))) | ||
| 129 | :options-alist | ||
| 130 | '((:description "DESCRIPTION" nil nil newline) | ||
| 131 | (:keywords "KEYWORDS" nil nil space) | ||
| 132 | (:with-toc nil nil nil) ;; Never include HTML's toc | ||
| 133 | (:rss-extension "RSS_EXTENSION" nil org-rss-extension) | ||
| 134 | (:rss-image-url "RSS_IMAGE_URL" nil org-rss-image-url) | ||
| 135 | (:rss-feed-url "RSS_FEED_URL" nil nil t) | ||
| 136 | (:rss-categories nil nil org-rss-categories)) | ||
| 137 | :filters-alist '((:filter-final-output . org-rss-final-function)) | ||
| 138 | :translate-alist '((headline . org-rss-headline) | ||
| 139 | (comment . (lambda (&rest args) "")) | ||
| 140 | (comment-block . (lambda (&rest args) "")) | ||
| 141 | (timestamp . (lambda (&rest args) "")) | ||
| 142 | (plain-text . org-rss-plain-text) | ||
| 143 | (section . org-rss-section) | ||
| 144 | (template . org-rss-template))) | ||
| 145 | |||
| 146 | ;;; Export functions | ||
| 147 | |||
| 148 | ;;;###autoload | ||
| 149 | (defun org-rss-export-as-rss (&optional async subtreep visible-only) | ||
| 150 | "Export current buffer to an RSS buffer. | ||
| 151 | |||
| 152 | If narrowing is active in the current buffer, only export its | ||
| 153 | narrowed part. | ||
| 154 | |||
| 155 | If a region is active, export that region. | ||
| 156 | |||
| 157 | A non-nil optional argument ASYNC means the process should happen | ||
| 158 | asynchronously. The resulting buffer should be accessible | ||
| 159 | through the `org-export-stack' interface. | ||
| 160 | |||
| 161 | When optional argument SUBTREEP is non-nil, export the sub-tree | ||
| 162 | at point, extracting information from the headline properties | ||
| 163 | first. | ||
| 164 | |||
| 165 | When optional argument VISIBLE-ONLY is non-nil, don't export | ||
| 166 | contents of hidden elements. | ||
| 167 | |||
| 168 | Export is done in a buffer named \"*Org RSS Export*\", which will | ||
| 169 | be displayed when `org-export-show-temporary-export-buffer' is | ||
| 170 | non-nil." | ||
| 171 | (interactive) | ||
| 172 | (let ((file (buffer-file-name (buffer-base-buffer)))) | ||
| 173 | (org-icalendar-create-uid file 'warn-user) | ||
| 174 | (org-rss-add-pubdate-property)) | ||
| 175 | (org-export-to-buffer 'rss "*Org RSS Export*" | ||
| 176 | async subtreep visible-only nil nil (lambda () (text-mode)))) | ||
| 177 | |||
| 178 | ;;;###autoload | ||
| 179 | (defun org-rss-export-to-rss (&optional async subtreep visible-only) | ||
| 180 | "Export current buffer to an RSS file. | ||
| 181 | |||
| 182 | If narrowing is active in the current buffer, only export its | ||
| 183 | narrowed part. | ||
| 184 | |||
| 185 | If a region is active, export that region. | ||
| 186 | |||
| 187 | A non-nil optional argument ASYNC means the process should happen | ||
| 188 | asynchronously. The resulting file should be accessible through | ||
| 189 | the `org-export-stack' interface. | ||
| 190 | |||
| 191 | When optional argument SUBTREEP is non-nil, export the sub-tree | ||
| 192 | at point, extracting information from the headline properties | ||
| 193 | first. | ||
| 194 | |||
| 195 | When optional argument VISIBLE-ONLY is non-nil, don't export | ||
| 196 | contents of hidden elements. | ||
| 197 | |||
| 198 | Return output file's name." | ||
| 199 | (interactive) | ||
| 200 | (let ((file (buffer-file-name (buffer-base-buffer)))) | ||
| 201 | (org-icalendar-create-uid file 'warn-user) | ||
| 202 | (org-rss-add-pubdate-property)) | ||
| 203 | (let ((outfile (org-export-output-file-name | ||
| 204 | (concat "." org-rss-extension) subtreep))) | ||
| 205 | (org-export-to-file 'rss outfile async subtreep visible-only))) | ||
| 206 | |||
| 207 | ;;;###autoload | ||
| 208 | (defun org-rss-publish-to-rss (plist filename pub-dir) | ||
| 209 | "Publish an org file to RSS. | ||
| 210 | |||
| 211 | FILENAME is the filename of the Org file to be published. PLIST | ||
| 212 | is the property list for the given project. PUB-DIR is the | ||
| 213 | publishing directory. | ||
| 214 | |||
| 215 | Return output file name." | ||
| 216 | (let ((bf (get-file-buffer filename))) | ||
| 217 | (if bf | ||
| 218 | (with-current-buffer bf | ||
| 219 | (org-icalendar-create-uid filename 'warn-user) | ||
| 220 | (org-rss-add-pubdate-property) | ||
| 221 | (write-file filename)) | ||
| 222 | (find-file filename) | ||
| 223 | (org-icalendar-create-uid filename 'warn-user) | ||
| 224 | (org-rss-add-pubdate-property) | ||
| 225 | (write-file filename) (kill-buffer))) | ||
| 226 | (org-publish-org-to | ||
| 227 | 'rss filename (concat "." org-rss-extension) plist pub-dir)) | ||
| 228 | |||
| 229 | ;;; Main transcoding functions | ||
| 230 | |||
| 231 | (defun org-rss-headline (headline contents info) | ||
| 232 | "Transcode HEADLINE element into RSS format. | ||
| 233 | CONTENTS is the headline contents. INFO is a plist used as a | ||
| 234 | communication channel." | ||
| 235 | (if (> (org-export-get-relative-level headline info) 1) | ||
| 236 | (org-export-data-with-backend headline 'html info) | ||
| 237 | (unless (org-element-property :footnote-section-p headline) | ||
| 238 | (let* ((email (org-export-data (plist-get info :email) info)) | ||
| 239 | (author (and (plist-get info :with-author) | ||
| 240 | (let ((auth (plist-get info :author))) | ||
| 241 | (and auth (org-export-data auth info))))) | ||
| 242 | (htmlext (plist-get info :html-extension)) | ||
| 243 | (hl-number (org-export-get-headline-number headline info)) | ||
| 244 | (hl-home (file-name-as-directory (plist-get info :html-link-home))) | ||
| 245 | (hl-pdir (plist-get info :publishing-directory)) | ||
| 246 | (hl-perm (org-element-property :RSS_PERMALINK headline)) | ||
| 247 | (anchor | ||
| 248 | (or (org-element-property :CUSTOM_ID headline) | ||
| 249 | (org-export-get-reference headline info))) | ||
| 250 | (category (org-rss-plain-text | ||
| 251 | (or (org-element-property :CATEGORY headline) "") info)) | ||
| 252 | (pubdate0 (org-element-property :PUBDATE headline)) | ||
| 253 | (pubdate (let ((system-time-locale "C")) | ||
| 254 | (if (and pubdate0 (not (string-empty-p pubdate0))) | ||
| 255 | (format-time-string | ||
| 256 | "%a, %d %b %Y %T %z" | ||
| 257 | (org-time-string-to-time pubdate0))))) | ||
| 258 | (title (org-rss-plain-text | ||
| 259 | (or (org-element-property :RSS_TITLE headline) | ||
| 260 | (replace-regexp-in-string | ||
| 261 | org-link-bracket-re | ||
| 262 | (lambda (m) (or (match-string 3 m) | ||
| 263 | (match-string 1 m))) | ||
| 264 | (org-element-property :raw-value headline))) info)) | ||
| 265 | (publink | ||
| 266 | (or (and hl-perm (concat (or hl-home hl-pdir) hl-perm)) | ||
| 267 | (concat | ||
| 268 | (or hl-home hl-pdir) | ||
| 269 | (file-name-nondirectory | ||
| 270 | (file-name-sans-extension | ||
| 271 | (plist-get info :input-file))) "." htmlext "#" anchor))) | ||
| 272 | (guid (if org-rss-use-entry-url-as-guid | ||
| 273 | publink | ||
| 274 | (org-rss-plain-text | ||
| 275 | (or (org-element-property :ID headline) | ||
| 276 | (org-element-property :CUSTOM_ID headline) | ||
| 277 | publink) | ||
| 278 | info)))) | ||
| 279 | (if (not pubdate) "" ;; Skip entries with no PUBDATE prop | ||
| 280 | (format | ||
| 281 | (concat | ||
| 282 | "<item>\n" | ||
| 283 | "<title>%s</title>\n" | ||
| 284 | "<link>%s</link>\n" | ||
| 285 | "<author>%s (%s)</author>\n" | ||
| 286 | "<guid isPermaLink=\"false\">%s</guid>\n" | ||
| 287 | "<pubDate>%s</pubDate>\n" | ||
| 288 | (org-rss-build-categories headline info) "\n" | ||
| 289 | "<description><![CDATA[%s]]></description>\n" | ||
| 290 | "</item>\n") | ||
| 291 | title publink email author guid pubdate contents)))))) | ||
| 292 | |||
| 293 | (defun org-rss-build-categories (headline info) | ||
| 294 | "Build categories for the RSS item from INFO. | ||
| 295 | Fallback to the HEADLINE :CATEGORY property." | ||
| 296 | (if (eq (plist-get info :rss-categories) 'from-tags) | ||
| 297 | (mapconcat | ||
| 298 | (lambda (c) (format "<category><![CDATA[%s]]></category>" c)) | ||
| 299 | (org-element-property :tags headline) | ||
| 300 | "\n") | ||
| 301 | (let ((c (org-element-property :CATEGORY headline))) | ||
| 302 | (format "<category><![CDATA[%s]]></category>" c)))) | ||
| 303 | |||
| 304 | (defun org-rss-template (contents info) | ||
| 305 | "Return complete document string after RSS conversion. | ||
| 306 | CONTENTS is the transcoded contents string. INFO is a plist used | ||
| 307 | as a communication channel." | ||
| 308 | (let ((style (plist-get info :rss-stylesheet))) | ||
| 309 | (concat | ||
| 310 | (format "<?xml version=\"1.0\" encoding=\"%s\"?>" | ||
| 311 | (symbol-name org-html-coding-system)) | ||
| 312 | (if style | ||
| 313 | (format "\n<?xml-stylesheet type=\"text/xsl\" href=\"%s\"?>" | ||
| 314 | style)) | ||
| 315 | "\n<rss version=\"2.0\" | ||
| 316 | xmlns:content=\"http://purl.org/rss/1.0/modules/content/\" | ||
| 317 | xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\" | ||
| 318 | xmlns:dc=\"http://purl.org/dc/elements/1.1/\" | ||
| 319 | xmlns:atom=\"http://www.w3.org/2005/Atom\" | ||
| 320 | xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\" | ||
| 321 | xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\" | ||
| 322 | xmlns:georss=\"http://www.georss.org/georss\" | ||
| 323 | xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\" | ||
| 324 | xmlns:media=\"http://search.yahoo.com/mrss/\">" | ||
| 325 | "<channel>" | ||
| 326 | (org-rss-build-channel-info info) "\n" | ||
| 327 | contents | ||
| 328 | "</channel>\n" | ||
| 329 | "</rss>"))) | ||
| 330 | |||
| 331 | (defun org-rss-build-channel-info (info) | ||
| 332 | "Given plist INFO build the RSS channel information." | ||
| 333 | (let* ((system-time-locale "C") | ||
| 334 | (title (org-export-data (plist-get info :title) info)) | ||
| 335 | (email (org-export-data (plist-get info :email) info)) | ||
| 336 | (author (and (plist-get info :with-author) | ||
| 337 | (let ((auth (plist-get info :author))) | ||
| 338 | (and auth (org-export-data auth info))))) | ||
| 339 | (date (format-time-string "%a, %d %b %Y %T %z")) ;; RFC 882 | ||
| 340 | (description (org-export-data (plist-get info :description) info)) | ||
| 341 | (lang (plist-get info :language)) | ||
| 342 | (keywords (plist-get info :keywords)) | ||
| 343 | (rssext (plist-get info :rss-extension)) | ||
| 344 | (blogurl (or (plist-get info :html-link-home) | ||
| 345 | (plist-get info :publishing-directory))) | ||
| 346 | (image (url-encode-url (plist-get info :rss-image-url))) | ||
| 347 | (ifile (plist-get info :input-file)) | ||
| 348 | (publink | ||
| 349 | (or (plist-get info :rss-feed-url) | ||
| 350 | (concat (file-name-as-directory blogurl) | ||
| 351 | (file-name-nondirectory | ||
| 352 | (file-name-sans-extension ifile)) | ||
| 353 | "." rssext)))) | ||
| 354 | (format | ||
| 355 | "\n<title>%s</title> | ||
| 356 | <atom:link href=\"%s\" rel=\"self\" type=\"application/rss+xml\" /> | ||
| 357 | <link>%s</link> | ||
| 358 | <description><![CDATA[%s]]></description> | ||
| 359 | <language>%s</language> | ||
| 360 | <pubDate>%s</pubDate> | ||
| 361 | <lastBuildDate>%s</lastBuildDate> | ||
| 362 | <generator>%s</generator> | ||
| 363 | <webMaster>%s (%s)</webMaster> | ||
| 364 | <image> | ||
| 365 | <url>%s</url> | ||
| 366 | <title>%s</title> | ||
| 367 | <link>%s</link> | ||
| 368 | </image> | ||
| 369 | " | ||
| 370 | title publink blogurl description lang date date | ||
| 371 | (concat (format "Emacs %d.%d" | ||
| 372 | emacs-major-version | ||
| 373 | emacs-minor-version) | ||
| 374 | " Org-mode " (org-version)) | ||
| 375 | email author image title blogurl))) | ||
| 376 | |||
| 377 | (defun org-rss-section (section contents info) | ||
| 378 | "Transcode SECTION element into RSS format. | ||
| 379 | CONTENTS is the section contents. INFO is a plist used as | ||
| 380 | a communication channel." | ||
| 381 | contents) | ||
| 382 | |||
| 383 | (defun org-rss-timestamp (timestamp contents info) | ||
| 384 | "Transcode a TIMESTAMP object from Org to RSS. | ||
| 385 | CONTENTS is nil. INFO is a plist holding contextual | ||
| 386 | information." | ||
| 387 | (org-html-encode-plain-text | ||
| 388 | (org-timestamp-translate timestamp))) | ||
| 389 | |||
| 390 | (defun org-rss-plain-text (contents info) | ||
| 391 | "Convert plain text CONTENTS into RSS encoded text. | ||
| 392 | INFO is a plist used as a communication channel" | ||
| 393 | (let (output) | ||
| 394 | (setq output (org-html-encode-plain-text contents) | ||
| 395 | output (org-export-activate-smart-quotes | ||
| 396 | output :html info)))) | ||
| 397 | |||
| 398 | ;;; Filters | ||
| 399 | |||
| 400 | (defun org-rss-final-function (contents backend info) | ||
| 401 | "Prettify the RSS output. | ||
| 402 | CONTENTS is the headline contents as a transcoded string. BACKEND | ||
| 403 | is a symbol representation of the backend used. INFO is a plist | ||
| 404 | used as a communication channel." | ||
| 405 | (with-temp-buffer | ||
| 406 | (xml-mode) | ||
| 407 | (insert contents) | ||
| 408 | (indent-region (point-min) (point-max)) | ||
| 409 | (buffer-substring-no-properties (point-min) (point-max)))) | ||
| 410 | |||
| 411 | ;;; Miscellaneous | ||
| 412 | |||
| 413 | (defun org-rss-add-pubdate-property () | ||
| 414 | "Set the PUBDATE property for top-level headlines." | ||
| 415 | (let (msg) | ||
| 416 | (org-map-entries | ||
| 417 | (lambda () | ||
| 418 | (let* ((entry (org-element-at-point)) | ||
| 419 | (level (org-element-property :level entry))) | ||
| 420 | (when (= level 1) | ||
| 421 | (unless (org-entry-get (point) "PUBDATE") | ||
| 422 | (setq msg t) | ||
| 423 | (org-set-property | ||
| 424 | "PUBDATE" (format-time-string | ||
| 425 | (cdr org-time-stamp-formats))))))) | ||
| 426 | nil nil 'comment 'archive) | ||
| 427 | (when msg | ||
| 428 | (message "Property PUBDATE added to top-level entries in %s" | ||
| 429 | (buffer-file-name)) | ||
| 430 | (sit-for 2)))) | ||
| 431 | |||
| 432 | (provide 'ox-rss) | ||
| 433 | |||
| 434 | ;;; ox-rss.el ends here | ||
elisp/publish.el added +58
| @@ -0,0 +1,58 @@ | |||
| 1 | ;; Publish org files to HTML | ||
| 2 | |||
| 3 | ;; Functions | ||
| 4 | (defun org-rss-publish-to-rss (plist filename pub-dir) | ||
| 5 | "Publish RSS with PLIST, only when FILENAME is 'rss.org'. | ||
| 6 | PUB-DIR is when the output will be placed." | ||
| 7 | (if (equal "rss.org" (file-name-nondirectory filename)) | ||
| 8 | (org-rss-export-to-rss plist filename pub-dir))) | ||
| 9 | |||
| 10 | ;; Project publishing settings | ||
| 11 | (setq org-publish-project-alist | ||
| 12 | '(("cleberg.net" | ||
| 13 | :base-directory "~/Source/cleberg.net/" | ||
| 14 | :publishing-function org-html-publish-to-html | ||
| 15 | :publishing-directory "~/Source/cleberg.net/public/" | ||
| 16 | :auto-sitemap t | ||
| 17 | :recursive t | ||
| 18 | :section-numbers nil | ||
| 19 | :with-author nil | ||
| 20 | :html-validation-link nil | ||
| 21 | :with-tags t | ||
| 22 | :html-head-include-default-style nil | ||
| 23 | :html-head-include-scripts nil | ||
| 24 | :html-head "<link rel=stylesheet href=/static/styles.css.min>" | ||
| 25 | :html-preamble "<nav><a href=/>Home</a><a href=/blog/>Blog</a><a href=/services/>Services</a><a href=/wiki/>Wiki</a></nav>") | ||
| 26 | |||
| 27 | ("rss" | ||
| 28 | :base-directory "~/Source/cleberg.net/blog/" | ||
| 29 | :base-extension "org" | ||
| 30 | :html-link-home "https://cleberg.net/" | ||
| 31 | :html-link-use-abs-url t | ||
| 32 | :rss-extension "xml" | ||
| 33 | :publishing-directory "~/Source/cleberg.net/public/blog/" | ||
| 34 | :publishing-function org-rss-publish-to-rss | ||
| 35 | :section-numbers nil | ||
| 36 | :exclude "index.org" | ||
| 37 | :author "cmc" | ||
| 38 | :email "" | ||
| 39 | ;; test | ||
| 40 | :html-link-org-files-as-html t | ||
| 41 | :auto-sitemap t | ||
| 42 | :sitemap-filename "rss.org" | ||
| 43 | :sitemap-title "cleberg.net" | ||
| 44 | :sitemap-style list | ||
| 45 | :sitemap-sort-files anti-chronologically | ||
| 46 | ;;:sitemap-function 'rw/format-rss-feed | ||
| 47 | ;;:sitemap-format-entry 'rw/format-rss-feed-entry | ||
| 48 | ;; end test | ||
| 49 | ) | ||
| 50 | |||
| 51 | ("static" | ||
| 52 | :base-directory "~/Source/cleberg.net/static/" | ||
| 53 | :base-extension "css\\|el" | ||
| 54 | :publishing-directory "~/Source/cleberg.net/public/static/" | ||
| 55 | :publishing-function org-publish-attachment) | ||
| 56 | ("website" :components ("cleberg.net" "rss" "static")))) | ||
| 57 | |||
| 58 | (provide 'publish) | ||