Compare commits

...

No commits in common. "9bf6a6b78a370a54c1b1a460332cd5cf656e7c21" and "56090c4c65938178c797a7b13877c9810a07ca14" have entirely different histories.

1 changed files with 0 additions and 264 deletions

264
mfblog.el
View File

@ -1,264 +0,0 @@
;;; mfblog.el --- Microformats2 compatible notes site generator
;; Copyright (C) 2016 Free Software Foundation, Inc.
;; Author: Ryan Rix <ryan@whatthefuck.computer>
;; Version: 0.1
;; Package-Requires: ((json "0.1") (org "8.0"))
;; Keywords: web
;; URL: http://notes.whatthefuck.computer/
;;; Commentary:
;; This package generates a small blog from a single org-mode file, leveraging Microformats to
;; provide semantic information about the posts; you can use this information to automate sharing,
;; linkbacks, embedding images in 3rd party silso, and more; see http://indiewebcamp.com and
;; http://microformats.org for more information.
;; This package can be used by configuring the various variables and then calling [`mfblog:gen']
;; which will publish the blog index, an RSS feed and URLs for each entry. You can then have Brid.gy
;; automatically syndicate the content to silos by calling [`mfblog:syndicate-entry-at-point'].
;;; Code:
(require 'org-attach)
(require 'ox-html)
(require 'htmlize)
(require 'url-http)
(require 'url)
(require 'json)
(defgroup mfblog nil
"Microformats/IndieWeb blog.")
(defcustom mfblog:template-file "/home/rrix/Projects/notes/template.html"
"Template file for mfblog to use.
You should provide your own, but feel free to base it on the one in the package."
:group 'mfblog)
(defvar mfblog:postlist '())
(defcustom mfblog:preamble
"<p> This page is short notes, things I've read, and not full
length posts; long-form is posted on <a
href=\"http://whatthefuck.computer/\">my main site</a> and linked
to from here, as sort of a self-hosted broadcast-only
Twitter. This site uses semantic markup to automatically
syndicate to social networks (<a
href=\"http://indiewebcamp.com/POSSE\">POSSE</a>-style). Comments
and feedback are handled via <a
href=\"http://indiewebcamp.com/webmention\">webmention</a>.
Subscribe via <a
href=\"http://notes.whatthefuck.computer/index.xml\">RSS</a>.</p>"
"A preamble to post at the end of each page."
:group 'mfblog)
(defcustom mfblog:publish-config '(
:rss-image-url "http://notes.whatthefuck.computer/~rrix/25ZLKRlf.jpg"
:html-link-home "http://notes.whatthefuck.computer"
:html-link-use-abs-url t
:rss-extension "xml"
:select-tags ("EXPORT")
:publishing-directory "/ssh:li01.rix.si:/home/rrix/public_html/notes/"
:table-of-contents nil
:section-numbers nil)
"An `org-publish-project-alist' format plist containing shared state between all of the temporary publish projects."
:group 'mfblog)
(defun mfblog:gen ()
"Generate the mfblog and publish it."
(interactive)
(setq mfblog:postlist nil)
(message "Generating notes files")
(with-current-buffer (find-file-noselect "~/Projects/notes/index.org")
(goto-char (point-min))
(org-sort-entries nil ?T)
;; (org-map-entries 'mfblog:index-posts "EXPORT" 'file)
(org-map-entries 'mfblog:entry-to-page "EXPORT" 'file))
(let ((org-publish-project-alist
(list (append '("notes_rss")
(mfblog:plist-merge '(:base-directory "~/Projects/notes" :base-extension "org" :publishing-function (org-rss-publish-to-rss) :exclude ".*" :include ("index.org"))
mfblog:publish-config))
(append '("notes_other")
(mfblog:plist-merge '(:base-directory "/var/tmp/mfblog" :base-extension "JPG\\|js\\|html\\|jpg\\|gif\\|png" :publishing-function (org-publish-attachment))
mfblog:publish-config)))))
(copy-file "~/Projects/notes/webmention.js" "/var/tmp/mfblog/webmention.js" t)
(copy-file "~/Projects/notes/go.png" "/var/tmp/mfblog/go.png" t)
(copy-file "~/Projects/notes/favicon.gif" "/var/tmp/mfblog/favicon.gif" t)
(org-publish "notes_rss")
(mfblog:make-index)
(org-publish "notes_other")))
(defun mfblog:syndicate-entry-at-point ()
"Syndicate the org-mode entry at point, by calling out to Bridgy and storing the result."
(interactive)
(let* ((date (org-entry-get (point) "CLOSED"))
(date (org-time-string-to-seconds date))
(base-url (plist-get mfblog:publish-config :html-link-home))
(url (format "%s/%s-note.html" base-url date))
(syn-twitter (org-entry-get (point) "SYN-TWITTER"))
(syn-facebook (org-entry-get (point) "SYN-FACEBOOK"))
(realpoint (point)))
(unless syn-twitter
(let* ((url-request-data (format "source=%s&target=http://brid.gy/publish/twitter" url))
(url-request-method "POST")
(buf (url-retrieve-synchronously "https://brid.gy/publish/webmention")))
(org-entry-put realpoint "SYN-TWITTER"
(with-current-buffer buf
(goto-char url-http-end-of-headers)
(let* ((body (json-read))
(url (assoc 'url body)))
(when url
(cdr url)))))))
(unless syn-facebook
(let* ((url-request-data (format "source=%s&target=http://brid.gy/publish/facebook" url))
(url-request-method "POST")
(buf (url-retrieve-synchronously "https://brid.gy/publish/webmention")))
(org-entry-put realpoint "SYN-FACEBOOK"
(with-current-buffer buf
(goto-char url-http-end-of-headers)
(let* ((body (json-read))
(url (assoc 'url body)))
(when url
(cdr url)))))))))
(defun mfblog:heading-to-html (heading)
"HTMLize the given HEADING, cleaning up crap and generating in-reply-to URLs."
(with-temp-buffer
(insert heading)
(let* ((str (htmlize-region-for-paste (point-min) (point-max))))
(with-temp-buffer
(insert str)
(goto-char (point-min))
(replace-regexp "<pre>" "")
(goto-char (point-min))
(replace-regexp "</pre>" "")
(goto-char (point-min))
(replace-regexp "<a href=\"https://twitter" "<a class=\"u-in-reply-to\" href=\"https://twitter")
(buffer-string)))))
(defun mfblog:to-html ()
"Convert the heading at point to HTML, sprinkling in ID where necessary."
(let* ((id (org-id-get-create))
(location (first (org-property-values "LOCATION")))
(attach-dir (org-attach-dir))
(file-list (if attach-dir
(org-attach-file-list attach-dir)
'())))
(with-current-buffer (org-html-export-as-html nil t nil t)
(dolist (file file-list)
(let ((file- (concat attach-dir "/" file))
(newfile (concat "/var/tmp/mfblog/" id "-" file))
)
(unless (file-exists-p newfile)
(copy-file file- newfile)
(set-file-modes newfile 420))
(insert "<img style=\"width: 100%\" src=\"" id "-" file "\" class=\"u-photo\"/><br/>")))
(when location
(insert "<span class=\"p-location\">" location "</span>"))
(buffer-string))))
(defun mfblog:entry-to-page ()
"Convert the heading at POINT to an HTML page"
(save-window-excursion
(unless (file-exists-p "/var/tmp/mfblog")
(make-directory "/var/tmp/mfblog"))
(let* ((pubdate (org-entry-get (point) "CLOSED"))
(pubdate (org-time-string-to-seconds pubdate))
(id (org-id-get-create))
(filename (format "%s-note.html" pubdate))
(fullpath (format "/var/tmp/mfblog/%s" filename))
(title (mfblog:heading-to-html (org-get-heading)))
(content (mfblog:to-html))
(base-url (plist-get mfblog:publish-config :html-link-home))
(full-url (concat base-url "/" filename))
(syn-twitter-url (or (org-entry-get (point) "SYN-TWITTER") ""))
(syn-facebook-url (or (org-entry-get (point) "SYN-FACEBOOK") ""))
(syn-twitter-href (if (> (length syn-twitter-url) 0)
(format "<a rel=\"syndication\" href=\"%s\">On Twitter</a>" syn-twitter-url)
""))
(syn-facebook-href (if (> (length syn-facebook-url) 0)
(format "<a rel=\"syndication\" href=\"%s\">On Facebook</a>" syn-facebook-url)
"")))
(org-entry-put (point) "RSS_PERMALINK" filename)
(with-current-buffer (find-file-noselect fullpath)
(erase-buffer)
(insert-file mfblog:template-file)
(goto-char (point-min))
(replace-regexp "{{content}}" content)
(goto-char (point-min))
(replace-regexp "{{title}}" title)
(goto-char (point-min))
(replace-regexp "{{url}}" full-url)
(goto-char (point-min))
(replace-regexp "<a href=\"{{twitter}}\">On Twitter</a>" syn-twitter-href)
(goto-char (point-min))
(replace-regexp "<a href=\"{{facebook}}\">On Facebook</a>" syn-facebook-href)
(write-file fullpath)
(kill-buffer (current-buffer))
(add-to-ordered-list 'mfblog:postlist
(list pubdate fullpath title content filename)
pubdate)))))
(defun mfblog:index-posts ()
"Create an index of all the posts to speed up generation of index.html"
(save-window-excursion
(let* ((pubdate (org-entry-get (point) "CLOSED"))
(pubdate (org-time-string-to-seconds pubdate))
(id (org-id-get-create))
(filename (format "%s-note.html" pubdate))
(fullpath (format "/var/tmp/mfblog/%s" filename)))
(unless (alist-get pubdate 'mfblog:postlist)
(let* ((title-html (mfblog:heading-to-html (org-get-heading)))
(title-txt (mfblog:heading-to-txt (org-get-heading)))
(base-url (plist-get mfblog:publish-config :html-link-home))
(full-url (concat base-url "/" filename)))
(add-to-ordered-list 'mfblog:postlist
(list fullpath title-html title-text filename full-url)
pubdate))))))
(defun mfblog:plist-merge (&rest plists)
"Merge a bunch of PLISTS together."
(if plists
(let ((result (copy-sequence (car plists))))
(while (setq plists (cdr plists))
(let ((plist (car plists)))
(while plist
(setq result (plist-put result (car plist) (car (cdr plist)))
plist (cdr (cdr plist))))))
result)
nil))
(defun mfblog:make-index ()
"Generate the mfblog index page."
(let* ((index-path "/var/tmp/mfblog/index.html")
(all-content
(mapconcat
(lambda (post)
(let ((pubdate (pop post))
(fullpath (pop post))
(title (pop post))
(content (pop post))
(filename (pop post)))
(format "<li style=\"text-size: 0.8em;\">%s (<a href=\"/%s\">Permalink</a>)</li>" title filename)))
(reverse mfblog:postlist) "\n"))
(all-content (format "%s<ul>%s</ul>" mfblog:preamble all-content)))
(with-current-buffer (find-file-noselect "/var/tmp/mfblog/index.html")
(erase-buffer)
(insert-file mfblog:template-file)
(goto-char (point-min))
(replace-regexp "{{content}}" all-content)
(goto-char (point-min))
(replace-regexp "{{url}}" (concat (plist-get mfblog:publish-config :html-link-home) "/"))
(goto-char (point-min))
(replace-regexp "{{twitter}}" "https://twitter.com/rrrrrrrix")
(goto-char (point-min))
(replace-regexp "{{facebook}}" "https://facebook.com/rjrix")
(goto-char (point-min))
(replace-regexp "{{title}}" "Ryan's Shortnotes")
(write-file "/var/tmp/mfblog/index.html"))))
(provide 'mfblog)
;;; mfblog.el ends here