Sublime Forum

Additional markdown context (hugo sites)

#1

Hi I’d like to make some web pages with hugo, using its “shortcodes” for rendering math with katex.

# KaTeX

KaTeX shortcode let you render math typesetting in markdown document. See [KaTeX](https://katex.org/)

## Example

{{< katex [display] [class="text-center"] >}}
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,d\xi
{{< /katex >}}

{{< katex >}}
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,dξ
{{< /katex >}}

Here is some inline example: {{< katex >}}\pi(x){{< /katex >}}, rendered in the same line.

Eventually I’d also like to make a syntax for katex so I would get embedded highlighting and so on but for now I would be content if the math was highlighted as “raw” text.

I made a simple syntax context that matches the pattern but don’t know where to add it to the Markdown.sublime-syntax.

%YAML 1.2
---
name: TestSyntax
scope: text.test

contexts:
  main:
    - include: hugo-shortcode

  hugo-shortcode:
    - match: \{\{<\s(\w*)\s*([^>\}\}]*)\s>\}\}\n{0,1}
      captures:
        0: hugo.shortcode.header
        1: hugo.shortcode.header.name
        2: hugo.shortcode.header.parameters
      embed: scope:hugo.shortcode.content
      embed_scope: markup.raw.inline.markdown
      escape: \{\{<\s/(\1)\s>\}\}
      escape_captures:
        0: hugo.shortcode.footer
        1: hugo.shortcode.footer.name

I’m already using OverrideAudit so I don’t mind if the whole syntax has to be modified but ideally I would have a separate syntax for build hugo sites.

0 Likes

#2

In case you are on ST4134+, extending builtin Markdown is quite easy and sraightforward.

Just look for the appropriate context and add your patterns:

%YAML 1.2
---
# http://www.sublimetext.com/docs/syntax.html
name: Markdown (Hogo)
scope: text.html.markdown.hugo
version: 2

extends: Packages/Markdown/Markdown.sublime-syntax

contexts:

  literals:
    - meta_prepend: true
    - include: hugo-shortcode

  hugo-shortcode:
    - match: (\{\{<)\s+(\w*)\s*([^>\}\}]*)\s+(>\}\})\n?
      scope: meta.tag.hugo
      captures:
        1: punctuation.definition.tag.begin.hugo
        2: entity.name.tag.hugo
        3: shortcode.header.parameters.hugo
        4: punctuation.definition.tag.end.hugo
      embed: scope:shortcode.content.hugo
      embed_scope: markup.raw.inline.markdown
      escape: (\{\{<)\s+/(\2)\s+(>\}\})
      escape_captures:
        1: punctuation.definition.tag.begin.hugo
        0: entity.name.tag.hugo
        3: punctuation.definition.tag.end.hugo

If you are on ST4126+, you can do the same with MarkdownEditing’s syntax. MDE backports ST4134+ Markdown to make it available for older builds.

0 Likes

#3

Thank you, works great!

0 Likes

#4

Hi,

I just came across your post trying to find a syntax highlighting for my Hugo shortcodes in the Markdown-files.

I created a new file called “Hugo.sublime-syntax” in the “Packages/User” folder and added your YAML to the file.

The moment I switched the language from “Markdown” to " Markdown (Hogo)", some of the highlighting of the markdown file got lost (like the embedded links) and the keyword of the first shortcode was highlighted.

There are several things I tried to find out but wasn’t able to:

  • Why is only the first shortcode highlighted and not all instances?
  • Why gets some of the markdown highlighting lost the moment I switch language?
  • How can I also highlight possible parameters?
  • If I use a shortcode with opening and closing tag - is there a way to change the background color of the contents between the tags?

Maybe you can point me to the right direction?

Regards,
-anmith

0 Likes

#5

Sublime Text 4169+ ships with a Markdown (Go) syntax, which already supports basic Go templates.

Why is only the first shortcode highlighted and not all instances?

The snippet above still works fine on ST4169 and ST4175 with both, bundled Markdown and MarkdownEditing packages.

grafik

It would need some modification when extending Markdown (Go), however.

Maybe you are using an too old Sublime Text or Markdown syntax as a base.

How can I also highlight possible parameters?

You would need to modify the hugo-shortcode pattern by pushing a dedicated “attributes” context onto stack instead of trying to match the whole tag {{< tag ... >}} in a single regex.

If I use a shortcode with opening and closing tag - is there a way to change the background color of the contents between the tags?

You can do so by targeting the value of embed_scope in your color scheme.l

0 Likes

#6

Thanks for the quick response. I’m running ST 4169 (registered).

When setting the language to “Markdown (Go)” it looks like this with the “Mariana” color scheme:

Bildschirmfoto%20vom%202024-07-09%2018-07-13

Only with “Celeste” the shortcode itself seems to be highlighted:

Bildschirmfoto%20vom%202024-07-09%2018-08-46

So it seems the highlighting isn’t working with all color schemes?

Although I have to switch the language every time I open a “.md” file. Is there any way to change the default?

0 Likes

#7

To always open your md files with a certain syntax definition you can

  1. use the Main Menu > View > Syntax > Open all with current extension as... menu item
  2. use packages like ApplySyntax package to specify some more sophisticated rules for when to apply it.

Yeah, {{< tag >}} seems to be something special for Hugo. Looks like Handlebars, actually.

It’s just a quick shot from what I saw right now, but the following might work good enough.

%YAML 1.2
---
# http://www.sublimetext.com/docs/syntax.html
name: Markdown (Hugo)
scope: text.html.markdown.hugo
version: 2

extends: Packages/Go/Markdown (Go).sublime-syntax

file_extensions:
  - hugo

