diff --git a/visual-studio/source/GitWebLinks/GitWebLinks.csproj b/visual-studio/source/GitWebLinks/GitWebLinks.csproj index f282f50..72d5f8c 100644 --- a/visual-studio/source/GitWebLinks/GitWebLinks.csproj +++ b/visual-studio/source/GitWebLinks/GitWebLinks.csproj @@ -227,8 +227,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - 2.2.692 + + 2.12.0 compile; build; native; contentfiles; analyzers; buildtransitive diff --git a/visual-studio/source/GitWebLinks/Services/DefinitionProvider.cs b/visual-studio/source/GitWebLinks/Services/DefinitionProvider.cs index b67363f..0228111 100644 --- a/visual-studio/source/GitWebLinks/Services/DefinitionProvider.cs +++ b/visual-studio/source/GitWebLinks/Services/DefinitionProvider.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -28,15 +28,17 @@ public static IReadOnlyCollection GetDefinitions() { if (_definitions is null) { Assembly container; List definitions; + FluidParser parser; definitions = new List(); container = typeof(LinkHandlerProvider).Assembly; + parser = new FluidParser(); foreach (string name in container.GetManifestResourceNames()) { if (Path.GetExtension(name) == ".json") { using (Stream stream = container.GetManifestResourceStream(name)) { - definitions.Add(LoadDefinition(stream)); + definitions.Add(LoadDefinition(stream, parser)); } } } @@ -48,7 +50,7 @@ public static IReadOnlyCollection GetDefinitions() { } - private static HandlerDefinition LoadDefinition(Stream stream) { + private static HandlerDefinition LoadDefinition(Stream stream, FluidParser parser) { JsonHandlerDefinition? json; @@ -65,10 +67,10 @@ private static HandlerDefinition LoadDefinition(Stream stream) { json.Name, json.BranchRef, json.SettingsKeys ?? Array.Empty(), - Template.Parse(json.Url), + parser.Parse(json.Url), json.Query is not null ? ParseQueryModifications(json.Query) : Array.Empty(), - Template.Parse(json.Selection), - ParseReverseSettings(json.Reverse), + parser.Parse(json.Selection), + ParseReverseSettings(json.Reverse, parser), json.Private ); @@ -77,17 +79,17 @@ private static HandlerDefinition LoadDefinition(Stream stream) { json.Name, json.BranchRef, json.SettingsKeys ?? Array.Empty(), - Template.Parse(json.Url), + parser.Parse(json.Url), json.Query is not null ? ParseQueryModifications(json.Query) : Array.Empty(), - Template.Parse(json.Selection), - ParseReverseSettings(json.Reverse), - ParseServers(json.Server!) + parser.Parse(json.Selection), + ParseReverseSettings(json.Reverse, parser), + ParseServers(json.Server!, parser) ); } } - private static IReadOnlyList ParseServers(IReadOnlyList json) { + private static IReadOnlyList ParseServers(IReadOnlyList json, FluidParser parser) { List servers; @@ -98,10 +100,10 @@ private static IReadOnlyList ParseServers(IReadOnlyList jso servers.Add( new DynamicServer( new Regex(server.RemotePattern), - Template.Parse(server.Http), - Template.Parse(server.Ssh), + parser.Parse(server.Http), + parser.Parse(server.Ssh), (server.WebPattern is not null) ? new Regex(server.WebPattern) : null, - (server.Web is not null) ? Template.Parse(server.Web) : null + (server.Web is not null) ? parser.Parse(server.Web) : null ) ); } else { @@ -118,21 +120,21 @@ private static IReadOnlyList ParseQueryModifications(IReadOnl } - private static ReverseSettings ParseReverseSettings(JsonReverseSettings json) { + private static ReverseSettings ParseReverseSettings(JsonReverseSettings json, FluidParser parser) { return new ReverseSettings( new Regex(json.Pattern), - Template.Parse(json.File), + parser.Parse(json.File), json.FileMayStartWithBranch, new ReverseServerSettings( - Template.Parse(json.Server.Http), - Template.Parse(json.Server.Ssh), - (json.Server.Web is not null) ? Template.Parse(json.Server.Web) : null + parser.Parse(json.Server.Http), + parser.Parse(json.Server.Ssh), + (json.Server.Web is not null) ? parser.Parse(json.Server.Web) : null ), new ReverseSelectionSettings( - Template.Parse(json.Selection.StartLine), - json.Selection.StartColumn is not null ? Template.Parse(json.Selection.StartColumn) : null, - json.Selection.EndLine is not null ? Template.Parse(json.Selection.EndLine) : null, - json.Selection.EndColumn is not null ? Template.Parse(json.Selection.EndColumn) : null + parser.Parse(json.Selection.StartLine), + json.Selection.StartColumn is not null ? parser.Parse(json.Selection.StartColumn) : null, + json.Selection.EndLine is not null ? parser.Parse(json.Selection.EndLine) : null, + json.Selection.EndColumn is not null ? parser.Parse(json.Selection.EndColumn) : null ) ); } diff --git a/visual-studio/source/GitWebLinks/Services/LinkHandler.cs b/visual-studio/source/GitWebLinks/Services/LinkHandler.cs index 937ef85..35bb4da 100644 --- a/visual-studio/source/GitWebLinks/Services/LinkHandler.cs +++ b/visual-studio/source/GitWebLinks/Services/LinkHandler.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using Microsoft.VisualStudio; using System; using System.Collections.Generic; @@ -57,7 +57,7 @@ public async Task CreateUrlAsync(Repository repository, FileInf string relativePath; string selection; TemplateData data; - Hash hash; + TemplateContext context; // If a link type wasn't specified, then we'll use @@ -111,11 +111,11 @@ public async Task CreateUrlAsync(Repository repository, FileInf data.Add(key, await _settings.GetHandlerSettingAsync(key)); } - hash = data.ToHash(); - url = _definition.Url.Render(hash); + context = data.AsTemplateContext(); + url = _definition.Url.Render(context); if (file.Selection is not null) { - selection = _definition.Selection.Render(hash); + selection = _definition.Selection.Render(context); url += selection; } else { selection = ""; @@ -472,33 +472,33 @@ private static bool TryGetFinalPathNameByHandle(IntPtr handle, int bufferSize, o match = _definition.Reverse.Pattern.Match(webUrl); if (match.Success) { - Hash hash; + TemplateContext context; string file; StaticServer server; PartialSelectedRange? selection; - hash = TemplateData + context = TemplateData .Create() .Add("http", address?.Http) .Add("ssh", address?.Ssh) .Add("web", address?.Web) .Add(match) - .ToHash(); + .AsTemplateContext(); - file = _definition.Reverse.File.Render(hash); + file = _definition.Reverse.File.Render(context); server = new StaticServer( - _definition.Reverse.Server.Http.Render(hash), - _definition.Reverse.Server.Ssh.Render(hash), - _definition.Reverse.Server.Web?.Render(hash) + _definition.Reverse.Server.Http.Render(context), + _definition.Reverse.Server.Ssh.Render(context), + _definition.Reverse.Server.Web?.Render(context) ); selection = new PartialSelectedRange( - TryParseNumber(_definition.Reverse.Selection.StartLine.Render(hash)), - TryParseNumber(_definition.Reverse.Selection.StartColumn?.Render(hash)), - TryParseNumber(_definition.Reverse.Selection.EndLine?.Render(hash)), - TryParseNumber(_definition.Reverse.Selection.EndColumn?.Render(hash)) + TryParseNumber(_definition.Reverse.Selection.StartLine.Render(context)), + TryParseNumber(_definition.Reverse.Selection.StartColumn?.Render(context)), + TryParseNumber(_definition.Reverse.Selection.EndLine?.Render(context)), + TryParseNumber(_definition.Reverse.Selection.EndColumn?.Render(context)) ); return new UrlInfo(file, server, selection); diff --git a/visual-studio/source/GitWebLinks/Services/TemplateData.cs b/visual-studio/source/GitWebLinks/Services/TemplateData.cs index 56751fd..d24426f 100644 --- a/visual-studio/source/GitWebLinks/Services/TemplateData.cs +++ b/visual-studio/source/GitWebLinks/Services/TemplateData.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; @@ -9,7 +9,7 @@ namespace GitWebLinks; public class TemplateData { - private readonly Dictionary _data = new(); + private readonly TemplateContext _context = new(TemplateEngine.Options); public static TemplateData Create() { @@ -21,7 +21,7 @@ private TemplateData() { } public TemplateData Add(string key, object? value) { - _data[key] = value; + _context.SetValue(key, value); return this; } @@ -42,18 +42,18 @@ public TemplateData Add(Match match) { } matchData["groups"] = groupsData; - _data["match"] = matchData; + _context.SetValue("match", matchData); } else { - _data["match"] = match.Groups.OfType().Select((x) => x.Success ? x.Value : null).ToArray(); + _context.SetValue("match", match.Groups.OfType().Select((x) => x.Success ? x.Value : null).ToArray()); } return this; } - public Hash ToHash() { - return Hash.FromDictionary(_data); + public TemplateContext AsTemplateContext() { + return _context; } } diff --git a/visual-studio/source/GitWebLinks/Services/TemplateEngine.cs b/visual-studio/source/GitWebLinks/Services/TemplateEngine.cs index 567d2b2..05cae85 100644 --- a/visual-studio/source/GitWebLinks/Services/TemplateEngine.cs +++ b/visual-studio/source/GitWebLinks/Services/TemplateEngine.cs @@ -1,10 +1,11 @@ #nullable enable -using DotLiquid; +using Fluid; +using Fluid.Values; using System; using System.IO; using System.Linq; -using System.Text.RegularExpressions; +using System.Threading.Tasks; namespace GitWebLinks; @@ -13,9 +14,18 @@ public static class TemplateEngine { private static bool _initialized; + public static TemplateOptions Options = new(); + + public static void Initialize() { if (!_initialized) { - Template.RegisterFilter(typeof(Filters)); + Options.Filters.AddFilter("filename", Filters.FilenameAsync); + Options.Filters.AddFilter("encode_uri", Filters.EncodeUriAsync); + Options.Filters.AddFilter("encode_uri_component", Filters.EncodeUriComponentAsync); + Options.Filters.AddFilter("encode_uri_component_segments", Filters.EncodeUriComponentSegmentsAsync); + Options.Filters.AddFilter("decode_uri", Filters.DecodeUriAsync); + Options.Filters.AddFilter("decode_uri_component", Filters.DecodeUriComponentAsync); + Options.Filters.AddFilter("decode_uri_component_segments", Filters.DecodeUriComponentSegmentsAsync); _initialized = true; } } @@ -23,38 +33,70 @@ public static void Initialize() { private class Filters { - public static string Filename(string value) { - return Path.GetFileName(value); + public static ValueTask FilenameAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create(Path.GetFileName(value.ToStringValue())); } - public static string EncodeUri(string value) { - return Uri.EscapeUriString(value); + public static ValueTask EncodeUriAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create(Uri.EscapeUriString(value.ToStringValue())); } - public static string EncodeUriComponent(string value) { - return Uri.EscapeDataString(value); + public static ValueTask EncodeUriComponentAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create(Uri.EscapeDataString(value.ToStringValue())); } - public static string EncodeUriComponentSegments(string value) { - return string.Join("/", value.Split('/').Select(Uri.EscapeDataString)); + public static ValueTask EncodeUriComponentSegmentsAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create( + string.Join("/", value.ToStringValue().Split('/').Select(Uri.EscapeDataString)) + ); } - public static string DecodeUri(string value) { - return Uri.UnescapeDataString(value); + public static ValueTask DecodeUriAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create(Uri.UnescapeDataString(value.ToStringValue())); } - public static string DecodeUriComponent(string value) { - return Uri.UnescapeDataString(value); + public static ValueTask DecodeUriComponentAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create(Uri.UnescapeDataString(value.ToStringValue())); } - public static string DecodeUriComponentSegments(string value) { - return string.Join("/", value.Split('/').Select(Uri.UnescapeDataString)); + public static ValueTask DecodeUriComponentSegmentsAsync( + FluidValue value, + FilterArguments arguments, + TemplateContext context + ) { + return StringValue.Create( + string.Join("/", value.ToStringValue().Split('/').Select(Uri.UnescapeDataString)) + ); } } diff --git a/visual-studio/source/GitWebLinks/Types/DynamicServer.cs b/visual-studio/source/GitWebLinks/Types/DynamicServer.cs index 9c0056f..9651356 100644 --- a/visual-studio/source/GitWebLinks/Types/DynamicServer.cs +++ b/visual-studio/source/GitWebLinks/Types/DynamicServer.cs @@ -1,13 +1,19 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Text.RegularExpressions; namespace GitWebLinks; public class DynamicServer : IServer { - public DynamicServer(Regex remotePattern, Template http, Template ssh, Regex? webPattern, Template? web) { + public DynamicServer( + Regex remotePattern, + IFluidTemplate http, + IFluidTemplate ssh, + Regex? webPattern, + IFluidTemplate? web + ) { RemotePattern = remotePattern; Http = http; Ssh = ssh; @@ -19,15 +25,15 @@ public DynamicServer(Regex remotePattern, Template http, Template ssh, Regex? we public Regex RemotePattern { get; } - public Template Http { get; } + public IFluidTemplate Http { get; } - public Template Ssh { get; } + public IFluidTemplate Ssh { get; } public Regex? WebPattern { get; } - public Template? Web { get; } + public IFluidTemplate? Web { get; } } diff --git a/visual-studio/source/GitWebLinks/Types/HandlerDefinition.cs b/visual-studio/source/GitWebLinks/Types/HandlerDefinition.cs index 28bf620..46ebd93 100644 --- a/visual-studio/source/GitWebLinks/Types/HandlerDefinition.cs +++ b/visual-studio/source/GitWebLinks/Types/HandlerDefinition.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Collections.Generic; namespace GitWebLinks; @@ -11,9 +11,9 @@ public HandlerDefinition( string name, BranchRefType branchRef, IReadOnlyList settingsKeys, - Template url, + IFluidTemplate url, IReadOnlyList query, - Template selection, + IFluidTemplate selection, ReverseSettings reverse ) { Name = name; @@ -35,13 +35,13 @@ ReverseSettings reverse public IReadOnlyList SettingsKeys { get; } - public Template Url { get; } + public IFluidTemplate Url { get; } public IReadOnlyList Query { get; } - public Template Selection { get; } + public IFluidTemplate Selection { get; } public ReverseSettings Reverse { get; } diff --git a/visual-studio/source/GitWebLinks/Types/PrivateHandlerDefinition.cs b/visual-studio/source/GitWebLinks/Types/PrivateHandlerDefinition.cs index 9a113ce..41dce46 100644 --- a/visual-studio/source/GitWebLinks/Types/PrivateHandlerDefinition.cs +++ b/visual-studio/source/GitWebLinks/Types/PrivateHandlerDefinition.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Collections.Generic; namespace GitWebLinks; @@ -11,9 +11,9 @@ public PrivateHandlerDefinition( string name, BranchRefType branchRef, IReadOnlyList settingsKeys, - Template url, + IFluidTemplate url, IReadOnlyList query, - Template selection, + IFluidTemplate selection, ReverseSettings reverse, string serverSettingsKey ) : base(name, branchRef, settingsKeys, url, query, selection, reverse) { diff --git a/visual-studio/source/GitWebLinks/Types/PublicHandlerDefinition.cs b/visual-studio/source/GitWebLinks/Types/PublicHandlerDefinition.cs index 43a0e83..ce1e0f8 100644 --- a/visual-studio/source/GitWebLinks/Types/PublicHandlerDefinition.cs +++ b/visual-studio/source/GitWebLinks/Types/PublicHandlerDefinition.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Collections.Generic; namespace GitWebLinks; @@ -11,9 +11,9 @@ public PublicHandlerDefinition( string name, BranchRefType branchRef, IReadOnlyList settingsKeys, - Template url, + IFluidTemplate url, IReadOnlyList query, - Template selection, + IFluidTemplate selection, ReverseSettings reverse, IReadOnlyList servers ) : base(name, branchRef, settingsKeys, url, query, selection, reverse) { diff --git a/visual-studio/source/GitWebLinks/Types/RemoteServer.cs b/visual-studio/source/GitWebLinks/Types/RemoteServer.cs index 59d7557..4f532b9 100644 --- a/visual-studio/source/GitWebLinks/Types/RemoteServer.cs +++ b/visual-studio/source/GitWebLinks/Types/RemoteServer.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System; using System.Collections.Generic; using System.Linq; @@ -53,17 +53,17 @@ UrlMatcher Create(Regex pattern) { match = pattern.Match(url); if (match.Success) { - Hash hash; + TemplateContext context; // The URL matched the pattern. Render the templates to get the HTTP // and SSH URLs, making the match available for the templates to use. - hash = TemplateData.Create().Add(match).ToHash(); + context = TemplateData.Create().Add(match).AsTemplateContext(); result = new StaticServer( - server.Http.Render(hash), - server.Ssh.Render(hash), - server.Web?.Render(hash) + server.Http.Render(context), + server.Ssh.Render(context), + server.Web?.Render(context) ); } else { diff --git a/visual-studio/source/GitWebLinks/Types/ReverseSelectionSettings.cs b/visual-studio/source/GitWebLinks/Types/ReverseSelectionSettings.cs index 0ffe77d..f74d9b0 100644 --- a/visual-studio/source/GitWebLinks/Types/ReverseSelectionSettings.cs +++ b/visual-studio/source/GitWebLinks/Types/ReverseSelectionSettings.cs @@ -1,12 +1,17 @@ #nullable enable -using DotLiquid; +using Fluid; namespace GitWebLinks; public class ReverseSelectionSettings { - public ReverseSelectionSettings(Template startLine, Template? startColumn, Template? endLine, Template? endColumn) { + public ReverseSelectionSettings( + IFluidTemplate startLine, + IFluidTemplate? startColumn, + IFluidTemplate? endLine, + IFluidTemplate? endColumn + ) { StartLine = startLine; StartColumn = startColumn; EndLine = endLine; @@ -14,15 +19,15 @@ public ReverseSelectionSettings(Template startLine, Template? startColumn, Templ } - public Template StartLine { get; } + public IFluidTemplate StartLine { get; } - public Template? StartColumn { get; } + public IFluidTemplate? StartColumn { get; } - public Template? EndLine { get; } + public IFluidTemplate? EndLine { get; } - public Template? EndColumn { get; } + public IFluidTemplate? EndColumn { get; } } diff --git a/visual-studio/source/GitWebLinks/Types/ReverseServerSettings.cs b/visual-studio/source/GitWebLinks/Types/ReverseServerSettings.cs index 7739188..ae9b170 100644 --- a/visual-studio/source/GitWebLinks/Types/ReverseServerSettings.cs +++ b/visual-studio/source/GitWebLinks/Types/ReverseServerSettings.cs @@ -1,24 +1,24 @@ #nullable enable -using DotLiquid; +using Fluid; namespace GitWebLinks; public class ReverseServerSettings { - public ReverseServerSettings(Template http, Template ssh, Template? web) { + public ReverseServerSettings(IFluidTemplate http, IFluidTemplate ssh, IFluidTemplate? web) { Http = http; Ssh = ssh; Web = web; } - public Template Http { get; } + public IFluidTemplate Http { get; } - public Template Ssh { get; } + public IFluidTemplate Ssh { get; } - public Template? Web { get; } + public IFluidTemplate? Web { get; } } diff --git a/visual-studio/source/GitWebLinks/Types/ReverseSettings.cs b/visual-studio/source/GitWebLinks/Types/ReverseSettings.cs index 31f406c..665cef7 100644 --- a/visual-studio/source/GitWebLinks/Types/ReverseSettings.cs +++ b/visual-studio/source/GitWebLinks/Types/ReverseSettings.cs @@ -1,6 +1,6 @@ #nullable enable -using DotLiquid; +using Fluid; using System.Text.RegularExpressions; namespace GitWebLinks; @@ -9,7 +9,7 @@ public class ReverseSettings { public ReverseSettings( Regex pattern, - Template file, + IFluidTemplate file, bool fileMayStartWithBranch, ReverseServerSettings server, ReverseSelectionSettings selection @@ -25,7 +25,7 @@ ReverseSelectionSettings selection public Regex Pattern { get; } - public Template File { get; } + public IFluidTemplate File { get; } public bool FileMayStartWithBranch { get; } diff --git a/visual-studio/tests/GitWebLinks.UnitTests/Handlers/HandlerTests.cs b/visual-studio/tests/GitWebLinks.UnitTests/Handlers/HandlerTests.cs index ce4edee..43c5b28 100644 --- a/visual-studio/tests/GitWebLinks.UnitTests/Handlers/HandlerTests.cs +++ b/visual-studio/tests/GitWebLinks.UnitTests/Handlers/HandlerTests.cs @@ -1,4 +1,4 @@ -using DotLiquid; +using Fluid; using Newtonsoft.Json.Linq; using NSubstitute; @@ -520,11 +520,11 @@ protected async Task PrepareTestAsync(Dictionary? settin // Treat the test URL as a template and allow // the current commit hash to be used in the result. - return Template.Parse(url).Render( + return new FluidParser().Parse(url).Render( TemplateData .Create() .Add("commit", string.Concat(await Git.ExecuteAsync(_repositoryRoot, "rev-parse", "HEAD")).Trim()) - .ToHash() + .AsTemplateContext() ); } diff --git a/visual-studio/tests/GitWebLinks.UnitTests/Services/LinkHandlerTests.cs b/visual-studio/tests/GitWebLinks.UnitTests/Services/LinkHandlerTests.cs index a54c196..ceb92e5 100644 --- a/visual-studio/tests/GitWebLinks.UnitTests/Services/LinkHandlerTests.cs +++ b/visual-studio/tests/GitWebLinks.UnitTests/Services/LinkHandlerTests.cs @@ -1,4 +1,4 @@ -using DotLiquid; +using Fluid; using NSubstitute; using System.Text.RegularExpressions; @@ -6,7 +6,8 @@ namespace GitWebLinks; public static class LinkHandlerTests { - private static readonly Template EmptyTemplate = Template.Parse(""); + private static readonly FluidParser Parser = new(); + private static readonly IFluidTemplate EmptyTemplate = Parser.Parse(""); public class CreateUrlAsyncMethod : RepositoryTestBase { @@ -647,7 +648,7 @@ private LinkHandler CreateHandler(PartialHandlerDefinition definition) { "Test", definition.BranchRef ?? BranchRefType.Abbreviated, Array.Empty(), - Template.Parse(definition.Url ?? ""), + Parser.Parse(definition.Url ?? ""), definition.Query ?? Array.Empty(), EmptyTemplate, new ReverseSettings( @@ -741,15 +742,15 @@ await GetUrlInfoAsync( Pattern = "http://example\\.com/[^/]+/(?.+)", File = "{{ match.groups.file }}", Server = new ReverseServerSettings( - Template.Parse("http"), - Template.Parse("ssh"), + Parser.Parse("http"), + Parser.Parse("ssh"), null ), Selection = new ReverseSelectionSettings( - Template.Parse("10"), - Template.Parse("20"), - Template.Parse("30"), - Template.Parse("40") + Parser.Parse("10"), + Parser.Parse("20"), + Parser.Parse("30"), + Parser.Parse("40") ) }, "http://example.com/foo/bar.txt", @@ -773,14 +774,14 @@ await GetUrlInfoAsync( Pattern = "http://example\\.com/[^/]+/(?.+)", File = "{{ match.groups.file }}", Server = new ReverseServerSettings( - Template.Parse("http"), - Template.Parse("ssh"), + Parser.Parse("http"), + Parser.Parse("ssh"), null ), Selection = new ReverseSelectionSettings( - Template.Parse("10"), - Template.Parse("x"), - Template.Parse(""), + Parser.Parse("10"), + Parser.Parse("x"), + Parser.Parse(""), null ) }, @@ -804,8 +805,8 @@ await GetUrlInfoAsync( new PartialReverseSettings { Pattern = "http://example\\.com/.+", Server = new ReverseServerSettings( - Template.Parse("{{ http }}"), - Template.Parse("{{ ssh }}"), + Parser.Parse("{{ http }}"), + Parser.Parse("{{ ssh }}"), null ) }, @@ -835,9 +836,9 @@ await GetUrlInfoAsync( new PartialReverseSettings { Pattern = "http://(web\\.)?example\\.com/.+", Server = new ReverseServerSettings( - Template.Parse("{{ http }}"), - Template.Parse("{{ ssh }}"), - Template.Parse("{{ web }}") + Parser.Parse("{{ http }}"), + Parser.Parse("{{ ssh }}"), + Parser.Parse("{{ web }}") ) }, "http://web.example.com/foo/bar.txt", @@ -864,7 +865,7 @@ private LinkHandler CreateHandler(PartialReverseSettings reverse) { EmptyTemplate, new ReverseSettings( new Regex(reverse.Pattern ?? ""), - Template.Parse(reverse.File ?? ""), + Parser.Parse(reverse.File ?? ""), false, reverse.Server ?? new ReverseServerSettings(EmptyTemplate, EmptyTemplate, null), reverse.Selection ?? new ReverseSelectionSettings(EmptyTemplate, null, null, null) diff --git a/visual-studio/tests/GitWebLinks.UnitTests/Services/TemplateEngineTests.cs b/visual-studio/tests/GitWebLinks.UnitTests/Services/TemplateEngineTests.cs index e9dc6f7..6f5088a 100644 --- a/visual-studio/tests/GitWebLinks.UnitTests/Services/TemplateEngineTests.cs +++ b/visual-studio/tests/GitWebLinks.UnitTests/Services/TemplateEngineTests.cs @@ -1,4 +1,4 @@ -using DotLiquid; +using Fluid; using System.Text.RegularExpressions; namespace GitWebLinks; @@ -14,7 +14,7 @@ static TemplateEngineTests() { public void CanRenderBasicTemplate() { Assert.Equal( "Hello world!", - Render("Hello {{ name }}!", Hash.FromAnonymousObject(new { name = "world" })) + Render("Hello {{ name }}!", TemplateData.Create().Add("name", "world")) ); } @@ -25,7 +25,7 @@ public void CanRenderTemplateWithRegexMatches() { "Hello there, Bob!", Render( "Hello {{ match[1] }}, {{ match[2] }}!", - TemplateData.Create().Add(Regex.Match("there once was a man named Bob", @"^(\w+)\s.+\s(\w+)$")).ToHash() + TemplateData.Create().Add(Regex.Match("there once was a man named Bob", @"^(\w+)\s.+\s(\w+)$")) ) ); } @@ -37,7 +37,7 @@ public void CanRenderTemplateWithRegexGroups() { "Hello there, Bob!", Render( "Hello {{ match.groups.greeting }}, {{ match.groups.name }}!", - TemplateData.Create().Add(Regex.Match("there once was a man named Bob", @"^(?\w+)\s.+\s(?\w+)$")).ToHash() + TemplateData.Create().Add(Regex.Match("there once was a man named Bob", @"^(?\w+)\s.+\s(?\w+)$")) ) ); } @@ -106,8 +106,8 @@ public void Filename() { } - private static string Render(string template, Hash? hash = null) { - return Template.Parse(template).Render(hash ?? Hash.FromAnonymousObject(new object())); + private static string Render(string template, TemplateData? data = null) { + return new FluidParser().Parse(template).Render((data ?? TemplateData.Create()).AsTemplateContext()); } } diff --git a/visual-studio/tests/GitWebLinks.UnitTests/Types/RemoteServerTests.cs b/visual-studio/tests/GitWebLinks.UnitTests/Types/RemoteServerTests.cs index eea8211..90991d9 100644 --- a/visual-studio/tests/GitWebLinks.UnitTests/Types/RemoteServerTests.cs +++ b/visual-studio/tests/GitWebLinks.UnitTests/Types/RemoteServerTests.cs @@ -1,4 +1,4 @@ -using DotLiquid; +using Fluid; using System.Text.RegularExpressions; namespace GitWebLinks; @@ -188,8 +188,8 @@ public SingleDynamicServer() : base( new RemoteServer( new DynamicServer( new Regex("http://(.+)\\.example\\.com:8000"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), null, null ) @@ -217,10 +217,10 @@ public async Task ShouldMatchTheWebAddressWhenThereIsAWebAddress() { Server = new RemoteServer( new DynamicServer( new Regex("http://(.+)\\.example\\.com:8000"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), new Regex("http://(.+)\\.test\\.com:8000"), - Template.Parse("http://test.com:8000/repos/{{ match[1] }}") + Parser.Parse("http://test.com:8000/repos/{{ match[1] }}") ) ); @@ -245,15 +245,15 @@ public MultipleDynamicServers() : base( new IServer[] { new DynamicServer( new Regex("http://(.+)\\.example\\.com:8000"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), null, null ), new DynamicServer( new Regex("ssh://git@example\\.com:9000/_([^/]+)"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), new Regex("^$"), // This server should only match SSH remote URLs. null ) @@ -290,17 +290,17 @@ public async Task ShouldMatchTheWebAddressWhenThereIsAWebAddress() { new IServer[] { new DynamicServer( new Regex("http://(.+)\\.example\\.com:8000"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), new Regex("http://(.+)\\.test\\.com:8000"), - Template.Parse("http://test.com:8000/repos/{{ match[1] }}") + Parser.Parse("http://test.com:8000/repos/{{ match[1] }}") ), new DynamicServer( new Regex("ssh://git@example\\.com:9000/_([^/]+)"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), new Regex("http://(.+)\\.other\\.com:8000"), - Template.Parse("http://other.com:8000/repos/{{ match[1] }}") + Parser.Parse("http://other.com:8000/repos/{{ match[1] }}") ) } ); @@ -336,8 +336,8 @@ public MixedStaticAndDynamicServers() : base( new IServer[] { new DynamicServer( new Regex("http://(.+)\\.example\\.com:8000"), - Template.Parse("http://example.com:8000/repos/{{ match[1] }}"), - Template.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), + Parser.Parse("http://example.com:8000/repos/{{ match[1] }}"), + Parser.Parse("ssh://git@example.com:9000/_{{ match[1] }}"), null, null ), @@ -510,6 +510,9 @@ public int GetHashCode(StaticServer? obj) { public abstract class TestBase { + protected static readonly FluidParser Parser = new(); + + protected TestBase(RemoteServer defaultServer) { Server = defaultServer; }