This package generates pretty, responsive, websites from .org files and your choice of Emacs themes. You can optionally specify a header, footer, and additional CSS and JS to be included. To see the default output, for my chosen themes and with no header, footer or extras, view this README in your browser here. If you’re already there, you can find the GitHub repo here.
With the README I also publish these samples, which include a list-specified header and footer:
nice-org-html defines an Emacs pipeline for exporting Org files, or publishing Org projects, to HTML. The generated HTML is optimized for readability and responsiveness, esp. of documents that include code, and makes it easy to achieve a custom look-and-feel, in part by leveraging the variety of themes available for Emacs. Under the hood, this is achieved by:
- Extracting colors from user-specified themes, inserting these in a CSS template (nice-org-html.css), and injecting the result into a <style>element.
- Inserting toggle-buttons for light- and dark-mode viewing, and a click-to-jump table-of-content view, governed by the included scripts (nice-org-html.js).
- Extending the default org-to-html export backend to include copy-to-clipboard buttons for source blocks.
- Injecting (optional) header and footer, CSS styling, and JS scripts.
- Get the source files on your load path. E.g. with MELPA and use-package:
    (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (package-initialize) (unless (package-installed-p 'use-package) (package-install 'use-package)) 
- Add something like this to your configuration file:
    (use-package nice-org-html :hook (org-mode . nice-org-html-mode) :config (setq nice-org-html-theme-alist '((light . solo-jazz) (dark . tomorrow-night-eighties))) (setq nice-org-html-default-mode 'dark) (setq nice-org-html-headline-bullets nil) 
- If values for any of these variables are not specified, these defaults will be used:
    - Themes: tsdh-lightandtsdh-darkdistributed with GNU Emacs
- Default viewing mode: 'query- This will check against the visitor’s browser-set preference, and default to 'darkif no preference is specified. Anti-fingerprinting settings may prevent reading the browser setting, or cause the browser to mask it (usually, by showing a preference for'light).
 
- This will check against the visitor’s browser-set preference, and default to 
- Headline bullets: 'nil– i.e. bullets will not be prefixed to headlines- To prefix headlines with the default bullets, instead use:
            (setq nice-org-html-headline-bullets t) 
- Or you can specify headline bullets with a plist like this (the defaults):
            (setq nice-org-html-headline-bullets '(:h1 "◉" :h2 "✸" :h3 "▷" :h4 "⦁" :h5 "○")) 
 
- To prefix headlines with the default bullets, instead use:
            
 
- Themes: 
- Further look-and-feel customization is handled through the nice-org-html-optionsplist. The following properties and values are supported (so far):Property Value Effect :layout “compact” Header and footer links always contained in drawer :layout “expanded” Header and footer links never contained in drawer :collapsing t Clicking headlines collapses / expands sections :src-lang t Source language displayed in header of source blocks 
- After loading this package and hooking nice-org-html-mode to org-mode, when you open an Org buffer, nice-org-html-mode will activate.
- If you then interactively export your Org buffer via the dispatcher (C-c C-e), you will be presented with options to export to ‘nice HTML’, in addition to the basic HTML export options.
- When exporting to ‘nice HTML’, you will be prompted for (all optional) options plist, header and footer, and CSS and JS filepaths. If specified, the contents of those variables will be injected, accordingly, into the generated HTML.
    - CSS and JS must be paths (strings) to files with contents to be injected.
- Header and footer may be a path to an HTML file, or a list of cons pairs.
- A default HTML structure will be used for the header and/or footer, if a list of this form:
        '(("left" . uri0) ("link1" . "uri1") ... ("linkN" . "uriN")) - leftwill be displayed as anchor text, and hyperlinked if- uri0is non-nil.
- link1…- linkNwill be hyperlinks, collapsed into a drawer for mobile viewers.
 
 
- These variables may also be set globally, and then used or overridden during interactive export. For example:
    (setq nice-org-html-header '(("title" . "/home.html") ("foo" . "/foo.html") ("bar" . "/bar.html"))) ;; Or: (setq nice-org-html-header "path/to/your/header.html") (setq nice-org-html-footer '(("© author" . "mailto:a@b.c") ("oof" . "https://oof.a") ("rab" . "https://rab.b"))) ;; Or: (setq nice-org-html-header "path/to/your/footer.html") (setq nice-org-html-css "path/to/your/style.css") (setq nice-org-html-js "path/to/your/script.js") (setq nice-org-html-options '(:layout "compact" :collapsing t)) 
- This package is particularly well-suited to publishing Org projects, as websites comprised of many linked pages. The included publishing function, nice-org-html-publish-to-html, relies on global values for all of the above variables. To use it, in specifying the value oforg-publish-projects-alist, for a given project just specify:;; ... :publishing-function #'nice-org-html-publish-to-html ;; ... 
- For more granular per-project configuration, there is a publishing-function-generating macro, nice-org-html-publishing-function, which takes values for the above configuration variables, and defines a publishing function unique to that invocation. Note: the options plist is constructed out of remaining arguments to this macro, so options should be specified directly. For example, your per-project configuration - i.e. the value oforg-publish-projects-alist- may look something like this:`(("project-x/files" :base-extension "org" :base-directory "path/to/source-x/" :publishing-directory "path/to/target-x/" ;; ... :publishing-function ,(nice-org-html-publishing-function :theme-alist ((light . spacemacs-light) (dark . spacemacs-dark)) :default-mode dark :headline-bullets (:h1 "" :h2 "✸" :h3 "▷" :h4 "" :h5 "") :header "path/to/your/header.html" :footer "path/to/your/footer.html" :css "path/to/your/style.css" :js "path/to/your/script.js" :layout "compact" :collapsing t))) - Any variable for which values are not specified will take the global (or default) value.
 
- Finally, there is a less ergonomic alternative macro, nice-org-html-make-publishing-function, which takes values for all of the above configuration variables as direct arguments, rather than properties. The function defined by this macro does not validate its arguments, and the macro is primarily for use in contexts where invocations need to be constructed programmatically, with lexically bound variables spliced in. For most uses,nice-org-html-publishing-functionshould be preferred over the “-make-” alternative.
- Important: for downloaded themes, you must run M-x load-themeonce, at some point, before exporting or publishing, so that Emacs “recognizes” the theme as safe to load. Failure to do so may brick an Emacs instance, requiring a restart.
- You can specify ""as the bullet for a headline level to omit bullets for that level.
- The HTML specified by nice-org-html-headerandnice-org-html-footerwill inherit the package default styling, unless further styling for these is defined in the file specified bynice-org-html-css.
- For easy CSS customization, the contents of each user-specified HTML file are wrapped together in a <div>element; with id = ‘injected-header’ and id = ‘injected-footer’, respectively, and both with class = ‘injected’.
- The CSS specified by nice-org-html-cssmay also use the CSS variables defined in nice-org-html.css, which ultimately refer to Emacs face attribute values determined by your chosen themes.
- The CSS specified by nice-org-html-cssmay override the default styling.
- If you find a bug and want it fixed, please raise an issue.
- If you would like to add or refine something feel free to:
    - Fork the repo
- Clone your fork and develop / use it
- Create a pull request – I’ll probably approve it
 
- Note: there are so many themes for Emacs, that it’s tough to make them all render nicely with a uniform mapping of face-attributes to CSS variables. But fear not! If you find that this package doesn’t “play nice” with your preferred theme, there is a built-in mechanism for re-mapping variables on a per-theme basis, precisely to handle these outliers. Just raise an issue, or take a look at the CSS specific to ‘leuven’ themes and create a PR with something similar.
- All of the theme developers, without which this package would be useless.
- Shi Tianshu’s org-html-themify provided the basic model for CSS interpolation.
- Various stackoverflow posts were of great help, but alas, I’ve lost the links.