Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Custom Template and Config

term-transcript allows overwriting the Handlebars template, or to collect all config options into a single TOML file.

Custom template

The --tpl option allows to configure a custom Handlebars template rather than the standard ones. As an example, it’s possible to render a transcript into HTML.

term-transcript exec --tpl custom.html.handlebars \
  -o rainbow.html rainbow 'rainbow --short'
Used Handlebars template (click to expand)
{{!
  Example of a custom Handlebars template for use with `term-transcript`.
  This template renders an HTML document with collapsible interaction sections.
}}
{{! Import misc helpers to the scope. }}
{{>_helpers}}
{{! CSS definitions: colors. }}
{{~#*inline "styles_colors"}}
:root {
  {{~#each palette.colors}}

  --{{@key}}: {{this}}; --i-{{@key}}: {{lookup ../palette.intense_colors @key}};
  {{~/each}}

  --hl-black: rgba(255, 255, 255, 0.1);
}
.fg0 { color: var(--black); } .bg0 { background: var(--black); }
.fg1 { color: var(--red); } .bg1 { background: var(--red); }
.fg2 { color: var(--green); } .bg2 { background: var(--green); }
.fg3 { color: var(--yellow); } .bg3 { background: var(--yellow); }
.fg4 { color: var(--blue); } .bg4 { background: var(--blue); }
.fg5 { color: var(--magenta); } .bg5 { background: var(--magenta); }
.fg6 { color: var(--cyan); } .bg6 { background: var(--cyan); }
.fg7 { color: var(--white); } .bg7 { background: var(--white); }
.fg8 { color: var(--i-black); } .bg8 { background: var(--i-black); }
.fg9 { color: var(--i-red); } .bg9 { background: var(--i-red); }
.fg10 { color: var(--i-green); } .bg10 { background: var(--i-green); }
.fg11 { color: var(--i-yellow); } .bg11 { background: var(--i-yellow); }
.fg12 { color: var(--i-blue); } .bg12 { background: var(--i-blue); }
.fg13 { color: var(--i-magenta); } .bg13 { background: var(--i-magenta); }
.fg14 { color: var(--i-cyan); } .bg14 { background: var(--i-cyan); }
.fg15 { color: var(--i-white); } .bg15 { background: var(--i-white); }
{{/inline~}}

{{! CSS definitions }}
{{~#*inline "styles"}}
    <style>
    {{>styles_colors}}
    .bold,.prompt { font-weight: bold; }
    .italic { font-style: italic; }
    .underline { text-decoration: underline; }
    .strike { text-decoration: line-through; }
    .underline.strike { text-decoration: underline line-through; }
    .dimmed > span { opacity: 0.5; }
    @keyframes blink {
      0% { opacity: 1; }
      100% { opacity: 0.5; }
    }
    .blink > span { animation: 1s steps(2, jump-none) 0s infinite blink; }
    .concealed { color: transparent !important; }
    .term-wrapper {
      color: var(--white);
      background-color: var(--black);
    }
    .term-output {
      line-height: 1.25;
    }
    .content {
      max-width: {{add width 100}}px;
      margin: 0 auto;
      padding: .75rem;
    }
    main {
      max-width: {{add width 40}}px;
      margin: 0 auto;
      padding: .75rem;
    }
    main .accordion-button {
      margin: 0 -.75rem;
      padding: .75rem;
      width: calc(100% + 1.5rem);
      border-radius: 0 !important;
    }
    .white-space-pre {
      white-space: pre;
    }
    </style>
{{/inline~}}

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="language" content="en">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">

    {{~>styles}}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>Terminal transcript</title>
  </head>
  <body>
    <header>
      <div class="content">
        <h1 class="display-3 mb-4 text-center">Terminal Transcript</h1>
        <p class="lead">This example demonstrates using <code>term-transcript</code> with a custom template.</p>
        <p>Templating allows changing the output format completely; in this case, it is changed to HTML instead of default SVG. The template source and docs can be found in the <a href="{{creator.repo}}">project repository</a>.</p>
      </div>
    </header>
    <main class="term-wrapper rounded">
      <div class="accordion accordion-flush">
      {{~#each interactions}}
        <div class="accordion-item bg-transparent{{#if (not @last)}} mb-2{{/if}}">
          <h2 class="accordion-header" id="user-input-{{@index}}">
            <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#term-output-{{@index}}" aria-expanded="true" aria-controls="term-output-{{@index}}">
              <span class="font-monospace small white-space-pre">{{input.text}}</span>
            </button>
          </h2>
          <div id="term-output-{{@index}}" class="accordion-collapse collapse show" aria-labelledby="user-input-{{@index}}">
            <div class="accordion-body p-0 pt-2">
              <pre class="term-output mb-0">
              {{~#each output as |line|~}}
                {{~#each line.spans as |span|~}}
                  {{! Invoke the `html_span` helper used by the default template. }}
                  {{~>html_span span~}}
                {{~else~}}{{! The line may be empty }}
                {{~/each}}
                {{! Add a newline in order to make the text correctly copyable }}

              {{/each~}}
              </pre>
            </div>
          </div>
        </div>
      {{~/each}}
      </div>
    </main>
    <footer class="my-4 text-center">
      <p><em class="small text-muted">Created with <a href="{{creator.repo}}">{{creator.name}} v{{creator.version}}</a></em></p>
    </footer>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
  </body>
</html>

Configuration file

--config-path option allows reading rendering options from a TOML file. This enables configuring low-level template details. The snapshot below uses a configuration file to customize palette colors and scroll animation step / interval.

Snapshot with config read from file

Configuration file (click to expand)
# Custom template configuration.
line_height = 1.3
width = 900
window = { title = 'Custom Configuration Example' }
line_numbers = { scope = 'continuous', continued.mark = '…' }
dim_opacity = 0.5
wrap.hard_break_at = { chars = 100, mark = '—' }
scroll = { max_height = 300, pixels_per_scroll = 18, interval = 1.5 }

[palette.colors]
black = '#3c3836'
red = '#b85651'
green = '#8f9a52'
yellow = '#c18f41'
blue = '#68948a'
magenta = '#ab6c7d'
cyan = '#72966c'
white = '#a89984'

[palette.intense_colors]
black = '#5a524c'
red = '#b85651'
green = '#a9b665'
yellow = '#d8a657'
blue = '#7daea3'
magenta = '#d3869b'
cyan = '#89b482'
white = '#ddc7a1'

Generating command:

term-transcript exec --config-path config.toml \
  'rainbow --long-lines'