org-howto/env/publish-static-html.org
2024-03-06 18:25:13 -05:00

292 lines
10 KiB
Org Mode

#+title: publishing static HTML
# org-publish options
# ^:{} require a_{b} before assuming that b should be subscripted.
# without this option a_b will automatically subscript b.
#+options: ^:{}
#
# emacs-specific options
#+startup: showall
#
# html exporter options
#+setupfile: ../ext/fniessen/theme-readtheorg.setup
#+language: en
# +infojs_opt: view:showall mouse:#ffc0c0 toc:nil ltoc:nil path:/web/ext/orginfo/org-info.js
# +html_head: <link rel="stylesheet" type="text/css" href="/web/css/primary.css" />
#+html_link_home: /web/index.html
#+html_link_up: /web/env/development-environment.html
* Publish Static HTML
In particular, including this content.
Content formatted using ~org-mode~.
Maintaining public ~.org~ content here: [[https://github.com/Rconybea/org-howto]]
** base emacs configuration for publishing
See also
[[https://orgmode.org/worg/org-tutorials/org-publish-html-tutorial.html]]
~org-publish-project-alist~ configures org trees for publishing:
#+begin_src elisp
;; ----------------------------------------------------------------
;; org-mode publishing
;;
(require 'ox-publish)
;; publishing setup -- this is a kitchen sink -- it's intended to cover
;; everything we want org-mode to publish
;;
(setq org-publish-project-alist
'(
("org-howto"
:components ("org-howto-notes" "org-howto-static"))
("org-howto-notes"
:base-directory "~/proj/org-howto"
:base-extension "org"
:publishing-directory "~/proj/public_html/org-howto"
:recursive t
:publishing-function org-html-publish-to-html
:headling-levels 4
:auto-preamble t
)
("org-howto-static"
:base-directory "~/proj/org-howto"
:base-extension "css\\|html\\|js\\|svg\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
:publishing-directory "~/proj/public_html/org-howto"
:recursive t
:publishing-function org-publish-attachment
)
)
; ... additional org trees here ...
)
#+end_src
With this configuration
#+begin_example
~M-x org-publish-project org-howto~
#+end_example
generates HTML content in =~/proj/public_html/org-howto~=.
** setup for literate programming
~org-mode~ can automate weaving together content prepared by other programs,
for example ~graphviz~.
=~/.emacs= Configuration for such adopted sources (as of 1oct2023 just graphviz):
#+begin_src elisp
;; ----------------------------------------------------------------
;; org-mode babel setup
;; (execute dot/ditaa/bash/c++ etc. from .org code blocks)
;;
;; see
;; [[https://orgmode.org/worg/org-contrib/babel/intro.html]]
;; [[https://orgmode.org/worg/org-contrib/babel/languages/index.html]]
;;
;; code block:
;; #+begin_src ${language} ${switches} ${headerarguments}
;; ${body}
;; #+end_src
;;
;; use header argument
;; :results output
;; to insert code-block output (i.e. contents of stdout) into .org file below code block
;;
;; use
;; :results value
;; to just take value of last statement
;;
;; use
;; :session
;; to share language sub-process across code-blocks.
;;
;; can use
;; #+name: foo
;; to name an org-mode table; then:
;; #+begin_src ... :var myfreevar=foo
;; ...
;; #+end_src
;; with body mentioning myfreevar; .org will substitute foo
;;
;; can do inline coode block with
;; src_<${lang}>{${code}} or src_<${lang}[${args}]{${code}}
;; e.g.
;; src_python[:session]{10*x}
;;
;; notes:
;; [C-c C-v] org-babel prefix
;; [C-c C-v b] -- evaluate code blocks in buffer
;; [C-c C-v s] -- evaluate code blocks in subtree
;; [C-c C-v e] -- evaluate code block at point
;; [C-c '] M-x org-edit-src-code -- puts code block in new buffer with appropriate mode activated
;; [C-c M-b p] M-x org-babel-expand-src-block -- show expanded code block prior to evaluation
;; (org-babel-lob-ingest "path/to/file.org") to share code blogs as 'library'
(org-babel-do-load-languages
'org-babel-load-languages
'((ditaa . t) ; ditaa
(dot . t) ; graphviz [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-dot.html]] see also graphviz-dot-mode
))
#+end_src
Example ~.org~ content using graphviz:
#+begin_example
,#+begin_src dot :file img/living-room-av/macmini.svg :exports results :cmdline -Tsvg
digraph {
size="4,4";
rankdir=LR;
s [label="mac mini", shape="box"];
r [label="receiver", shape="box"];
m [label="monitor", shape="box"];
sp [label="spkr", shape="ellipse"];
s -> r[label="VDP",color="red"];
s -> m[label="input#2",color="blue"];
r -> sp[color="red"];
}
,#+end_src
#+end_example
publishing (or using =C-c C-v b=) creates/updates file in =img/living-room-av/macmini.svg=
** HTML theme
Using Fabrice Niessen's awesome readtheorg theme see [[https://github.com/fniessen/org-html-themes][org-html-themes]]
Cloned ~.setup~ file to ~org-howto/ext/fniessen/theme-readtheorg.setup~.
Apply theme by including the following in each ~.org~ header:
#+begin_src org
# options used exclusively by the html exporter
#+setupfile: ext/fniessen/theme-readtheorg.setup
#+end_src
** display HTML locally
Once we have HTML in =~/proj/public_html/org-howto=, can view it locally:
#+begin_src sh
python3 -m http.server --directory ~/proj/public_html/org-howto 8080
#+end_src
then point browser to =localhost:8080= (or for the content you're reading now: =localhost:8080/env/development-environment.html=)
Caveat: builtin python webserver doesn't support https.
** publish to github pages
To work with github pages, We tweak the ~.org~ tree slightly:
#+begin_src sh
cd ~/proj/org-howto
ln -s ext web
#+end_src
This is to match the github repo name [[https://github.com/Rconybea/web]].
When we publish ~.org~ tree to github pages, it appears at [[https://rconybea.github.io/web]]
~.org~ pages that want to use root-relative paths, prefix with =/web=:
#+begin_example
,#+infojs_opt: view:showall toc:nil ltoc:nil mouse:#ffc0c0 path:/web/ext/orginfo/org-info.js
,#+html_head: <link rel="stylesheet" type="text/css" href="/web/css/notebook.css" />
#+end_example
1. github pages: =/web/ext/orginfo/org-info.js= resolves via =ext/orginfo/org-info.js=..
2. natively hosted: =/web/ext/orginfo/org-info.js= resolves via =web/ext/orginfo-org-info.js=.
Note that =org-publish= expands the =web= symlink, so everything under the =ext= tree will be duplicated
** package as docker container
We can snapshot and serve generated html in a dedicated docker container with this =flake.nix=
(in =~/proj/public_html=, given html output written to =~/proj/public_html/org-howto=)
#+begin_src nix
{
description = "publish org-howto-derived html";
# dependencies of this flake
inputs = rec {
nixpkgs.url = "github:nixos/nixpkgs/23.05";
org_howto_path = {
url = "./org-howto";
flake = false;
};
};
outputs = { self, nixpkgs, org_howto_path } :
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
# creates shell script 'serve-org-howto'.
# to use:
# $ cd ~/proj/public_html
# A.
# $ nix build
# $ ./result/bin/serve-org-howto
# B.
# $ nix run
#
serve_org_howto_deriv = pkgs.writeShellScriptBin "serve-org-howto" ''
${pkgs.python3}/bin/python3 -m http.server 8080 --directory ${org_howto_path}
'';
# builds custom docker image!
serve_org_howto_docker_deriv =
let
serve_org_howto = self.packages.${system}.serve_org_howto;
in
pkgs.dockerTools.buildLayeredImage {
name = serve_org_howto.name;
tag = "1.0";
contents = [ serve_org_howto ];
config = {
Cmd = [ "/bin/serve-org-howto" ];
WorkingDir = "/";
};
};
in rec {
packages.${system} = {
default = serve_org_howto_deriv;
serve_org_howto = serve_org_howto_deriv;
serve_org_howto_docker = serve_org_howto_docker_deriv;
};
};
}
#+end_src
1. build docker container image using =~/proj/public_html/flake.nix=:
#+begin_example
$ cd ~/proj/public_html
$ nix build
$ ls -ld result
/nix/store/dck2rix8n8sx6wi0d4is0fq17c72ddqx-serve-org-howto.tar.gz
#+end_example
2. load image into docker
#+begin_example
$ docker load <./result
#+end_example
or send to some other host:
#+begin_example
$ mycloudhost=...
$ scp /nix/store/dck2rix8n8sx6wi0d4is0fq17c72ddqx-serve-org-howto.tar.gz root@${mycloudhost}
$ ssh ${mycloudhost}
mycloudhost$ docker load < /nix/store/dck2rix8n8sx6wi0d4is0fq17c72ddqx-serve-org-howto.tar.gz
mycloudhost$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
serve-org-howto 1.0 113e8c1232fa 53 years ago 165MB
mycloudhost$ docker run serve-org-howto
#+end_example
HTML tree now served from =${mycloudhost}:8080=
Docker image contains only python and our html tree, so much smaller than typical image.