Add support for naming a page (#1204)

This commit is contained in:
Pranav K 2017-04-11 10:10:45 -07:00 committed by GitHub
parent 69b019ebd8
commit e2267f54a6
3 changed files with 175 additions and 10 deletions

View File

@ -1,27 +1,40 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public static class PageDirective
public class PageDirective
{
public static readonly DirectiveDescriptor DirectiveDescriptor = DirectiveDescriptorBuilder
.Create("page")
.BeginOptionals()
.AddString()
.AddString() // Route template
.AddString() // Page Name
.Build();
private PageDirective(string routeTemplate, string pageName)
{
RouteTemplate = routeTemplate;
PageName = pageName;
}
public string RouteTemplate { get; }
public string PageName { get; }
public static IRazorEngineBuilder Register(IRazorEngineBuilder builder)
{
builder.AddDirective(DirectiveDescriptor);
return builder;
}
public static bool TryGetRouteTemplate(DocumentIRNode irDocument, out string routeTemplate)
public static bool TryGetPageDirective(DocumentIRNode irDocument, out PageDirective pageDirective)
{
var visitor = new Visitor();
for (var i = 0; i < irDocument.Children.Count; i++)
@ -29,22 +42,46 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
visitor.Visit(irDocument.Children[i]);
}
routeTemplate = visitor.RouteTemplate;
return visitor.DirectiveNode != null;
if (visitor.DirectiveNode == null)
{
pageDirective = null;
return false;
}
var tokens = visitor.DirectiveNode.Tokens.ToList();
string routeTemplate = null;
string pageName = null;
if (tokens.Count > 0)
{
routeTemplate = TrimQuotes(tokens[0].Content);
}
if (tokens.Count > 1)
{
pageName = TrimQuotes(tokens[1].Content);
}
pageDirective = new PageDirective(routeTemplate, pageName);
return true;
}
private static string TrimQuotes(string content)
{
Debug.Assert(content.StartsWith("\"", StringComparison.Ordinal));
Debug.Assert(content.EndsWith("\"", StringComparison.Ordinal));
return content.Substring(1, content.Length - 2);
}
private class Visitor : RazorIRNodeWalker
{
public DirectiveIRNode DirectiveNode { get; private set; }
public string RouteTemplate { get; private set; }
public override void VisitDirective(DirectiveIRNode node)
{
if (node.Descriptor == DirectiveDescriptor)
{
DirectiveNode = node;
RouteTemplate = node.Tokens.FirstOrDefault()?.Content;
}
}
}

View File

@ -15,8 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIRNode irDocument)
{
string routePrefix;
return PageDirective.TryGetRouteTemplate(irDocument, out routePrefix);
return PageDirective.TryGetPageDirective(irDocument, out var directive);
}
protected override void OnDocumentStructureCreated(

View File

@ -0,0 +1,129 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
{
public class PageDirectiveTest
{
[Fact]
public void TryGetPageDirective_ReturnsFalse_IfPageDoesNotHaveDirective()
{
// Arrange
var content = "Hello world";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.False(result);
Assert.Null(pageDirective);
}
[Fact(Skip = "https://github.com/aspnet/Razor/issues/1201")]
public void TryGetPageDirective_ReturnsFalse_IfPageDoesStartWithDirective()
{
// Arrange
var content = "Hello @page";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.False(result);
Assert.Null(pageDirective);
}
[Fact]
public void TryGetPageDirective_ReturnsTrue_IfContentHasDirective()
{
// Arrange
var content = "@page";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.True(result);
Assert.Null(pageDirective.RouteTemplate);
Assert.Null(pageDirective.PageName);
}
[Fact]
public void TryGetPageDirective_ParsesRouteTemplate()
{
// Arrange
var content = "@page \"some-route-template\"";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.True(result);
Assert.Equal("some-route-template", pageDirective.RouteTemplate);
Assert.Null(pageDirective.PageName);
}
[Fact]
public void TryGetPageDirective_ParsesPageName()
{
// Arrange
var content = "@page \"some-route\" \"some name\"";
var sourceDocument = RazorSourceDocument.Create(content, "file");
var codeDocument = RazorCodeDocument.Create(sourceDocument);
var engine = CreateEngine();
var irDocument = CreateIRDocument(engine, codeDocument);
// Act
var result = PageDirective.TryGetPageDirective(irDocument, out var pageDirective);
// Assert
Assert.True(result);
Assert.Equal("some-route", pageDirective.RouteTemplate);
Assert.Equal("some name", pageDirective.PageName);
}
private RazorEngine CreateEngine()
{
return RazorEngine.Create(b =>
{
PageDirective.Register(b);
});
}
private DocumentIRNode CreateIRDocument(RazorEngine engine, RazorCodeDocument codeDocument)
{
for (var i = 0; i < engine.Phases.Count; i++)
{
var phase = engine.Phases[i];
phase.Execute(codeDocument);
if (phase is IRazorDocumentClassifierPhase)
{
break;
}
}
return codeDocument.GetIRDocument();
}
}
}