diagrams

This document implements the ability to create diagrams in documents. Documents can take advantage of this by declaring that the use the make_diagrams service.

1 dot diagrams

Graphviz is a beautiful little program created at AT&T, originally for visualizing complex network layouts. It’s basically the TeX of diagrams—particularly the “general directed graphs” that Brooks mentions. You describe the graph using an extremely simple language (called “dot”), which looks like this:

and send it to a little program (also called “dot”), which can produce graphics like Figure 1 in a variety of formats.

testing.svg
Figure 1: A sample diagram

Although Org has very convenient support for dot diagrams, we forego some of that convenience to integrate with our build system. (See “because Tup.”) Instead of using Org Babel to “evaluate” the code block and create the image link as a “result”, we just tangle the block like any other, and then create the SVG image in a separate step. This is all done by the following build rules, in conjunction with one link-rewriting rule in the template you’ll see later.

service make_diagrams : \
foreach $(PUBLISHED)/dot/*.dot \
|> ^ dot %B^ \
   dot -Tsvg \
       -Gbgcolor=transparent \
       -Gfontnames=svg \
       "%f" > "%o" \
|> $(PUBLISHED)/images/%B.svg

service make_diagrams : \
foreach $(PUBLISHED)/images/*.svg \
|> !copy_to |> $(SITE_IMAGES)/%b

By default, the box containing a dot diagram has a solid background. But as far as we’re concerned, that bounding box is immaterial (so to speak). Only the contents are real. The -Gbgcolor=transparent sets a graph-level option to turn off the background.

1.1 stylesheet

You can’t do this this way, because it clobbers any stylesheet loaded specifically with the image, which we do in the program graph. So you’ll have to support this another way.

-Gstylesheet="/static/style/dot-rules.css" \

Regarding the stylesheet, it’s just nominal. The point is that we have a place to put CSS rules that apply to all dot diagrams.

//@require colors
//polygon, rect
//      fill rgba($aboutColor, .6)

And of course that’s just for a web (HTML) context.

1.1.1 BUG the above doesn’t work, see note

1.2 placing figures

The image will not automatically appear in place of the dot code; you have to add a link to the svg file. This is convenience we give up by not using Org Babel. But we can still hide the dot blocks by default,

This will prevent dot blocks from being included in the “published” document, unless we override the setting on the block itself, as we did for the example above.

1.3 rebase references

Is this needed? You can do the same thing by writing ../site/static/images, and it will get handled by the more general rule. Is there some downside to this, e.g. for PDF export?

We publish these image files to a site-specific, absolute location. This transform allows us to write image links relative to the documents (which means that they actually work in Emacs), but also work on the site.

<!-- Rebase image paths -->
<xsl:template mode="org-copy" match="img/@src[starts-with(., '../published/images/')]">
	<xsl:param name="attribute" select="'src'" />
	<xsl:attribute name="{$attribute}">
		<xsl:value-of select="concat(
							    '/static/images/',
							    substring-after(., 'images/'))"/>
	</xsl:attribute>
</xsl:template>

This directory (published/images) could at some point be used for something other than dot diagrams. At the moment, it’s not, so this rebase is here.

1.4 on setting header arguments in Org Babel

The function defined here is indeed used, but otherwise maybe this should be deleted or moved back to the bootstrap section. The thing is, that function is only used here.

Source blocks in Org can have “header arguments” to control a number of things, particularly during export and tangle. Header arguments can be set on individual blocks, such as this

#+BEGIN_SRC emacs-lisp :exports none
some junk that you don't want to be exported
#+END_SRC

which sets the :exports none header. But if a certain header value is used very commonly, we may set a default for convenience. One way to do that would be with a PROPERTY line:

#+PROPERTY: header-args :exports none

This would set the header for all code blocks in the document, and by using such a line in a SETUPFILE or INCLUDE file, we could share common settings among all of the documents. But doing so would require referencing that file from all documents. Worse, it would cause all documents to be dependent on that file, meaning that any change to it would trigger a complete rebuild.

Of course, like everything else in Org (and Emacs generally), this setting is ultimately controlled through a variable, in this case org-babel-default-header-args. The shortest way to set a header is with add-to-list:

(add-to-list 'org-babel-default-header-args '(:exports . "none"))

However, this won’t work if the variable isn’t defined. And for language-specific headers (such as we just used for dot), it won’t be. So we use a custom function instead:

(defun set-babel-header (name value &optional language)
  "Utility function to set `org-babel' headers."
  (let* ((suffix (if language (concat ":" language)))
		 (symbol (intern (concat "org-babel-default-header-args" suffix))))
	(set symbol
		 (cons `(,name . ,value)
			   (if (boundp symbol)
				 (assq-delete-all name (symbol-value symbol)))))))

I never said I was a master of Emacs Lisp, and I’m sure there’s a better way to do that. But it does work.

As discussed in the system, we don’t use Org’s tangle, and although our custom tangle does recognize a few header arguments, it only uses those set on individual blocks, having its own mechanism for system-wide headers.

That header-utility is a little function that I stole from the old (Emacs-based) tangler, where I used it to set a bunch of settings. That has been replaced by the custom tangler, so it’s not needed there, but it’s still kind of a useful function (albeit overkill for this one case).

1.5 support interactive SVG

SVG graphics straddle the line between static and dynamic media. They can be flat, they can be printed. But they can also be dynamic and responsive. At the very least, they can contain functioning links, just like HTML. However, an SVG document that is imported into HTML as an image (using the <img/> element) will not support most of these features. It will be essentially opaque, like a raster image.

Instead, you have to “embed” it into the document, so that its particulars can be accessed.

<!-- Embed SVG as object. -->
<xsl:template
		match="img['.svg' = substring(@src, string-length(@src) - 3)]"
		mode="org-copy">
	<object type="image/svg+xml">
		<!-- We have to do this to get the rebased path. -->
		<xsl:apply-templates select="@src" mode="org-copy">
			<xsl:with-param name="attribute" select="'data'" />
		</xsl:apply-templates>
		<xsl:apply-templates select="@*[not(name() = 'src')]"
												 mode="org-copy" />
		<img>
			<xsl:apply-templates select="@*" mode="org-copy" />
		</img>
	</object>
</xsl:template>

The contents of the <object/> element will be used as a fallback in case the type of object is not supported. This is unlikely at this point, but in any event, we fall back to the <img/> as it was.

This also depends on some additional script, which is currently in the “transitional” folder.

about willshake

Project “willshake” is an ongoing effort to bring the beauty and pleasure of Shakespeare to new media.

Please report problems on the issue tracker. For anything else, public@gavinpc.com

Willshake is an experiment in literate programming—not because it’s about literature, but because the program is written for a human audience.

Following is a visualization of the system. Each circle represents a document that is responsible for some part of the system. You can open the documents by touching the circles.

Starting with the project philosophy as a foundation, the layers are built up (or down, as it were): the programming system, the platform, the framework, the features, and so on. Everything that you see in the site is put there by these documents—even this message.

Again, this is an experiment. The documents contain a lot of “thinking out loud” and a lot of old thinking. The goal is not to make it perfect, but to maintain a reflective process that supports its own evolution.

graph of the program

about

Shakespeare

An edition of the plays and poems of Shakespeare.

the works