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) | |