From 83173362387d03da93ddbbad61bacc6aa4355f05 Mon Sep 17 00:00:00 2001 From: James Richardson Date: Sun, 15 Mar 2020 22:13:36 -0400 Subject: [PATCH] Post about blogging with org. --- .gitignore | 1 + blog/blog.org | 5 + blog/entry/blog-with-only-orgmode.org | 172 ++++++++++++++++++++++++++++++++ blog/header.html | 13 +++ css/main.css | 15 +++ css/org.css | 180 ++++++++++++++++++++++++++++++++++ pages/about.org | 12 +++ pages/header.html | 13 +++ pages/index.org | 6 +- 9 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 blog/blog.org create mode 100644 blog/entry/blog-with-only-orgmode.org create mode 100644 blog/header.html create mode 100644 css/main.css create mode 100644 css/org.css create mode 100644 pages/about.org create mode 100644 pages/header.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/blog/blog.org b/blog/blog.org new file mode 100644 index 0000000..f8d60f8 --- /dev/null +++ b/blog/blog.org @@ -0,0 +1,5 @@ +#+TITLE: Blog articles + +- [[file:theindex.org][Index]] +- entry + - [[file:entry/blog-with-only-orgmode.org][blog-with-only-orgmode]] \ No newline at end of file diff --git a/blog/entry/blog-with-only-orgmode.org b/blog/entry/blog-with-only-orgmode.org new file mode 100644 index 0000000..9f29024 --- /dev/null +++ b/blog/entry/blog-with-only-orgmode.org @@ -0,0 +1,172 @@ +#+options: title:nil num:t + +#+TITLE: Blog With Only Orgmode +#+DATE: <2020-03-15 Sun> + +This blog is now being written with [[https://orgmode.org/][org-mode]] and [[https://www.gnu.org/software/emacs][Emacs]]. I have been +threatening to do so for a while now. I have previously used [[https://ikiwiki.info][ikiwiki]], +which is also a static site generator. I have switched to org-mode, +mainly because I like org markup better than [[https://en.wikipedia.org/wiki/Markdown][markdown]]. I write most +everything else in org-mode; the context switch, I think, kept me from +writing.[fn:1] + +* Blog files setup +As I have decided that all I need is the [[https://orgmode.org/manual/Publishing.html][publishing features of +org-mode]], I had to structure the sources for the blog smartly. I think +I have come up with a structure that can be maintained and grokked +by ~(org-publish)~ without requiring too much additional [[https://en.wikipedia.org/wiki/Emacs_Lisp][Emacs Lisp]]. + +Another thing I am changing is not publishing directly from a +=git hook=. Not publishing directly from a =git hook= allows easier +writing across several computers. I have ~(org-publish)~ write to +=~/public_html/jamestechnotes.com= for local testing. + +This is my setup, from which I borrowed heavily from [[https://ogbe.net/blog/blogging_with_org.html][Dennis Ogbe's +writeup]]: ++ All of my websites are beneath ~~/src/wikis~. This one is beneath + ~/src/wikis/jamestechnotes.com~. If you happen to be really + interested in the layout, all of the source is [[https://git.jamestechnotes.com/?p=jamestechnotes.com.git;a=summary][published]].[fn:2] ++ The elisp that glues all of this together is in my [[https://git.jamestechnotes.com/?p=james/home/home-etc.git;a=blob;f=.emacs.d/config/org.el;h=bb3385aaf086305e389ae6b7251f4f735589dedc;hb=HEAD][emacs config]]; + relevant sections will be detailed below. ++ The blog files split into the following structure: + - =/pages/= --- Static pages, like the [[https://jamestechnotes.com][home page]], live here as org + files. + - =/css/= --- css files live here. + - =/blog/entry/= --- individual blog posts live here. + - =/img/= -- (Not yet implemented) images would live here. +** How does this help? +Hopefully, =/css/= and =/img/= are rather clear. They hold, well, css +files and images. The images bother me. As images are binary +artifacts, they are rather awkward[fn:3] to check into git. I suspect +if I start accumulating large images, I will look into using some like +[[https://git-annex.branchable.com][git annex]] to manage them. + +Static pages, which don't change often, live out of the way beneath +=/pages/=. There is a separate publishing project just for these. + +Individual blog entries live in their own org file in +=/blog/entry/=. If I actually start writing many post and the +directory get unwieldy, I will have to hash the entries, probably by +year. This section also has it's own publishing project, that also +generates a sitemap index. Elisp will be developed to coerce this +sitemap into a proper blog index. + +I have an elisp function, =jr/prepare-pages=, which looks for a file +named =header.html= in the =base-directory= of the project. The +function is called when ~(org-publish)~ generates the preamble of each +page. I use this machinery to build the top navigation menu on the +pages. + +A benefit of this layout, to which I did not pay attention, is the top +directory of the web site contains no content that is +publishable. Adding a todo.org file here will allow me to add [[https://www.orgmode.org/manual/TODO-Items.html][org todo +items]] with ideas for future blog post and have them show up in my +[[https://orgmode.org/manual/Agenda-Views.html][Agenda]]. I could also add actual todo headline in actual blog posts and +mark them =noexport= so they won't publish. + +* Show me the code +While ~(org-publish)~ already does a lot out of the box, a bit of help +is need to achieve the desired layout. First, links to stylesheets +need to be added to the == of the document. The variable +~jr/html-head~ contains text which is inserted in the document. +#+BEGIN_SRC emacs-lisp + (setq jr/html-head + (concat + "\n" ;; start with org.css + "")) +#+END_SRC +=org.css= was copied from an exported html buffer. =main.css= contains +custom layouts which will override the defaults from =org.css= and +required. + +The =jr/prepare-pages= function mentioned earlier the inserts +=header.html= into the preamble is listed here: +#+BEGIN_SRC emacs-lisp + (defun jr/prepare-pages (plist) + (message "In the prepare pages.") + (message (plist-get plist :base-directory)) + (let ((header (concat + (file-name-as-directory + (plist-get plist :base-directory)) + "header.html"))) + (message header) + (when (file-exists-p header) + (with-temp-buffer + (insert-file-contents header) + (buffer-string))))) +#+END_SRC + +Now comes the publishing project: +#+BEGIN_SRC emacs-lisp + (setq org-publish-project-alist + `(("jamestechnotes-com" :components ("jamestechnotes-com-css" + "jamestechnotes-com-entries" + "jamestechnotes-com-pages")) + ("jamestechnotes-com-css" + :base-directory "~/src/wikis/jamestechnotes.com/css" + :publishing-directory "~/public_html/jamestechnotes.com/css" + :base-extension "css" + :publishing-function org-publish-attachment) + ("jamestechnotes-com-entries" + :base-directory "~/src/wikis/jamestechnotes.com/blog" + :publishing-directory "~/public_html/jamestechnotes.com/blog" + :recursive t + :publishing-function org-html-publish-to-html + :preparation-function jr/prepare-pages + :htmlized-source t + :with-toc nil + :section-numbers nil + :html-doctype "xhtml5" + :html-html5-fancy t + :html-head-include-default-style nil + :html-head-include-scripts nil + :html-head ,jr/html-head + :html-preamble jr/prepare-pages + + :auto-sitemap t + :sitemap-filename "blog.org" + :sitemap-title "Blog articles" + :sitemap-sort-files anti-chronologically + + :makeindex t) + ("jamestechnotes-com-pages" + :base-directory "~/src/wikis/jamestechnotes.com/pages" + :publishing-directory "~/public_html/jamestechnotes.com" + :publishing-function org-html-publish-to-html + :preparation-function jr/prepare-pages + :htmlized-source t + :with-toc nil + :section-numbers nil + :html-doctype "xhtml5" + :html-html5-fancy t + :html-head-include-default-style nil + :html-head-include-scripts nil + :html-head ,jr/html-head + :html-preamble jr/prepare-pages + + :auto-sitemap t + :sitemap-filename "blog.org" + :sitemap-title "Blog articles" + :sitemap-sort-files anti-chronologically + + :makeindex t))) +#+END_SRC +The interesting thing to note here is the use of quasiquote ~`~, +which allows use of unquote ~,~ for ~:html-head~. ~:html-head~ +requires a string, not a variable containing a string. The ~unquote~ +and ~quasiquote~ allows this to function. + +* TODO adfadf :noexport: +afdafdafsfas + + +* Footnotes + +[fn:3] Git handles binary artifacts reasonably well. I just think such +shouldn't be done in general. + +[fn:2] All of the code I write (that isn't owned by others) lives in +[[https://git.jamestechnotes.com][my git repositories]], including source for my websites. + +[fn:1]Well, at least that my excuse. ;) + diff --git a/blog/header.html b/blog/header.html new file mode 100644 index 0000000..bac06d5 --- /dev/null +++ b/blog/header.html @@ -0,0 +1,13 @@ +
+ +
diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..682ad20 --- /dev/null +++ b/css/main.css @@ -0,0 +1,15 @@ +/* Layout myname */ +#myname {text-decoration: none; font-size: 200%; font-weight:bold; color: black;} + +/* Add space a bottom of #preamble, and center text */ +#preamble {margin-bottom: 30px; text-align: center;} + +/* header layout */ +.banner nav {font-size: 115%; font-weight: bolder; } +.banner nav a {color: blue; text-decoration: none; height: 30px;} +.banner p {word-spacing: .5em; margin: 0;} + +/* set content width, so it will center. */ +#content {width: 80%; margin-left: auto; margin-right: auto;} +/* hide this for now */ +#postamble {display: none;} diff --git a/css/org.css b/css/org.css new file mode 100644 index 0000000..b0cf6b2 --- /dev/null +++ b/css/org.css @@ -0,0 +1,180 @@ +.title { text-align: center; + margin-bottom: .2em; } +.subtitle { text-align: center; + font-size: medium; + font-weight: bold; + margin-top:0; } +.todo { font-family: monospace; color: red; } +.done { font-family: monospace; color: green; } +.priority { font-family: monospace; color: orange; } +.tag { background-color: #eee; font-family: monospace; + padding: 2px; font-size: 80%; font-weight: normal; } +.timestamp { color: #bebebe; } +.timestamp-kwd { color: #5f9ea0; } +.org-right { margin-left: auto; margin-right: 0px; text-align: right; } +.org-left { margin-left: 0px; margin-right: auto; text-align: left; } +.org-center { margin-left: auto; margin-right: auto; text-align: center; } +.underline { text-decoration: underline; } +#postamble p { font-size: 90%; margin: .2em; } +p.verse { margin-left: 3%; } +pre { + border: 1px solid #ccc; + box-shadow: 3px 3px 3px #eee; + padding: 8pt; + font-family: monospace; + overflow: auto; + margin: 1.2em; +} +pre.src { + position: relative; + overflow: visible; + padding-top: 1.2em; +} +pre.src:before { + display: none; + position: absolute; + background-color: white; + top: -10px; + right: 10px; + padding: 3px; + border: 1px solid black; +} +pre.src:hover:before { display: inline;} +/* Languages per Org manual */ +pre.src-asymptote:before { content: 'Asymptote'; } +pre.src-awk:before { content: 'Awk'; } +pre.src-C:before { content: 'C'; } +/* pre.src-C++ doesn't work in CSS */ +pre.src-clojure:before { content: 'Clojure'; } +pre.src-css:before { content: 'CSS'; } +pre.src-D:before { content: 'D'; } +pre.src-ditaa:before { content: 'ditaa'; } +pre.src-dot:before { content: 'Graphviz'; } +pre.src-calc:before { content: 'Emacs Calc'; } +pre.src-emacs-lisp:before { content: 'Emacs Lisp'; } +pre.src-fortran:before { content: 'Fortran'; } +pre.src-gnuplot:before { content: 'gnuplot'; } +pre.src-haskell:before { content: 'Haskell'; } +pre.src-hledger:before { content: 'hledger'; } +pre.src-java:before { content: 'Java'; } +pre.src-js:before { content: 'Javascript'; } +pre.src-latex:before { content: 'LaTeX'; } +pre.src-ledger:before { content: 'Ledger'; } +pre.src-lisp:before { content: 'Lisp'; } +pre.src-lilypond:before { content: 'Lilypond'; } +pre.src-lua:before { content: 'Lua'; } +pre.src-matlab:before { content: 'MATLAB'; } +pre.src-mscgen:before { content: 'Mscgen'; } +pre.src-ocaml:before { content: 'Objective Caml'; } +pre.src-octave:before { content: 'Octave'; } +pre.src-org:before { content: 'Org mode'; } +pre.src-oz:before { content: 'OZ'; } +pre.src-plantuml:before { content: 'Plantuml'; } +pre.src-processing:before { content: 'Processing.js'; } +pre.src-python:before { content: 'Python'; } +pre.src-R:before { content: 'R'; } +pre.src-ruby:before { content: 'Ruby'; } +pre.src-sass:before { content: 'Sass'; } +pre.src-scheme:before { content: 'Scheme'; } +pre.src-screen:before { content: 'Gnu Screen'; } +pre.src-sed:before { content: 'Sed'; } +pre.src-sh:before { content: 'shell'; } +pre.src-sql:before { content: 'SQL'; } +pre.src-sqlite:before { content: 'SQLite'; } +/* additional languages in org.el's org-babel-load-languages alist */ +pre.src-forth:before { content: 'Forth'; } +pre.src-io:before { content: 'IO'; } +pre.src-J:before { content: 'J'; } +pre.src-makefile:before { content: 'Makefile'; } +pre.src-maxima:before { content: 'Maxima'; } +pre.src-perl:before { content: 'Perl'; } +pre.src-picolisp:before { content: 'Pico Lisp'; } +pre.src-scala:before { content: 'Scala'; } +pre.src-shell:before { content: 'Shell Script'; } +pre.src-ebnf2ps:before { content: 'ebfn2ps'; } +/* additional language identifiers per "defun org-babel-execute" + in ob-*.el */ +pre.src-cpp:before { content: 'C++'; } +pre.src-abc:before { content: 'ABC'; } +pre.src-coq:before { content: 'Coq'; } +pre.src-groovy:before { content: 'Groovy'; } +/* additional language identifiers from org-babel-shell-names in + ob-shell.el: ob-shell is the only babel language using a lambda to put + the execution function name together. */ +pre.src-bash:before { content: 'bash'; } +pre.src-csh:before { content: 'csh'; } +pre.src-ash:before { content: 'ash'; } +pre.src-dash:before { content: 'dash'; } +pre.src-ksh:before { content: 'ksh'; } +pre.src-mksh:before { content: 'mksh'; } +pre.src-posh:before { content: 'posh'; } +/* Additional Emacs modes also supported by the LaTeX listings package */ +pre.src-ada:before { content: 'Ada'; } +pre.src-asm:before { content: 'Assembler'; } +pre.src-caml:before { content: 'Caml'; } +pre.src-delphi:before { content: 'Delphi'; } +pre.src-html:before { content: 'HTML'; } +pre.src-idl:before { content: 'IDL'; } +pre.src-mercury:before { content: 'Mercury'; } +pre.src-metapost:before { content: 'MetaPost'; } +pre.src-modula-2:before { content: 'Modula-2'; } +pre.src-pascal:before { content: 'Pascal'; } +pre.src-ps:before { content: 'PostScript'; } +pre.src-prolog:before { content: 'Prolog'; } +pre.src-simula:before { content: 'Simula'; } +pre.src-tcl:before { content: 'tcl'; } +pre.src-tex:before { content: 'TeX'; } +pre.src-plain-tex:before { content: 'Plain TeX'; } +pre.src-verilog:before { content: 'Verilog'; } +pre.src-vhdl:before { content: 'VHDL'; } +pre.src-xml:before { content: 'XML'; } +pre.src-nxml:before { content: 'XML'; } +/* add a generic configuration mode; LaTeX export needs an additional + (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */ +pre.src-conf:before { content: 'Configuration File'; } + +table { border-collapse:collapse; } +caption.t-above { caption-side: top; } +caption.t-bottom { caption-side: bottom; } +td, th { vertical-align:top; } +th.org-right { text-align: center; } +th.org-left { text-align: center; } +th.org-center { text-align: center; } +td.org-right { text-align: right; } +td.org-left { text-align: left; } +td.org-center { text-align: center; } +dt { font-weight: bold; } +.footpara { display: inline; } +.footdef { margin-bottom: 1em; } +.figure { padding: 1em; } +.figure p { text-align: center; } +.equation-container { + display: table; + text-align: center; + width: 100%; +} +.equation { + vertical-align: middle; +} +.equation-label { + display: table-cell; + text-align: right; + vertical-align: middle; +} +.inlinetask { + padding: 10px; + border: 2px solid gray; + margin: 10px; + background: #ffffcc; +} +#org-div-home-and-up + { text-align: right; font-size: 70%; white-space: nowrap; } +textarea { overflow-x: auto; } +.linenr { font-size: smaller } +.code-highlighted { background-color: #ffff00; } +.org-info-js_info-navigation { border-style: none; } +#org-info-js_console-label + { font-size: 10px; font-weight: bold; white-space: nowrap; } +.org-info-js_search-highlight + { background-color: #ffff00; color: #000000; font-weight: bold; } +.org-svg { width: 90%; } diff --git a/pages/about.org b/pages/about.org new file mode 100644 index 0000000..425d8cb --- /dev/null +++ b/pages/about.org @@ -0,0 +1,12 @@ +#+TITLE: About - James Richardson's Engineering Notebook +#+AUTHOR: James Richardson +#+EMAIL: j@mesrichardson.com +#+DATE: +#+STARTUP: showall +#+STARTUP: inlineimages + +#+options: title:nil + +Nothing here yet. + +See [[https://jamestechnotes.com/blog/blog.html][blog posts]] or [[https://jamesrichardson.name][my personal site]]. diff --git a/pages/header.html b/pages/header.html new file mode 100644 index 0000000..bac06d5 --- /dev/null +++ b/pages/header.html @@ -0,0 +1,13 @@ +
+ +
diff --git a/pages/index.org b/pages/index.org index 19ed55a..af72d62 100644 --- a/pages/index.org +++ b/pages/index.org @@ -7,7 +7,11 @@ #+options: title:nil -* this is a test page +Welcome! + +[[https://jamestechnotes.com/blog/blog.html][Here]] is my technical blog. I also have a [[https://jamesrichardson.name][personal]] site. + + -- 2.11.4.GIT