contexts:
  prototype:
    - meta_prepend: true
    - include: hugo-katex-tags
    - include: hugo-other-tags

  hugo-katex-tags:
    - match: ({{<)\s+(katex)\b
      captures:
        1: punctuation.definition.tag.begin.hugo
        2: entity.name.tag.hugo
        3: shortcode.header.parameters.hugo
        4: punctuation.definition.tag.end.hugo
      push: hugo-katex-tag-body

  hugo-katex-tag-body:
    - meta_scope: meta.tag.hugo
    - match: '>}}'
      scope: punctuation.definition.tag.end.hugo
      set: hugo-katex-begin
    - include: hugo-tag-attributes

  hugo-katex-begin:
    - match: ^
      embed: scope:text.tex.latex#math-content
      embed_scope: markup.raw.block.hugo
      escape: ({{<)\s+/(katex)\s+(>}})
      escape_captures:
        0: meta.tag.hugo entity.name.tag.hugo
        1: punctuation.definition.tag.begin.hugo
        3: punctuation.definition.tag.end.hugo
      pop: 1

  hugo-other-tags:
    - match: ({{<)\s+(/?\w+)\b
      captures:
        1: punctuation.definition.tag.begin.hugo
        2: entity.name.tag.hugo
        3: shortcode.header.parameters.hugo
        4: punctuation.definition.tag.end.hugo
      push: hugo-other-tag-body

  hugo-other-tag-body:
    - meta_scope: meta.tag.hugo
    - match: '>}}'
      scope: punctuation.definition.tag.end.hugo
      pop: 1
    - include: hugo-tag-attributes

  hugo-tag-attributes:
    - match: \[
      scope: punctuation.definition.attribute.begin.hugo
      push: hugo-attribute-body
    - include: scope:text.html.go#tag-attributes

  hugo-attribute-body:
    - meta_scope: meta.attribute.hugo
    - match: \]
      scope: punctuation.definition.attribute.end.hugo
      pop: 1
    - match: =
      scope: punctuation.separator.key-value.html
      push: scope:text.html.go#tag-generic-attribute-value
    - match: \w+
      scope: entity.other.attribute-name.html
1 Like

#8

Hi,

tried your snippet, looks good!

Thanks for your support!

0 Likes

#9

Hi,

one (hopefully) last thing - the detection and syntax highlighting of the Hugo shortcodes works as intended, but there’s one additional thing I’d like to do:

When there’s some markdown within a shortcode, there is markdown rendering applied:

Bildschirmfoto%20vom%202024-07-16%2014-12-41

So I tried to apply “markup.raw.inline.markdown” using “embed_scope” but didn’t succeed:

grafik

The scope is applied as intended and the formatting is gone, but the scope now starts right after matching the opening tag, exactly as I defined it.

The thing I can’t solve is how to change the rules so the scope is indeed only between the opening and closing tag and doesn’t start after the shortcode-word removing also the highlighting of the parameters.

%YAML 1.2
---
# https://forum.sublimetext.com/t/additional-markdown-context-hugo-sites/65054/7
# http://www.sublimetext.com/docs/syntax.html
name: Markdown (Hugo)
scope: text.html.markdown.hugo
version: 2

extends: Packages/Go/Markdown (Go).sublime-syntax

file_extensions:
  - hugo

contexts:
  prototype:
    - meta_prepend: true
    - include: hugo-tags

  hugo-tags:
    - match: ({{[<%])\s+(/?\w+)\b
      captures:
        1: punctuation.definition.tag.begin.hugo
        2: entity.name.tag.hugo
        3: shortcode.header.parameters.hugo
        4: punctuation.definition.tag.end.hugo
      push: hugo-tag-body
      embed: scope:shortcode.content.hugo
      embed_scope: markup.raw.inline.markdown
      escape: (\{\{<)\s+/(\2)\s+(>\}\})
      escape_captures:
        1: punctuation.definition.tag.begin.hugo
        0: entity.name.tag.hugo
        3: punctuation.definition.tag.end.hugo

  hugo-tag-body:
    - meta_scope: meta.tag.hugo
    - match: '[>%]}}'
      scope: punctuation.definition.tag.end.hugo
      pop: 1
    - include: hugo-tag-attributes

  hugo-tag-attributes:
    - match: \[
      scope: punctuation.definition.attribute.begin.hugo
      push: hugo-attribute-body
    - include: scope:text.html.go#tag-attributes

  hugo-attribute-body:
    - meta_scope: meta.attribute.hugo
    - match: \]
      scope: punctuation.definition.attribute.end.hugo
      pop: 1
    - match: =
      scope: punctuation.separator.key-value.html
      push: scope:text.html.go#tag-generic-attribute-value
    - match: \w+
      scope: entity.other.attribute-name.html
0 Likes

#10

You can either push or embed, not both at the same time.

You can embed a special “tag attributes context” which sets another body context instead of just popping.


  hugo-other-tags:
    - match: ({{<)\s+(\w+)\b
      captures:
        1: punctuation.definition.tag.begin.hugo
        2: entity.name.tag.hugo
      embed: hogo-other-tag-body
      escape: ({{<)\s+/(\2)\s+(>}})
      escape_captures:
        0: meta.tag.hugo entity.name.tag.hugo
        1: punctuation.definition.tag.begin.hugo
        3: punctuation.definition.tag.end.hugo

  hogo-other-tag-body:
    - meta_scope: meta.tag.hugo
    - match: '>}}'
      scope: punctuation.definition.tag.end.hugo
      set: hugo-raw-block-begin
    - include: hugo-tag-attributes

  hugo-raw-block-begin:
    - match: ^
      set: hugo-raw-block-body

  hugo-raw-block-body:
    - meta_scope: markup.raw.block.hugo
0 Likes

#11

Thanks for all your help, much appreciated.

I can’t think of any trick the syntax highlighting might now if a shortcode has a closing tag or hasn’t - so for all tags without closing tag a second rule has to be implemented with all shortcode names hardcoded.

Or is there something I don’t see?

0 Likes

#12

That’s the way to go. Without any look into hugo I’d probably implement a general rule for shortcode tags, which does not push a dedicated context and use a hard coded list of tags, which are known to need it in order to disable markdown highlighting.

0 Likes

#13

Hi,

thanks - again - for all your help and input.

Shortcodes are defined by the website creator on a project to project base, so building something that fits every project will not be possible IMHO.

Using the ProjectSpecificSyntax plugin and a project-specific syntax file does the trick.

0 Likes