publishing static HTML
Table of Contents
1. Publish Static HTML
In particular, including this content.
Content formatted using org-mode
.
Maintaining public .org
content here: https://github.com/Rconybea/org-howto
1.1. 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:
;; ---------------------------------------------------------------- ;; 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 ... )
With this configuration
~M-x org-publish-project org-howto~
generates HTML content in ~/proj/public_html/org-howto~
.
1.2. 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):
;; ---------------------------------------------------------------- ;; 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 ))
Example .org
content using graphviz:
#+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
publishing (or using C-c C-v b
) creates/updates file in img/living-room-av/macmini.svg
1.3. HTML theme
Using Fabrice Niessen's awesome readtheorg theme see org-html-themes
Cloned .setup
file to org-howto/ext/fniessen/theme-readtheorg.setup
.
Apply theme by including the following in each .org
header:
# options used exclusively by the html exporter #+setupfile: ext/fniessen/theme-readtheorg.setup
1.4. display HTML locally
Once we have HTML in ~/proj/public_html/org-howto
, can view it locally:
python3 -m http.server --directory ~/proj/public_html/org-howto 8080
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.
1.5. publish to github pages
To work with github pages, We tweak the .org
tree slightly:
cd ~/proj/org-howto
ln -s ext web
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
:
#+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" />
- github pages:
/web/ext/orginfo/org-info.js
resolves viaext/orginfo/org-info.js
.. - natively hosted:
/web/ext/orginfo/org-info.js
resolves viaweb/ext/orginfo-org-info.js
.
Note that org-publish
expands the web
symlink, so everything under the ext
tree will be duplicated
1.6. 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
)
{ 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; }; }; }
build docker container image using
~/proj/public_html/flake.nix
:$ cd ~/proj/public_html $ nix build $ ls -ld result /nix/store/dck2rix8n8sx6wi0d4is0fq17c72ddqx-serve-org-howto.tar.gz
load image into docker
$ docker load <./result
or send to some other host:
$ 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
HTML tree now served from
${mycloudhost}:8080
Docker image contains only python and our html tree, so much smaller than typical image.