Skip to content
This repository has been archived by the owner on Jul 2, 2023. It is now read-only.

Latest commit

 

History

History
332 lines (256 loc) · 10.2 KB

liaison.org

File metadata and controls

332 lines (256 loc) · 10.2 KB

Liaison

This manual is a reference guide for Liaison {{{version}}}, first released on {{{release-date}}}.

Copying

Copyright (C) 2022 Aziz Ben Ali.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.

Installation

Find and navigate to your desired project, and run the following in a shell prompt:

git clone https://github.com/grtcdr/liaison.git

Likewise, you may choose to add it as a submodule:

git submodule add https://github.com/grtcdr/liaison.git

It is assumed that you have a publishing script which this manual has chosen to name publish.el; within this file, you should define the project specification as well as any other configuration variables or special functions that affect the output of the published website.

It is best that you initiate the publishing process using a Makefile.

In your publishing script, add the package to the load-path and then require it like so:

(add-to-list 'load-path "liaison")
(require 'liaison)

If you’re interested in a more elaborate but less tedious method for installing this package, you should read my article on Implementing per-project package management for ox-publish.el projects.

Integration

This section outlines the different steps needed to integrate this package into your website, it assumes that you have already created a publishing script.

In the previous section you were told to import liaison, but you’ll also need to import ox-publish and any other libraries you depend on, in your publishing script.

(require 'ox-publish)

Using macros

This example registers a new blob macro which will receive the URL to the blob page of the currently visited document.

(setq org-export-global-macros
      '(("blob" . "(eval (liaison-get-resource-url 'blob))")))

We can now call the blob macro in an Org document and it will expand to the string we assigned to it.

#+TITLE: Example

* Heading

To view this document in its raw format, follow this link: {{{blob}}}.

In the preamble/postamble

In your publishing script, you will want to redefine the org-html-format-spec function such as to extend it with your custom format strings.

If you intend to use any other format strings, such as the preset %a or %e, don’t forget to add them, otherwise they won’t be expanded.

(defun org-html-format-spec (info)
  "Return format specification for preamble and postamble."
  `((?b . ,(liaison-get-resource-url 'blob))
    (?m . ,(liaison-get-resource-url 'blame))
    (?t . ,(liaison-get-resource-url 'tree))
    (?l . ,(liaison-get-resource-url 'log))
    (?p . ,(liaison-get-resource-url 'plain))
    (?e . ,(liaison-get-resource-url 'edit))))

This next step involves preparing your project structure to support the use of HTML templates; snippets which will be added onto our Org documents. These templates can reference at any point any of the format strings defined in the org-html-format-spec function.

The following is an example of such a template:

<nav>
  <a href="%e"><button>Edit</button></a>
  <a href="%m"><button>Blame</button></a>
  <a href="%b"><button>Blob</button></a>
  <a href="%t"><button>Tree</button></a>
  <a href="%l"><button>Log</button></a>
  <a href="%p"><button>Plain</button></a>
</nav>

During the export phase, Org will locate the format strings, and interpolate them using the return value of their associated function.

We’ll now need a way to access the contents of these HTML files from our publishing script - to achieve that, you could use something like this:

(defun read-template (filename)
  "Read contents of FILENAME from the templates directory."
    (with-temp-buffer
      (insert-file-contents
       (file-name-concat "templates" filename))
      (buffer-string)))

We will use read-template along with the :html-preamble property to inject a preamble into the files of a particular project component.

(setq org-publish-project-alist
      (let ((preamble (read-template "preamble.html")))
	(list
	 (list "articles"
	       :base-extension "org"
	       :base-directory "articles"
	       :publishing-directory "public/articles"
	       :publishing-function 'org-html-publish-to-html
	       :html-preamble preamble
	       :html-postamble nil)
	 (list "all"
	       :components "articles"))))

Your website is now properly configured to use Liaison.

Publishing your website

The publishing script should be loaded before the org-publish-project function is called, this translates to the following command:

emacs --quick --batch \
      --load publish.el \
      --funcall org-publish-all t t

Custom instances

Liaison by default doesn’t recognize domains beside the presets, so you’ll have to specify the domain of your forge and its associated resource URL builder.

Now, suppose you’re a member of freedesktop.org, your wonderful projects are present in the GitLab instance provided by your organization.

To add support for your infrastructure, you need to customize the liaison-forge-alist variable, here’s an example:

(defvar liaison-forge-alist
  '(("gitlab.freedesktop.org" . #'liaison--build-gitlab-resource-url)))

Edge cases

Handling sitemaps

In some cases, you may find yourself using Liaison’s functions in a publishing project with the :auto-sitemap option set to t.

Provided you are relying upon a templating system like the one proposed in this document, you will notice that when you visit the sitemap (e.g. https://example.com/blog/sitemap.html) in a web browser, the document will contain the same preamble/postamble as the files which it is indexing.

To get around this, you should use set the :sitemap-function option. Here’s an example in which we hide the postamble from appearing in the sitemap:

(defun my/blog-sitemap-function (title list)
  "Custom site map function for the blog project."
  (concat "#+OPTIONS: html-postamble:nil\n"
	  (org-publish-sitemap-default title list)))

Here’s another example which references a setupfile:

(defun my/blog-sitemap-function (title list)
  "Custom site map function for the blog project."
  (concat "#+SETUPFILE: setup.org\n"
	  (org-publish-sitemap-default title list)))

By now you will have noticed that the strings we’re concatenating to the default sitemap function, i.e. org-publish-sitemap-default, follow the same syntax as any Org document.

The result of this endeavor is a persistent configuration of the project’s sitemap with our own custom options.

Handling submodules

Git submodules are by default in a detached HEAD state, meaning that HEAD will always point to a specific commit (usually the most recent), rather than the usual, i.e. a specific branch.

This causes severe problems to the generation of URLs. Instead of receiving a working URL such as the following:

https://github.com/grtcdr/liaison/commits/main/liaison.el

You’ll instead receive a URL like this:

https://github.com/grtcdr/liaison/commits/(HEAD detached at 984d79d)/liaison.el

This URL is not understood by GitHub, or any other web interface for that matter. To get around this, one must checkout a specific branch (usually the default) immediately after pulling the contents of the submodule.

Within the context of CI/CD

GitHub

A workflow such as the following will not suffice on its own:

steps:
  - name: Checkout repository
    uses: actions/checkout@v3
    with:
      submodules: true

actions/checkout@v3 does not, at the time of writing this, offer the option to check out a specific branch after pulling the submodules of the repository, so our only option is to do this manually.

If you’re sure that every submodule is using the same name for their default branches, foreach is the appropriate and most efficient function. However, you shouldn’t do this unless you’re intending to integrate Liaison into every submodule.

steps:
  - name: Checkout repository
    uses: actions/checkout@v3
    with:
      submodules: true

  - name: [WORKAROUND] Attach to the default branches of submodules
    run:
      git submodule foreach 'git checkout <default-branch> && git pull'      

A better alternative is to individually checkout the default branch for the specific submodules you’re targeting.

This way, if your submodules are using different names for their default branch, e.g. “master” vs “main” or “x.y.z”, you won’t receive any errors about an unknown pathspec. Additionally, you are targeting only the necessary submodules.

steps:
  - name: Checkout repository
    uses: actions/checkout@v3
    with:
      submodules: true

  - name: [WORKAROUND] Attach to the default branches of submodules
    run: |
      cd <path/to/submodule>
      git checkout <default-branch>
      git pull