Skip to content

JavaScript Collocation TagHelper #42

Description

@khalidabuhakmeh

This is in reference to a .NET 6 feature known as JavaScript collocation. https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/?view=aspnetcore-6.0#load-a-script-from-an-external-javascript-file-js-collocated-with-a-component

I wanted to submit a PR but noticed you are multi-targeting .NET 3.1 and .NET 4.7.1 with this package. Seeing that JavaScript collocation is part of .NET 6 I'm not sure what to do. In any case, I've included the code below in the chance you'd like to add it to your library.

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.FileProviders;

public class ViewScriptTagHelper : TagHelper
{
    private readonly IWebHostEnvironment environment;
    private readonly IFileVersionProvider fileVersionProvider;
    private const string AppendVersionAttributeName = "append-version";

    public ViewScriptTagHelper(IWebHostEnvironment environment, IFileVersionProvider fileVersionProvider)
    {
        this.environment = environment;
        this.fileVersionProvider = fileVersionProvider;
    }

    [ViewContext] 
    public ViewContext? ViewContext { get; set; }
    
    /// <summary>
    /// Value indicating if file version should be appended to src urls.
    /// </summary>
    /// <remarks>
    /// A query string "v" with the encoded content of the file is added.
    /// </remarks>
    [HtmlAttributeName(AppendVersionAttributeName)]
    public bool? AppendVersion { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        // remove the `page-script` tag if script doesn't exist
        output.TagName = null;
        output.TagMode = TagMode.StartTagAndEndTag;

        var viewPath = ViewContext?.View.Path;
        var src = $"{viewPath}.js";
        
        /* When the app is published, the framework automatically moves the script to the web root.
           So we should check both places, with the content root first for development */
        var exists = environment.ContentRootFileProvider.GetFileInfo(src).Exists ||
                   environment.WebRootFileProvider.GetFileInfo(src).Exists;

        if (exists)
        {
            // switch it to script now
            output.TagName = "script";
            output.Content = new DefaultTagHelperContent();
            
            if (AppendVersion == true)
            {
                // people love their cache busting versions
                src = fileVersionProvider.AddFileVersionToPath(src, src);
            }
            
            output.Attributes.Add("src", src);
        }
    }
}

Usage

Add the following to the end of your _Layout.cshtml file.

<view-script append-version="true" />

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions