Making posters in System Crafter style using org-mode

As a scientist, I regularly need to produce posters to present at conferences. Over the last years I transitioned to “living in org-mode”, but I didn’t have a good solution for generating posters. Also I transitioned my websites to a heavily Systemcrafter-inspired style, and now I wanted also the poster to be in sync with this style (because I was presenting a tool with a website).

I started from org-beamerposter and added a customization and style layer. I wrote a short blog post about it. If this is of any interest to you, please check it out on github: github.com/bam93/org-beamerposter.

Here is a link to a small teaser image, as well.

5 Likes

@Marc this is really neat, thanks for sharing. I like the styles you created and being able to layout a poster in org-mode is quite something else.

1 Like

Thank you @shom, it took me a (much too) long time to get this first poster together, but now I feel I can streamline very quickly for any future ones, so happy to have put in the effort once, even if it messed up my week’s planning :slight_smile:

I also was worried the dark background style would not print well, but I must say the result is really stunning. I printed on a glossy paper and it is - for me - really a beautiful printout (that I was charged twice the price for, because it had over 80% ink coverage.. I didn’t know the print services do that.. but it was worth it).

2 Likes

Thank you for this, and I meet some errors:

  1. make style
info:: Converting style from YAML to JSON
yq -o=json '.' styles/donder-config.yml > config.json
jq: Unknown option -o=json
Use jq --help for help with command-line options,
or see the jq manpage, or online docs  at https://stedolan.github.io/jq
make: *** [Makefile:24: config.json] Error 2
  1. after I remove ‘-o=json’ option, I get
    make style
info:: Converting style from YAML to JSON
yq '.' styles/donder-config.yml > config.json

info:: ✔ Theme generated as tex/beamerorgposter.sty
/usr/lib/ruby/vendor_ruby/mustache/parser.rb:286:in `error': Illegal content in tag (Mustache::Parser::SyntaxError)
  Line 40
    <% #colors %>
      ^
	from /usr/lib/ruby/vendor_ruby/mustache/parser.rb:196:in `scan_tags'
	from /usr/lib/ruby/vendor_ruby/mustache/parser.rb:134:in `compile'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:59:in `tokens'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:50:in `compile'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:36:in `render'
	from /usr/lib/ruby/vendor_ruby/mustache.rb:137:in `render'
	from /usr/lib/ruby/vendor_ruby/mustache.rb:97:in `render'
	from /usr/bin/mustache:89:in `process_files'
	from /usr/bin/mustache:102:in `<main>'
make: *** [Makefile:30: tex/beamerorgposter.sty] Error 1

I think there is something weird going on on your system. yq and jq should be different and distinct commands. I don’t know why when you execute yq -o=json .. you get an error from jq ! Maybe you set an alias or so?

Here is what I have for both commands, you can see yq is from https://github.com/mikefarah/yq/. Let me know if that helps, if not we can try to debug further. In terms of version I have yq version v4.45.4 and jq-1.8.0.

:583; /opt/homebrew/bin/yq -h
yq is a portable command-line data file processor (https://github.com/mikefarah/yq/)
See https://mikefarah.gitbook.io/yq/ for detailed documentation and examples.

Usage:
  yq [flags]
  yq [command]

Examples:

# yq tries to auto-detect the file format based off the extension, and defaults to YAML if it's unknown (or piping through STDIN)
# Use the '-p/--input-format' flag to specify a format type.
cat file.xml | yq -p xml

# read the "stuff" node from "myfile.yml"
yq '.stuff' < myfile.yml

# update myfile.yml in place
yq -i '.stuff = "foo"' myfile.yml

# print contents of sample.json as idiomatic YAML
yq -P -oy sample.json


Available Commands:
  completion  Generate the autocompletion script for the specified shell
  eval        (default) Apply the expression to each document in each yaml file in sequence
  eval-all    Loads _all_ yaml documents of _all_ yaml files and runs expression once
  help        Help about any command

Flags:
  -C, --colors                        force print with colors
      --csv-auto-parse                parse CSV YAML/JSON values (default true)
      --csv-separator char            CSV Separator character (default ,)
  -e, --exit-status                   set exit status if there are no matches or null or false is returned
      --expression string             forcibly set the expression argument. Useful when yq argument detection thinks your expression is a file.
      --from-file string              Load expression from specified file.
  -f, --front-matter string           (extract|process) first input as yaml front-matter. Extract will pull out the yaml content, process will run the expression against the yaml content, leaving the remaining data intact
      --header-preprocess             Slurp any header comments and separators before processing expression. (default true)
  -h, --help                          help for yq
  -I, --indent int                    sets indent level for output (default 2)
  -i, --inplace                       update the file in place of first file given.
  -p, --input-format string           [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|lua|l] parse format for input. (default "auto")
      --lua-globals                   output keys as top-level global variables
      --lua-prefix string             prefix (default "return ")
      --lua-suffix string             suffix (default ";\n")
      --lua-unquoted                  output unquoted string keys (e.g. {foo="bar"})
  -M, --no-colors                     force print with no colors
  -N, --no-doc                        Don't print document separators (---)
  -0, --nul-output                    Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char.
  -n, --null-input                    Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.
  -o, --output-format string          [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|shell|s|lua|l] output format type. (default "auto")
  -P, --prettyPrint                   pretty print, shorthand for '... style = ""'
      --properties-array-brackets     use [x] in array paths (e.g. for SpringBoot)
      --properties-separator string   separator to use between keys and values (default " = ")
  -s, --split-exp string              print each result (or doc) into a file named (exp). [exp] argument must return a string. You can use $index in the expression as the result counter. The necessary directories will be created.
      --split-exp-file string         Use a file to specify the split-exp expression.
      --string-interpolation          Toggles strings interpolation of \(exp) (default true)
      --tsv-auto-parse                parse TSV YAML/JSON values (default true)
  -r, --unwrapScalar                  unwrap scalar, print the value with no quotes, colors or comments. Defaults to true for yaml (default true)
  -v, --verbose                       verbose mode
  -V, --version                       Print version information and quit
      --xml-attribute-prefix string   prefix for xml attributes (default "+@")
      --xml-content-name string       name for xml content (if no attribute name is present). (default "+content")
      --xml-directive-name string     name for xml directives (e.g. <!DOCTYPE thing cat>) (default "+directive")
      --xml-keep-namespace            enables keeping namespace after parsing attributes (default true)
      --xml-proc-inst-prefix string   prefix for xml processing instructions (e.g. <?xml version="1"?>) (default "+p_")
      --xml-raw-token                 enables using RawToken method instead Token. Commonly disables namespace translations. See https://pkg.go.dev/encoding/xml#Decoder.RawToken for details. (default true)
      --xml-skip-directives           skip over directives (e.g. <!DOCTYPE thing cat>)
      --xml-skip-proc-inst            skip over process instructions (e.g. <?xml version="1"?>)
      --xml-strict-mode               enables strict parsing of XML. See https://pkg.go.dev/encoding/xml for more details.

Use "yq [command] --help" for more information about a command.`

And for jq:

baaden@neo-(08:37)-(/dev/disk3s5)-(1,3Ti)-
-(/Users/baaden)-
:584; jq -h
jq - commandline JSON processor [version 1.8.0]

Usage:	jq [options] <jq filter> [file...]
	jq [options] --args <jq filter> [strings...]
	jq [options] --jsonargs <jq filter> [JSON_TEXTS...]

jq is a tool for processing JSON inputs, applying the given filter to
its JSON text inputs and producing the filter's results as JSON on
standard output.

The simplest filter is ., which copies jq's input to its output
unmodified except for formatting. For more advanced filters see
the jq(1) manpage ("man jq") and/or https://jqlang.org/.

Example:

	$ echo '{"foo": 0}' | jq .
	{
	  "foo": 0
	}

Command options:
  -n, --null-input          use `null` as the single input value;
  -R, --raw-input           read each line as string instead of JSON;
  -s, --slurp               read all inputs into an array and use it as
                            the single input value;
  -c, --compact-output      compact instead of pretty-printed output;
  -r, --raw-output          output strings without escapes and quotes;
      --raw-output0         implies -r and output NUL after each output;
  -j, --join-output         implies -r and output without newline after
                            each output;
  -a, --ascii-output        output strings by only ASCII characters
                            using escape sequences;
  -S, --sort-keys           sort keys of each object on output;
  -C, --color-output        colorize JSON output;
  -M, --monochrome-output   disable colored output;
      --tab                 use tabs for indentation;
      --indent n            use n spaces for indentation (max 7 spaces);
      --unbuffered          flush output stream after each output;
      --stream              parse the input value in streaming fashion;
      --stream-errors       implies --stream and report parse error as
                            an array;
      --seq                 parse input/output as application/json-seq;
  -f, --from-file           load the filter from a file;
  -L, --library-path dir    search modules from the directory;
      --arg name value      set $name to the string value;
      --argjson name value  set $name to the JSON value;
      --slurpfile name file set $name to an array of JSON values read
                            from the file;
      --rawfile name file   set $name to string contents of file;
      --args                consume remaining arguments as positional
                            string values;
      --jsonargs            consume remaining arguments as positional
                            JSON values;
  -e, --exit-status         set exit status code based on the output;
  -V, --version             show the version;
  --build-configuration     show jq's build configuration;
  -h, --help                show the help;
  --                        terminates argument processing;

Named arguments are also available as $ARGS.named[], while
positional arguments are available as $ARGS.positional[].

Thanks. The yq on my system is a Debian Package (https://debian.pkgs.org/12/debian-main-arm64/yq_3.1.0-3_all.deb.html), and yours is a specific software.
Why do they have the same name?

Ok, I tried to check on that. The discrepancy with the yq tool arises because there are multiple, unrelated command-line utilities named “yq” in the open source ecosystem. For what I know, the most widely used “yq” today is Mike Farah’s yq (GitHub - mikefarah/yq: yq is a portable command-line YAML, JSON, XML, CSV, TOML and properties processor), a Go-based YAML/JSON processor with jq-like syntax. However, Debian and some other Linux distributions have historically packaged a different tool under the same name, often a Python-based wrapper around jq, or even other variants.

Anyway, in the poster pipeline, I wanted to use a human readable format that can be easily edited, so I chose YAML. But further down the pipeline I need json format (of the same data), and I use the above yq to convert the YAML into Json. But you could use any tool that does that. One alternative would be Python’s PyYAML library for example. Could be as simple as:

python3 -c 'import sys, yaml, json; json.dump(yaml.safe_load(sys.stdin), sys.stdout)' < input.yaml > output.json

Thanks. I tried your proposal. It generates the same error.

make style 

info:: Converting style from YAML to JSON
python3 -c 'import sys, yaml, json; json.dump(yaml.safe_load(sys.stdin), sys.stdout)' < styles/donder-config.yml > config.json

info:: ✔ Theme generated as tex/beamerorgposter.sty
/usr/lib/ruby/vendor_ruby/mustache/parser.rb:286:in `error': Illegal content in tag (Mustache::Parser::SyntaxError)
  Line 40
    <% #colors %>
      ^
	from /usr/lib/ruby/vendor_ruby/mustache/parser.rb:196:in `scan_tags'
	from /usr/lib/ruby/vendor_ruby/mustache/parser.rb:134:in `compile'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:59:in `tokens'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:50:in `compile'
	from /usr/lib/ruby/vendor_ruby/mustache/template.rb:36:in `render'
	from /usr/lib/ruby/vendor_ruby/mustache.rb:137:in `render'
	from /usr/lib/ruby/vendor_ruby/mustache.rb:97:in `render'
	from /usr/bin/mustache:89:in `process_files'
	from /usr/bin/mustache:102:in `<main>'
make: *** [Makefile:30: tex/beamerorgposter.sty] Error 1

What is this ‘parser.rb’ for?

Thank you for the feedback. This is a different error now. Basically what you are doing is generating the style based on the configuration described in the yaml file to obtain a .sty file for latex. This has two steps:

  1. convert yaml to json
  2. use mustache to generate sty file from json
    I think step 1 now works (which was the previous issue about jq/yq). Step 2 seems to have an issue. Mustache is the template engine and can be installed different ways. Something does not seem to go right with your install. Maybe inspect the files manually.

Step 1 just executes

yq -o=json '.' styles/donder-config.yml > config.json

You can then inspect config.json, to make sure it looks like a proper json file.

Step 2 will be

mustache config.json styles/donder-beamertheme.mustache > tex/beamerorgposter.sty

this seems to be where you get your error from. I use mustache version 4.2.0. Your version does seem to have issues with the syntax <% #colors %>, which is a deviation from the standard {{ }} mustache syntax because Latex already uses the curly braces and mustache get confused, so the first line of the mustache file contains {{=<% %>=}}, which tells it to replace the default {{ and }} by <% and %>. To me it seems like your version doesn’t like/do this. I am unsure why. Maybe just check that the first line of the .mustache file that you use does indeed read as {{=<% %>=}}, which it should.

Thanks for the debugging.

  1. The first line of my .mustache file is
{{=<% %>=}}
  1. Again my mustache version is:
mustache --version
=> v1.1.1
It is from Debian package: http://mustache.github.com/mustache.1.html

Are we referring to the same mustache?

Thank you. I checked this, and could also reproduce the error. The issue is that a variety of mustache implementations are available. You are using the ruby implementation. It is quite old, and does not support the syntax that changes the delimiter change from {{ to <% and }} to %>. Several options (in theory):

  1. Use another mustache implementation that is more recent
  2. Update the ruby mustache version
  3. Escape the Latex {{/}} to use standard mustache

I haven’t tested all of those, but here is how you could in principle do it (solution 1), and what my tests for 2. and 3. produced:

  1. On ubuntu, you can do sudo apt-get install node-mustache and then get /usr/lib/nodejs/mustache/bin/mustache --version with version 2.3.2, which works fine for me
  2. Couldn’t find easily an update for a more recent ruby mustache version
  3. Seems complicated, couldn’t get it to work easily, the ruby version really seems ancient

So maybe if that’s ok for you, try the node version of mustache.

Thanks. I tried 2, and use

npm install -g mustache

and the make style PASS.

Now make logo complains:

make logo

info:: generating tiled logos
script/logo_tiler.py
make: script/logo_tiler.py: No such file or directory
make: *** [Makefile:44: logo] Error 127

The file script/logo_tiler.py is there and permission is also ok.

What’s wrong then?

The error could be due to a dysfunctional shebang in script/logo_tiler.py. I would call python directly in the make rule and let the shell find where the python interpreter is.

1 Like

Thanks. ‘make logo’ is ok.

1 Like

Good catch. Indeed, sorry, I left a shebang path that is specific to my system. Will correct that soon, but good to document it here.