statiqdev / Statiq.Framework

A flexible and extensible static content generation framework for .NET.
https://statiq.dev/framework
MIT License
421 stars 75 forks source link

Errors on inserting c# code snippets in a markdown file when using razor template #213

Closed AnkurSheel closed 2 years ago

AnkurSheel commented 2 years ago

I have built a custom pipeline that renders an HTML page using the markdown, highlightcode and razor modules

In one of the posts, I have a code snippet like

```csharp
    const sql = @"Select * FROM users
                WHERE id IN @UserIds"

On running the solution, I get an error [CRIT] One or more compilation failures occurred: Error RZ1005: ""Select * FROM users" is not valid at the start of a code block. Only identifiers, keywords, comments, "(" and "{" are valid.

I have gotten around this by updating the snippet to

 const sql = @@"@Html.Raw("Select * FROM users")
                WHERE id IN @@UserIds"

I was wondering if there is a better way to handle this?

Omitting unnecessary parts of the custom pipeline for brevity

ProcessModules = new ModuleList
{
// some modules here
    new RenderMarkdown().UseExtensions(),
    new HighlightCode(),
// some modules here
};
 PostProcessModules = new ModuleList
  {
      new RenderRazor()
  };
daveaglick commented 2 years ago

The issue here is the way Razor interprets anything starting with a @ as code. In the initial version, it saw the @Select * FROM users line and attempted to interpret that as C# code (which it obviously isn't).

The RenderMarkdown module attempts to correct for this by automatically HTML encoding any @ symbols (on the assumption that Markdown files generally get fed to the Razor engine later, though this behavior can be turned off by calling new RenderMarkdown.EscapeAt(false)). This is where I'm a little confused and wondering if there's a bug. It should have caught your @ and replaced it with @ post-Markdown rendering.

My first guess is that maybe the HighlightCode module is then un-escaping the @ when it processes the code block. Can you take that one out of the pipeline temporarily and add the original @Select * FROM users back in to see if it works successfully? If so, I'll take a look at the HighlightCode module to see how to stop it from un-escaping our carefully escaped @ symbols.

daveaglick commented 2 years ago

Just thought of another simple mitigation: the HighlightCode module can go after the RenderRazor module in the post-process phase. That'll ensure it doesn't mess with any of the escaping done to avoid problems with @. I'll still investigate how to keep HighlightCode from unescaping HTML escape sequences (I'm pretty sure that's the issue), but at least moving the modules around will unblock you.

daveaglick commented 2 years ago

This is now also resolved in the latest development branch (and with the next release). The HighlightCode module will no longer re-encode encoded character references so it can be placed before the RenderRazor module without problems going forward.