Updated the auto-load script

This commit is contained in:
Yann Esposito (Yogsototh) 2019-07-25 11:10:50 +02:00
parent 0c93cc602a
commit d789212b87
Signed by untrusted user who does not match committer: yogsototh
GPG Key ID: 7B19A4C650D59646
3 changed files with 95 additions and 231 deletions

View File

@ -1,204 +0,0 @@
(require 'org)
(require 'ox-publish)
(require 'ox-html)
(require 'org-element)
(require 'ox-rss)
(setq org-link-file-path-type 'relative)
(defun org-blog-prepare (project-plist)
"With help from `https://github.com/howardabrams/dot-files'.
Touch `index.org' to rebuilt it.
Argument `PROJECT-PLIST' contains information about the current project."
(let* ((base-directory (plist-get project-plist :base-directory))
(buffer (find-file-noselect (expand-file-name "index.org" base-directory) t)))
(with-current-buffer buffer
(set-buffer-modified-p t)
(save-buffer 0))))
(defvar org-blog-head
(concat
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/css/minimalist.css\"/>"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<link rel=\"alternative\" type=\"application/rss+xml\" title=\"Subscribe to articles\" href=\"/archives.xml\" />"
"<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/favicon.ico\">"))
(defun menu (lst)
"Blog menu"
(concat
"<navigation class=\"menu\">"
(mapconcat 'identity
(append
'("<a href=\"/index.html\">Home</a>"
"<a href=\"/archive.html\">Posts</a>")
lst)
" | ")
"</navigation>"))
(defun str-time-to-year-float (date-str)
(/ (float-time
(apply 'encode-time
(mapcar (lambda (x) (if (null x) 0 x))
(parse-time-string date-str))))
(* 365.25 24 60 60)))
(defvar blog-creation-date "2019-07-01")
(defun y-date (date-str)
"Number of year since the begining of this blog"
(let ((y (- (str-time-to-year-float date-str)
(str-time-to-year-float blog-creation-date))))
(format "∆t=%.2f" y)))
(defun org-blog-preamble (info)
"Pre-amble for whole blog."
(concat
"<div class=\"content\">"
(menu '("<a href=\"#postamble\">↓ bottom ↓</a>"))
"<h1>"
(format "%s" (car (plist-get info :title)))
(when-let ((date (get-from-info info :date)))
(format " - <span class=\"article-date\">%s</span>" date))
"</h1>"
"</div>"))
(defun get-from-info (info k)
(let ((i (car (plist-get info k))))
(when (and i (stringp i))
i)))
(defun rand-obfs (c)
(let ((r (% (random) 20)))
(cond ((eq 0 r) (format "%c" c))
((< 0 r 10) (format "&#%d;" c))
(t (format "&#x%X;" c)))))
(defun obfuscate-html (txt)
(apply 'concat
(mapcar 'rand-obfs txt)))
(defun org-blog-postamble (info)
"Post-amble for whole blog."
(concat
"<div class=\"content\">"
"<footer>"
(when-let ((author (get-from-info info :author)))
(if-let ((email (plist-get info :email)))
(format "<div class=\"author\">Author: <a href=\"%s%s\">%s</a></div>"
(obfuscate-html "mailto:")
(obfuscate-html email)
(obfuscate-html author))
(format "<div class=\"author\">Author: %s</div>" author)))
(when-let ((date (get-from-info info :date)))
(format "<div class=\"date\">Created: %s (%s)</div>" date (y-date date)))
(when-let ((keywords (plist-get info :keywords)))
(format "<div class=\"keywords\">Keywords: <code>%s</code></div>" keywords))
(format "<div class=\"date\">Generated: %s</div>"
(format-time-string "%Y-%m-%d %H:%M:%S"))
(format (concat "<div class=\"creator\"> Generated with "
"<a href=\"https://www.gnu.org/software/emacs/\" target=\"_blank\" rel=\"noopener noreferrer\">Emacs %s</a>, "
"<a href=\"http://spacemacs.org\" target=\"_blank\" rel=\"noopener noreferrer\">Spacemacs %s</a>, "
"<a href=\"http://orgmode.org\" target=\"_blank\" rel=\"noopener noreferrer\">Org Mode %s</a>"
"</div>")
emacs-version spacemacs-version org-version)
"</footer>"
(menu '("<a href=\"#preamble\">↑ Top ↑</a>"))
"</div>"))
(defun org-blog-sitemap-format-entry (entry _style project)
"Return string for each ENTRY in PROJECT."
(when (s-starts-with-p "posts/" entry)
(format "@@html:<span class=\"archive-item\"><span class=\"archive-date\">@@ %s: @@html:</span>@@ [[file:%s][%s]] @@html:</span>@@"
(format-time-string "%Y-%m-%d"
(org-publish-find-date entry project))
entry
(org-publish-find-title entry project))))
(defun org-blog-sitemap-function (title list)
"Return sitemap using TITLE and LIST returned by `org-blog-sitemap-format-entry'."
(concat "#+TITLE: " title "\n"
"#+AUTHOR: Yann Esposito\n"
"#+EMAIL: yann.esposito@gmail.com\n"
"\n#+begin_archive\n"
(mapconcat (lambda (li)
(format "@@html:<li>@@ %s @@html:</li>@@" (car li)))
(seq-filter #'car (cdr list))
"\n")
"\n#+end_archive\n"))
(setq base-dir (concat (projectile-project-root) "src"))
(setq publish-dir (concat (projectile-project-root) "_site"))
(setq assets-dir (concat base-dir "/assets"))
(setq publish-assets-dir (concat publish-dir "/assets"))
(setq rss-dir base-dir)
(setq publish-rss-dir publish-dir)
(setq domainname "https://her.esy.fun")
(setq org-publish-project-alist
`(("orgfiles"
:base-directory ,base-dir
:exclude ".*drafts/.*"
:base-extension "org"
:publishing-directory ,publish-dir
:recursive t
:preparation-function org-blog-prepare
:publishing-function org-html-publish-to-html
:with-toc nil
:with-title nil
:with-date t
:section-numbers nil
:html-doctype "html5"
:html-html5-fancy t
:html-head-include-default-style nil
:html-head-include-scripts nil
:htmlized-source t
:html-head-extra ,org-blog-head
:html-preamble org-blog-preamble
:html-postamble org-blog-postamble
:auto-sitemap t
:sitemap-filename "archive.org"
:sitemap-title "Blog Posts"
:sitemap-style list
:sitemap-sort-files anti-chronologically
:sitemap-format-entry org-blog-sitemap-format-entry
:sitemap-function org-blog-sitemap-function)
("assets"
:base-directory ,assets-dir
:base-extension ".*"
:publishing-directory ,publish-assets-dir
:publishing-function org-publish-attachment
:recursive t)
("rss"
:base-directory ,rss-dir
:base-extension "org"
:html-link-home ,domainname
:html-link-use-abs-url t
:rss-extension "xml"
:publishing-directory ,publish-rss-dir
:publishing-function (org-rss-publish-to-rss)
:exclude ".*"
:include ("archive.org")
:section-numbers nil
:table-of-contents nil)
("blog" :components ("orgfiles" "assets" "rss"))))
;; add target=_blank and rel="noopener noreferrer" to all links by default
(defun my-org-export-add-target-blank-to-http-links (text backend info)
"Add target=\"_blank\" to external links."
(when (and
(org-export-derived-backend-p backend 'html)
(string-match "href=\"http[^\"]+" text)
(not (string-match "target=\"" text))
(not (string-match (concat "href=\"" domainname "[^\"]*") text)))
(string-match "<a " text)
(replace-match "<a target=\"_blank\" rel=\"noopener noreferrer\" " nil nil text)))
(add-to-list 'org-export-filter-link-functions
'my-org-export-add-target-blank-to-http-links)

BIN
.project.el.gpg Normal file

Binary file not shown.

View File

@ -68,9 +68,10 @@ You can add a task quite easily while doing other work in emacs.
:CUSTOM_ID: basic-blog-a1fc
:END:
I put the need minimal code in a =.project.el= file of my blog repository.
I used the solution given [[https://francismurillo.github.io/2017-02-15-Project-Script-Loader/][here]] (see direct link to the code snippet) to eval the
content of that file each time I enter into this project.
I put the need minimal code in a =.project.el.gpg= file of my blog repository.
Inspired by this [[https://francismurillo.github.io/2017-02-15-Project-Script-Loader/][blog post]] I enhanced this version to be both more user friendly
and secure (see [[#digression]]).
But even before that, I simply put the code in has an elisp code block of my
=index.org= that I exectued with =C-c C-c=.
@ -180,30 +181,6 @@ images, etc...)
("blog" :components ("orgfiles" "assets"))))
#+end_src
#+begin_src elisp
(setq base-dir (concat (projectile-project-root) "src"))
(setq publish-dir (concat (projectile-project-root) "_site"))
(setq assets-dir (concat base-dir "/assets"))
(setq publish-assets-dir (concat publish-dir "/assets"))
(setq org-publish-project-alist
`(("orgfiles"
:base-directory ,base-dir
:exclude ".*drafts/.*"
:base-extension "org"
:publishing-directory ,publish-dir
:recursive t)
("assets"
:base-directory ,assets-dir
:base-extension ".*"
:publishing-directory ,publish-assets-dir
:publishing-function org-publish-attachment
:recursive t)
("blog" :components ("orgfiles" "assets"))))
#+end_src
With that you will copy the assets and export org file to html.
You can do both by selecting `blog` when doing an `org-publish`.
@ -422,3 +399,94 @@ That's better. But for a blog you also generally want to have your own CSS.
'my-org-export-add-target-blank-to-http-links)
#+end_src
* Digression
:PROPERTIES:
:CUSTOM_ID: digression
:END:
Auto loading a =.el= file when entering in a project.
It should be easy and safe.
The best solution I found.
Save your =.el= file as a =.el.gpg= file.
With =epa= emacs should encrypt the file for you using your own private key.
Great! Now we simply verify the file exists and load it only if it is encrypted
with one of you /trusted keys/.
The list of key fingerprint you trust is a configuration.
When opening a new file via projectile or dired
1. check the =.project.el.gpg= file is not already loaded for the current project
2. check the =.project.el.gpg= file exists
3. check the =.project.el.gpg= file is encrypted with a trusted key
4. decrypt and load =.project.el.gpg=
That's it.
You simply need to set the =y/trusted-gpg-key-fingerprints= variable with the
list of your own fingerprint.
You can get a list of them with =gpg --list-secret-keys=.
Now you can be happy, this is really safe, in the sense that if you clone a new
project from the internet with a =.project.el.gpg= file in it.
That file won't be run on your system.
Of course if you want to share that =.el= to other people, you need to adapt.
But for my use case, this is perfect.
#+begin_src elisp
(defvar y/trusted-gpg-key-fingerprints
'("448E9FEF4F5B86DE79C1669B7B19A4C650D59646")
"The list of GPG fingerprint you trust when decrypting a gpg file.
You can retrieve the fingerprints of your own private keys with:
`gpg --list-secret-keys' (take care of removing the spaces when copy/pasting here)")
(defun y/get-encryption-key (file)
"given a gpg encrypted file, returns the fingerprint of they
key that encrypted it"
(string-trim-right
(shell-command-to-string
(concat
"gpg --status-fd 1 --decrypt -o /dev/null " file " 2>/dev/null"
"|grep DECRYPTION_KEY"
"|awk '{print $4}'"))))
(defun y/trusted-gpg-origin-p (file)
"Returns true if the file is encrypted with a trusted key"
(member (y/get-encryption-key file) y/trusted-gpg-key-fingerprints))
(defun y/project-el-auto-load ()
(with-eval-after-load 'projectile
(defconst y/project-file ".project.el.gpg"
"Filename looked after to be loaded and evaluated.")
(defvar y/loaded-projects (list)
"Projects that have been loaded by `y/load-project-file'.")
(defun y/load-project-file ()
"Loads the `y/project-file' for a project. This is run
once after the project is loaded signifying project setup."
(interactive)
(when (projectile-project-p)
(lexical-let* ((project-root (projectile-project-root))
(project-init-file (expand-file-name y/project-file project-root)))
(when (and (not (member project-root y/loaded-projects)) ;; project file not already loaded
(file-exists-p project-init-file) ;; project file exists
(y/trusted-gpg-origin-p project-init-file)) ;; project file is tursted
(message "Loading project init file for %s" (projectile-project-name))
(condition-case ex
(progn (load project-init-file)
(add-to-list 'y/loaded-projects project-root)
(message "%s loaded successfully" project-init-file))
('error
(message
"There was an error loading %s: %s"
project-init-file
(error-message-string ex))))))))
;; for some obscure reason there is not really a working hook
;; to be used with projectile to launch the `y/load-project-file'
;; only when switching to a new project.
;; Thus the `y/loaded-projects' state.
(add-hook 'find-file-hook #'y/load-project-file t)
(add-hook 'dired-mode-hook #'y/load-project-file t)))
#+end_src