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

{% render "filename" %} with custom extensions #581

Open
brmassa opened this issue Jun 29, 2023 · 9 comments
Open

{% render "filename" %} with custom extensions #581

brmassa opened this issue Jun 29, 2023 · 9 comments

Comments

@brmassa
Copy link

brmassa commented Jun 29, 2023

Currently, {% render "filename" %} will only look for a file called filename.liquid. However, would be great to make it use the IFileProvider to figure out the proper file, allowing users to customize this behavior.

It's particularly good if the liquid template is actually creating a known format in IDE, like HTML, CSS. Using the destination format extension like filename.html, filename.css, filename.liquid.html would allow the IDE to highlight the code properly.

it's somewhat related to #357

probable targets:

  • Fluid/Ast/RenderStatement.cs
  • Fluid/Ast/IncludeStatement.cs
@hishamco
Copy link
Collaborator

hishamco commented Jul 6, 2023

I think it's fine to keep it as its. In your case, you can customize FluidMvcViewOptions

@brmassa
Copy link
Author

brmassa commented Jul 6, 2023

but this implies using MvcViewEngine, right? My app is a console one. when creating the parser, we already provide a IFileProvider to mostly inform the "root" path.

the proposed solution is to implement some kind of virtual method to search for and resolve the right filename. If the MVC already provides a bit of this, would be great to migrate the core into the parser itself.

In short: there is a use case for using kinda some of the MVC functionality without the need for the full-blown MVC framework.

@mihail-brinza
Copy link

Bumping this topic,
I was trying to use Fluid and wanted to store all my templates in the cloud, and having an IFileProvider would allow us to customize how the file is fetched.
I could open a PR to implement this if anyone would be interested to take a look.

@sebastienros
Copy link
Owner

There is already an IFileProvider in the general options:

https://github.com/sebastienros/fluid/blob/main/Fluid/TemplateOptions.cs#L19-L22

So you can set it as default options or per template (in TemplateContext). You can provide a custom implementation of IFileProvider to return the stream you want to use for any filename. Can you try them and let us know if that works?

@mihail-brinza
Copy link

mihail-brinza commented Jan 31, 2024

Thank you, that'll work. For some reason I missed the usage file provider in Ast/IncludeStatement.cs but it's there.
The only minor downside is that the interface is not prepared for async I/O operations.

I'll post an update after I finish the implementation.

@brmassa
Copy link
Author

brmassa commented Dec 16, 2024

@sebastienros and @mihail-brinza, RenderStatement, FromStatement and other force adding ".liquid" before searching for the file in the FS.

if (!relativePath.EndsWith(ViewExtension, StringComparison.OrdinalIgnoreCase))
{
    relativePath += ViewExtension;
}

...

var fileProvider = context.Options.FileProvider;

var fileInfo = fileProvider.GetFileInfo(relativePath);

I would suggest make ViewExtension and option TemplateOptions

@brmassa
Copy link
Author

brmassa commented Dec 16, 2024

@mihail-brinza, as a workaround, it reverts the ".liquid"

/// <summary>
/// Same as PhysicalFileProvider, but corrects bug on Fluid that
/// add ".liquid" extension on every render/from call
/// </summary>
public class LiquidPhysicalFileProvider : PhysicalFileProvider, IFileProvider
{
    /// <summary>
    /// ctr
    /// </summary>
    /// <param name="root"></param>
    public LiquidPhysicalFileProvider(string root) : base(root) { }

    /// <summary>
    /// Remove the ".liquid" extenstion
    /// </summary>
    /// <param name="subpath"></param>
    /// <returns></returns>
    public IFileInfo GetFileInfo(string subpath)
    {
        subpath = System.IO.Path.ChangeExtension(subpath, null);
        return base.GetFileInfo(subpath);
    }
}

Then use:

TemplateOptions.FileProvider = new LiquidPhysicalFileProvider(root);

@sebastienros
Copy link
Owner

@brmassa What about a DefaultLiquidExtension property set to .liquid that would be used if the specific file is not found. This wouldn't break the current behavior.

A concern I have is for security reasons, where one could request a file that is not liquid... The .liquid helping limit what types of files can be read.

@brmassa
Copy link
Author

brmassa commented Dec 17, 2024

Changing the default value extension value would require the c# configuration, so, deliberate option from the dev.

(For backward compatibility, it should be set ".liquid" by default)

Liquid could be implemented for any text output. Html, xnl, markdown, Json, etc... By having partials as "myfile.json", any IDE can properly highlight and parse it as Json instead "myfile.json.liquid"

Also, I don't see much risk on inputting an arbitrary file. File extensions don't prevent anything. Fluid, of course, must check if it's a valid txt file, but I guess it it's done now anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants