Code blocks with ansi color sequences

Hi,

(first time poster, hugo beginner)

I was wondering, when I want to put the output of a CLI tool on a hugo page in a code block which contains ansi color characters, what would be the best way to do that? If I just pipe the CLI output into a text file (and set CLI options to preserve the colorization) and put the result into a code block in markdown then the HTML just shows uncolored output and [1m or [0m from the control sequences.

Really looking for a convenient way to go from colored cli tool to colored terminal printout in the browser. Doesn’t really have to go through code blocks in a markdown file.

top to bottom

  • vim (with ansi color plugin) showing that the colored output from clang ended up in the text file
  • emacs (without ansi color parsing) showing my markdown file (never mind the small differences in the actual printout, i iterated around a bit)
  • after running with hugo, the browser view

I came across GitHub - buildkite/terminal-to-html: Converts arbitrary shell output (with ANSI) into beautifully rendered HTML , maybe someone has bodged this into hugo?

Thanks in advance,

Paul

I don’t know any implementation of that, but it would be as easy as a shortcode.

{{< myhighlightingshortcode >}}
YOUR ANSI FORMATTED HTML
{{< /myhighlightingshortcode >}}

and in layouts/_shortcodes/myhighlightingshortcode.html

<div class="with some classes">
{{ .Inner }}
</div>

where YOUR ANSI FORMATTED HTML is the output of buildkite/terminal-to-html.

To make it short, Chroma (the “upstream library” that does the code highlighting) has no option to parse and format ANSI. I see two solutions: one is the shortcode above. This will lead to a bit of an issue once you start re-designing your site, because then you will have to redesign every use of the shortcode.

Which brings me to solution two: Add a render hook for code blocks and do a check with the code. If it’s “your” ANSI format, then use your own code to parse and format it, else use the internal highlight function of GoHugo. That’s a bit work intense and probably overkill. On the other side with a little bit of configuration it’s probably something that wouldn’t change, ANSI is quite static.

A third option I just got out of my magic hat is that you could do a script outside of Hugo, put the code into a text file or Gist and then reparse everytime you change the design. Basically produce a pre-parsed HTML snippet that you then add (like the shortcode).

If you don’t care about JS on your pages there are some single file JS libraries that convert Text to HTML code.

  • ansi_up
  • fancy-ansi

Just a research not yet worked with any of them - so no recommendation.

they claim to

  • be used in a browser
  • look like they output some simple div-span sequence like syntax highlighters.
  • allow some customization using CSS …

together with a render hook or shortcode … could be nice

i played a little, and one possibility would be to code after the mermaid example in the docs

ansi_up is available via a CDN

check out their docs for styling options, guess you want white text on black background (hardcoded for the screenshot)

for a starter without validation, error checking…

  • markdown content file:

    ```ansi_up
    e[32;1mMode   e[0me[32;1m              LastWriteTimee[0m e[32;1;3m        Lengthe[0me[32;1m Namee[0m
    e[32;1m----   e[0m e[32;1m             -------------e[0m e[32;1m        ------e[0m e[32;1m----e[0m
    ```
    
  • layouts/_markup/render-codeblock-ansi_up.html

    <pre><div id="ansi-up-{{ .Ordinal }}">
    {{- .Inner -}}
    </div></pre>
    {{- .Page.Store.Set "hasAnsiUp" true }}
    
  • layouts/baseof.html at the end of body

    {{- if .Store.Get "hasAnsiUp" }}
      <script type="module">
        import { AnsiUp } from 'https://cdn.jsdelivr.net/npm/ansi_up@6.0.6/ansi_up.min.js';
        // var cdiv = document.getElementById("console");
        var ansiUp = new AnsiUp();
        var codeBlocks = document.querySelectorAll(`[id^="ansi-up-"]`);
        codeBlocks.forEach(function (block) {
      	block.innerHTML = ansiUp.ansi_to_html(block.innerHTML);
        });
      </script>
    {{- end }}
    </body>
    </html>
    

ps. not a web javascript-ing expert

1 Like

Here’s a showcase for using ascii_up and fancy-ascii in a code block processed with render hooks

  • utilizes the npm modules
  • utilizes jsBuild to compile to javascript module
  • render hooks follow the mermaid examples

open points: integrate module specific customization regarding features or styles. fancy-ansi caims to support tailwind

have fun coding

git clone --single-branch -b topic-56513-ansiColor --depth 1 https://github.com/irkode/hugo-forum.git topic-56513-ansiColor
cd topic-56513-ansiColor
npm install
hugo server

my first go with jsBuild:

  • took some time until I discovered problems where not code based but cause by the difference in iife and esm :wink: and f**k I had to point the AI to that to come to a working state.
  • posting improvements is very welcome