Gemini, RawContent and shortcodes

So I am of a mind to create a Gemini mirror for my Hugo blog, written, historically, in markdown.

The plan is to produce a “raw” not-yet-Gemini output with .RawContent that constitutes a valid Markdown file, and then pass it through pandoc with a lua formatter which will approximate it down into a Gemini-compliant form I am happy enough with, render everything it can, and quietly excise everything it can’t render.

The problem with that is shortcodes: .RawContent doesn’t render them. Which wouldn’t be a problem, as I can do the requisite filtering later for the most part – except for certain builtin shortcodes, like ref and relref.

A program that processes the resulting prefab output wouldn’t know where a relref or ref shortcode might point to. I’d basically have to reimplement half of Hugo just to get at this information in a non-hardcoded way.

The alternative, using HTML as the intermediate format by supplying specially pared-down templates, would work for everything I actually use, except footnotes: Pandoc can’t parse footnotes from HTML. I use a lot of footnotes, so this is not an option.

Is there a way to pass a string through a shortcode processor inside a template without turning the whole thing into HTML?

This came up yesterday:
https://discourse.gohugo.io/t/37115/

The short answer to your question is, “no.”

Guess I’ll just have to try to implement ref and relref by passing RawContent through regexp replacements then. :frowning:

Conceptually, passing .Content through the plainify function should produce the same results as using .Plain in your template, but it might be worth a quick test just to make sure.

cc/ @dece

Actually, plainify just turns {{< relref ....>}} into {{}}, presumably because it naively treats the contents of <> as a html tag. Never mind that it loses the paragraph breaks.

I almost got the regexp that turns {{< relref ... >}} into the correct link working, though.

1 Like

There we go.

{{ $page := . }}
{{ $raw := .RawContent }}
{{ $tags := findRE "{{< ?relref \"(.+)\" ?>}}" $raw }}
{{ range $link := $tags }}
{{ $raw = replaceRE $link (relref $page (replaceRE "{{< ?relref \"(.+)\" ?>}}" "$1" $link )) $raw }}
{{ end }}
{{ $tags = findRE "{{< ?ref \"(.+)\" ?>}}" $raw }}
{{ range $link := $tags }}
{{ $raw = replaceRE $link (ref $page (replaceRE "{{< ?ref \"(.+)\" ?>}}" "$1" $link )) $raw }}
{{ end }}
{{ return $raw }}

Put in a partial named something to the tune of refs.gemini.gmi and use like so:

{{ partial "refs.gemini.gmi" . }}

where you would otherwise use .RawContent.

1 Like

I ended up, for now, configuring Hugo to produce “mdgmi” files, which are Hugo Markdown files processed into a simplified Markdown version, ready to be truly converted with an external converter (Makeworld’s md2gemini). The layout file then simply reduces some shortcodes into plain Markdown, and is roughly like this:

{{ $content := .RawContent -}}
{{ $content := $content | replaceRE `{{<\s*(?:rel)?ref\s+"([^"]+)"\s*>}}` "$1" -}}
{{ $content := $content | replaceRE `{{<\s*figure\s*(?:.*)?src="([^"]+)"(?:.*)?caption="([^"]+)"(?:.*)?>}}` "![$2]($1)" -}}
{{ $content := $content | replaceRE `{{<\s*image\s*.*?src="([^"]+)".*?>}}` "![]($1)" -}}
{{ $content }}

Then a bash script converts those mdgmi files to proper gmi files. If you restrict yourself (and/or your users) to a frugal use of Markdown features, you obtain beautiful Gemtext.

I must say that this is not a suitable solution for a top-level experience of Gemini, and is more of a good enough solution for distributing your content over Gemini without having to manually reformat the files. Hope this helps!

1 Like

You can’t just do that to relref if, for example, you used it to refer to a post by post slug: if you have a permalink scheme that doesn’t solely consist of the post slug, the resulting markdown link will be broken, and there’s no easy way for whatever you use to process the markdown afterwards to find out the correct one. My blog contains a number of such references, which prompted the much more complicated replacement function I presented above, which actually calls the relref function to produce a proper relative link before the text leaves Hugo.

All the other shortcodes do not require digging into Hugo itself: They almost invariably deal with the presentation of a given link as an embed, a particular combination of image tags and divs, or whatever, none of which gemini supports anyway. The solution to those is to parse the link out and produce an equivalent markdown link. I took care of those outside Hugo with a js program, but that was mostly my preference, because Go template language is a Turing Tarpit not really meant for such things.

1 Like

Yes I did not meant to say my solution should replace yours. The project I used this layout with uses relrefs only with straightforward paths, so calling the relref function is not even needed.

I completely agree with that. Hopefully I’ll get the time to gather the different approaches seen here and on the Web to generate Gemtext content from a Hugo project (there are different, incompatible requirements expressed by different people: you, me, Sylvain Durand, Drew Devault, Seirdy, …) and it would be cool to have tidy documentation about it!

there are different, incompatible requirements expressed by different people: you, me, Sylvain Durand, Drew Devault, Seirdy, …

There are wildly differing opinions on how far you can or should push Gemtext, to start with. For an example, here’s the kind of stuff that was among my requirements that I’m sure nobody else wanted. This:

For whatever reason, the serial port does not respond, and I don't know what the
correct settings for it are anyway.[^2] However, while receiving, the radio sends
[SCO packets](https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols#Synchronous_Connection-Oriented_(SCO)_link),
which the PC drops on the floor:

[^2]: They might be discovered by disassembling the above mentioned Bluteooth
firmware, but like I said, this needs its own hero.

must translate into something like this:

For whatever reason, the serial port does not respond, and I don’t know what the
correct settings for it are anyway.[2] However, while receiving, the radio sends
[SCO packets], which the PC drops on the floor:
┄┄┄┄┄
[2]: They might be discovered by disassembling the above mentioned Bluteooth
firmware, but like I said, this needs its own hero.
┅┅┅┅┅
=> https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols#Synchronous_Connection-Oriented_(SCO)_link SCO packets

That’s simply the kind of posts I write and the expressive capabilities I am not willing to give up, I want my emphasis, my inline links and my footnotes. The only way I could get that going was with pandoc and an overly complicated Lua formatter for it, but fortunately, I had prior experience trying to squeeze Markdown of the same kind into idiosyncratic BBCode, (to be fair, BBCode is universally idiosyncratic) so it was mostly a matter of taking something I already had and hammering at it until it did what I wanted.

But ask me to render tables in Gemtext and I’ll come up blank, I have some ideas, but don’t know how to make Pandoc execute them yet. :slight_smile: Math would necessitate something a lot more complicated, like baking it into a png file.

And then, a lot more people will say I shouldn’t do that to Gemtext in the first place.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.