Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortcode templates #4

Open
mntn-xyz opened this issue Aug 9, 2021 · 6 comments
Open

Shortcode templates #4

mntn-xyz opened this issue Aug 9, 2021 · 6 comments
Labels
enhancement New feature or request gmnhg Issue related to cmd/gmnhg major Requires a major refactoring or rewrite question Further information is requested

Comments

@mntn-xyz
Copy link
Contributor

mntn-xyz commented Aug 9, 2021

Just wanted to put this out there for consideration... it would be helpful to have some kind of shortcode processing in gmnhg. Given the variety of shortcodes available, as well as the ability for people to define custom shortcodes, it would make sense to build this around the idea of user-defined templates.

Here's one approach:

  • Shortcode templates will be placed in a specified folder and must be named to match the desired shortcode (highlight.go would match the built-in {{< highlight >}} shortcode, and foo/bar.go would match {{< foo/bar >}}).
  • Before parsing with gomarkdown, input files are parsed for shortcodes. This process will have to take into account unpaired, paired, and self-closing shortcodes. The templates themselves will have to handle "nested" shortcodes; the parser will not bother with this. This should simplify parsing somewhat.
  • Each shortcode template presents a common method with arguments that represent both shortcode parameters (if any) and inner content (if any). The method should return the processed text for rendering.
  • Depending on whether the shortcode was called with {{% %}} (further rendering requested) or {{< >}} (present content without further rendering), the template output will either be inlined with the text and passed to gomarkdown, or it will be set aside for inclusion in the final rendered text as-is. The latter could be accomplished by replacing the template with some kind of temporary token like {{<1>}}, which will be replaced after rendering; there may be better approaches as well.
@tdemin tdemin added enhancement New feature or request major Requires a major refactoring or rewrite question Further information is requested labels Aug 12, 2021
@tdemin
Copy link
Owner

tdemin commented Aug 12, 2021

Allowing for custom templating code sure is nice, I never really thought about it. Can you please provide an usage example usage of this (not an existing one, just a short template pseudocode with how it would supposedly be processed)? I know Hugo already does shortcodes, but I've never really seen them in use to this day, and I'm having problems grasping the idea seeing no examples.

@tdemin tdemin added the gmnhg Issue related to cmd/gmnhg label Aug 12, 2021
@mntn-xyz
Copy link
Contributor Author

mntn-xyz commented Aug 12, 2021

The simplest example, taken from Hugo's documentation, is the built-in "highlight" shortcode.

{{< highlight html >}}
<section id="main">
  <div>
   <h1 id="title">{{ .Title }}</h1>
    {{ range .Pages }}
        {{ .Render "summary"}}
    {{ end }}
  </div>
</section>
{{< /highlight >}}

For translation to Gemtext, the template function would just receive the inner text and format it as a code block:

```
<section id="main">
  <div>
   <h1 id="title">{{ .Title }}</h1>
    {{ range .Pages }}
        {{ .Render "summary"}}
    {{ end }}
  </div>
</section>
```

For an example that uses parameters, there's the built-in "figure" shortcode. This can have a number of parameters, including captions, alt text, image attribution text, and image attribution links.

{{< figure src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Sc_%28spreadsheet_calculator%29.png/300px-Sc_%28spreadsheet_calculator%29.png" width="300" height="153" link="https://en.wikipedia.org/wiki/File:Sc_(spreadsheet_calculator).png" title="sc" caption="spreadsheet calculator" alt="Sc (spreadsheet calculator).png" >}}

Here's a hypothetical output for this example:

=> https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Sc_%28spreadsheet_calculator%29.png/300px-Sc_%28spreadsheet_calculator%29.png sc
=> https://en.wikipedia.org/wiki/File:Sc_(spreadsheet_calculator).png Sc (spreadsheet calculator).png
spreadsheet calculator

In order to render this, the parser would need to parse any shortcode arguments and pass them to the rendering function in figure.go. Some may be ignored by the function (width/height). These are the parameters from that particular figure template:

This is an implementation detail, but in case it helps, I imagine a signature like this:

type param struct {
    name string
    value string
}

func render(innerText *string, params ...param) string {}
  • innerText would be nil if there is none present
  • params would contain an arbitrary number of param structs
  • the function itself would be responsible for receiving these parameters, determining how they are formatted based on what is provided, and generating a string from it

@mntn-xyz
Copy link
Contributor Author

I'll add that the formatting function could get relatively complex and the output probably depends on the user's preference. For instance, in the figure example I gave, maybe the user would prefer to have the function output just the link and not the thumbnail if both are present. Maybe they would want the caption to have a "Caption: " prefix. With user-defined functions they can format this however they like, as long as they return a string.

@mntn-xyz
Copy link
Contributor Author

I started looking into this more, thinking that there may be a way to use Hugo itself for preprocessing to fill out any shortcodes and inline {{ }} code blocks. At first I was looking into using the rendering internals directly, but it is enormously complicated and would be fragile.

This led me to look at Hugo output formats, and I wonder if you couldn't just have Hugo render markdown files using "text/plain" to fill out the shortcodes? Then you would just postprocess the generated files to translate them to Gemtext. https://gohugo.io/templates/output-formats/

I think this could be done in a way where users could provide Gemtext "override" templates that take precedence over any theme or built-in templates. I'll investigate this more when I have some time.

@mntn-xyz
Copy link
Contributor Author

Investigated a little bit. I think this will be needed first (PR seems to be in progress): gohugoio/hugo#7297

Adding this to config.toml got me most of the way there:

[mediaTypes]
[mediaTypes."text/gemini"]
suffixes = ["gmi"]

[outputFormats]
[outputFormats.gemini]
isPlainText = false
isHTML = false
mediaType = "text/gemini"
protocol = "gemini://"

[outputs]
page = ["gemini"]

I also needed to create layouts/_default/single.gmi:

{{ .RawContent }}

Current issues:

  • isPlainText = false renders shortcodes, but escapes reserved HTML characters
  • isPlainText = true does not render shortcodes (linked Hugo issue should resolve that)
  • Rendered pages don't include front matter, and I don't know of a variable for this. The template could enumerate .Params maybe?

@mntn-xyz
Copy link
Contributor Author

I found a straightforward way to build a template that includes both the front matter and the raw text output:

{{ .Params | jsonify }}
{{ .RawContent }}

So if that proposed ".RenderShortcodes" function were implemented in Hugo, you could use the following template:

{{ .Params | jsonify }}
{{ .RawContent | .RenderShortcodes }}

With the definition of a custom media type and output format, this template can then be used to pre-render all markdown files for processing with gmnhg, filling out {{ }} code blocks and shortcodes. In fact this can be done 100% on the user side with some clever scripting, no need for gmnhg changes... but if this change does eventually make it into Hugo, it would be useful to have this process automated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request gmnhg Issue related to cmd/gmnhg major Requires a major refactoring or rewrite question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants