예제 #1
0
        private static void RegisterServices(IServiceCollection services)
        {
            services.TryAddEnumerable(ServiceDescriptor.Singleton <IActionDescriptorProvider, PageActionDescriptorProvider>());
            services.TryAddEnumerable(ServiceDescriptor.Singleton <IActionInvokerProvider, PageActionInvokerProvider>());

            services.TryAddSingleton <IPageFactory, DefaultPageFactory>();
            services.TryAddSingleton <IPageActivator, DefaultPageActivator>();
            services.TryAddSingleton <IPageHandlerMethodSelector, DefaultPageHandlerMethodSelector>();

            services.TryAddSingleton <RazorProject>((s) =>
            {
                var options = s.GetRequiredService <IOptions <RazorPagesOptions> >();
                return(RazorProject.Create(new CompositeFileProvider(options.Value.FileProviders)));
            });

            services.TryAddSingleton <IPageLoader, DefaultPageLoader>();
            services.TryAddSingleton <PageRazorEngineHost>();
            services.TryAddSingleton <ReferenceManager, ApplicationPartManagerReferenceManager>();
            services.TryAddSingleton <CSharpCompilationFactory, DefaultCSharpCompilationFactory>();

            services.Replace(ServiceDescriptor.Singleton <IRazorPageActivator, HackedRazorPageActivator>()); // Awful Hack

            services.TryAddSingleton <PageArgumentBinder, DefaultPageArgumentBinder>();

            services.TryAddSingleton <PageResultExecutor>();

            services.TryAddEnumerable(ServiceDescriptor.Transient <IConfigureOptions <RazorPagesOptions>, DefaultRazorPagesOptionsSetup>());

            services.TryAddSingleton <TempDataPropertyProvider>();
        }
        static void Main(string[] args)
        {
            // customize the default engine a little bit
            var engine = RazorEngine.Create(b =>
            {
                InheritsDirective.Register(b);     // make sure the engine understand the @inherits directive in the input templates
                b.SetNamespace("MyNamespace");     // define a namespace for the Template class
                b.Build();
            });
            // points to the local path
            var project = RazorProject.Create(".");
            var te      = new RazorTemplateEngine(engine, project);
            // get a razor-templated file. My "hello.txt" template file is defined like this:
            //
            // @inherits RazorTemplate.MyTemplate
            // Hello @Model.Name, welcome to Razor World!
            //
            var item = project.GetItem("hello.txt");
            // parse and generate C# code, outputs it on the console
            var cs = te.GenerateCode(item);

            Console.WriteLine(cs.GeneratedCode);
            // now, use roslyn, parse the C# code
            var tree = CSharpSyntaxTree.ParseText(cs.GeneratedCode);
            // define the dll
            const string dllName     = "hello";
            var          compilation = CSharpCompilation.Create(dllName, new[] { tree },
                                                                new[]
예제 #3
0
        private static string GetTemplateSourceCode <T>(string templatePath, string content)
        {
            // customize the default engine a little bit
            var engine = RazorEngine.Create(engineBuilder =>
            {
                InheritsDirective.Register(engineBuilder);
                engineBuilder.SetNamespace("MyNamespace");
                engineBuilder.Build();
            });

            // points to the local path
            var project = RazorProject.Create(".");
            var te      = new RazorTemplateEngine(engine, project);

            // get a razor-templated file. My "hello.txt" template file is defined like this:
            //
            // @inherits RazorTemplate.MyTemplate
            // Hello @Model.Name, welcome to Razor World!
            //
            StringBuilder builder = new StringBuilder();

            builder.AppendLine(String.Format("@inherits Developpez.MagazineTool.TemplateManager.Template<{0}>", typeof(T).FullName));
            builder.Append(content);
            RazorSourceDocument sourceDocument = RazorSourceDocument.Create(builder.ToString(), templatePath);
            RazorCodeDocument   codeDocument   = RazorCodeDocument.Create(sourceDocument);

            // parse and generate C# code, outputs it on the console

            //var cs = te.GenerateCode(item);
            var cs = te.GenerateCode(codeDocument);

            return(cs.GeneratedCode);
        }
예제 #4
0
        internal RazorCompilerResult ToCSharpByContent(string content)
        {
            var razorEngine    = GetRazorEngine();
            var razorProject   = RazorProject.Create(BasePath);
            var projectItem    = new ContentRazorProjectItem(content);
            var templateEngine = GetTemplateEngine(razorEngine, razorProject);

            return(GetCompilerResult(templateEngine, projectItem));
        }
        static void Main(string[] args)
        {
            // customize the default engine a little bit
            var engine = RazorEngine.Create(b =>
            {
                InheritsDirective.Register(b);     // make sure the engine understand the @inherits directive in the input templates
                b.SetNamespace("MyNamespace");     // define a namespace for the Template class
                b.Build();
            });
            // points to the local path
            var project = RazorProject.Create(".");
            var te      = new RazorTemplateEngine(engine, project);
            // get a file. My file is defined like this:
            //
            // @inherits RazorTemplate.MyTemplate
            // Hello @Model.Name, welcome to Razor World!
            //
            var item = project.GetItem("hello.txt");
            // parse and generate C# code, outputs it on the console
            var cs = te.GenerateCode(item);

            Console.WriteLine(cs.GeneratedCode);
            // now, use roslyn, parse the C# code
            var tree = CSharpSyntaxTree.ParseText(cs.GeneratedCode);
            // define the dll
            const string dllName     = "hello";
            var          compilation = CSharpCompilation.Create(dllName, new[] { tree },
                                                                new[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),         // include corlib
                MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location), // this file (that contains the MyTemplate base class)
                // for some reason on .NET core, I need to add this... this is not needed with .NET framework
                MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(typeof(object).Assembly.Location), "System.Runtime.dll")),
            },
                                                                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); // we want a dll
            // compile the dll
            string path   = Path.Combine(Path.GetFullPath("."), dllName + ".dll");
            var    result = compilation.Emit(path);

            if (!result.Success)
            {
                Console.WriteLine(string.Join(Environment.NewLine, result.Diagnostics));
                return;
            }
            // load the built DLL
            Console.WriteLine(path);
            var asm = Assembly.LoadFile(path);
            // the generated type is defined in our custom namespace, as we asked. "Template" is the type name that razor uses by default.
            var template = (MyTemplate)Activator.CreateInstance(asm.GetType("MyNamespace.Template"));

            // run the code.
            // should display "Hello Killroy, welcome to Razor World!"
            template.ExecuteAsync().Wait();
        }
예제 #6
0
        public static IList <RazorPageGeneratorResult> MainCore(string rootNamespace, string targetProjectDirectory)
        {
            var razorEngine = RazorEngine.Create(builder =>
            {
                builder
                .SetNamespace(rootNamespace)
                .SetBaseType("Microsoft.Extensions.RazorViews.BaseView")
                .ConfigureClass((document, @class) =>
                {
                    @class.ClassName = Path.GetFileNameWithoutExtension(document.Source.FilePath);
                    @class.Modifiers.Clear();
                    @class.Modifiers.Add("internal");
                });

                builder.Features.Add(new SuppressChecksumOptionsFeature());
            });

            var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
            var razorProject    = RazorProject.Create(targetProjectDirectory);
            var templateEngine  = new RazorTemplateEngine(razorEngine, razorProject);

            templateEngine.Options.DefaultImports = RazorSourceDocument.Create(@"
@using System
@using System.Threading.Tasks
", fileName: null);

            var fileCount = 0;

            var results = new List <RazorPageGeneratorResult>();

            foreach (var viewDir in viewDirectories)
            {
                Console.WriteLine();
                Console.WriteLine("  Generating code files for views in {0}", viewDir);
                var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/');
                var cshtmlFiles = razorProject.EnumerateItems(viewDirPath);

                if (!cshtmlFiles.Any())
                {
                    Console.WriteLine("  No .cshtml files were found.");
                    continue;
                }

                foreach (var item in cshtmlFiles)
                {
                    Console.WriteLine("    Generating code file for view {0}...", item.FileName);
                    results.Add(GenerateCodeFile(templateEngine, item));
                    Console.WriteLine("      Done!");
                    fileCount++;
                }
            }

            return(results);
        }
예제 #7
0
        private void _Init(string templateNamespace, string typeName, string basePath)
        {
            if (string.IsNullOrWhiteSpace(templateNamespace))
            {
                throw new ArgumentNullException(nameof(templateNamespace), "Cannot be null or empty.");
            }

            if (string.IsNullOrWhiteSpace(typeName))
            {
                throw new ArgumentNullException(nameof(typeName), "Cannot be null or empty.");
            }

            // customize the default engine a little bit
            var engine = RazorEngine.Create(b =>
            {
                InheritsDirective.Register(b);     // make sure the engine understand the @inherits directive in the input templates
                FunctionsDirective.Register(b);    // make sure the engine understand the @function directive in the input templates
                SectionDirective.Register(b);      // make sure the engine understand the @section directive in the input templates
                b.SetNamespace(templateNamespace); // define a namespace for the Template class
                b.Build();
            });

            var project        = RazorProject.Create(HostingEnvironment.ContentRootPath);
            var templateEngine = new RazorTemplateEngine(engine, project);

            // get a razor-templated file. My "hello.txt" template file is defined like this:
            //
            // @inherits RazorTemplate.MyTemplate
            // Hello @Model.Name, welcome to Razor World!
            //

            var fileInfo = _FindView(typeName, basePath, out var filepath);

            // ... parse and generate C# code ...
            var codeDoc = RazorCSharpDocument.Create();
            var cs      = templateEngine.GenerateCode(codeDoc);

            // ... use roslyn to parse the C# code ...
            //
            var tree = CSharpSyntaxTree.ParseText(cs.GeneratedCode);

            // ... name the assembly ...
            //
            string dllName = templateNamespace + "." + typeName;

            var compilation = CSharpCompilation.Create(dllName, new[] { tree },
                                                       new[]
        public override RazorTemplateEngine Create(string projectPath, Action <IRazorEngineBuilder> configure)
        {
            if (projectPath == null)
            {
                throw new ArgumentNullException(nameof(projectPath));
            }

            // In 15.5 we expect projectPath to be a directory, NOT the path to the csproj.
            var project              = FindProject(projectPath);
            var configuration        = (project?.Configuration as MvcExtensibilityConfiguration) ?? DefaultConfiguration;
            var razorLanguageVersion = configuration.LanguageVersion;
            var razorConfiguration   = new RazorConfiguration(razorLanguageVersion, "unnamed", Array.Empty <RazorExtension>(), designTime: true);

            RazorEngine engine;

            if (razorLanguageVersion.Major == 1)
            {
                engine = RazorEngine.CreateCore(razorConfiguration, b =>
                {
                    configure?.Invoke(b);

                    Mvc1_X.RazorExtensions.Register(b);

                    if (configuration.MvcAssembly.Identity.Version.Minor >= 1)
                    {
                        Mvc1_X.RazorExtensions.RegisterViewComponentTagHelpers(b);
                    }
                });

                var templateEngine = new Mvc1_X.MvcRazorTemplateEngine(engine, RazorProject.Create(projectPath));
                templateEngine.Options.ImportsFileName = "_ViewImports.cshtml";
                return(templateEngine);
            }
            else
            {
                engine = RazorEngine.CreateCore(razorConfiguration, b =>
                {
                    configure?.Invoke(b);

                    MvcLatest.RazorExtensions.Register(b);
                });

                var templateEngine = new MvcLatest.MvcRazorTemplateEngine(engine, RazorProject.Create(projectPath));
                templateEngine.Options.ImportsFileName = "_ViewImports.cshtml";
                return(templateEngine);
            }
        }
예제 #9
0
        public void Setup()
        {
            var razorProject = RazorProject.Create(AppDomain.CurrentDomain.BaseDirectory);
            var razorEngine = RazorEngine.Create(b =>
            {
                b.SetNamespace("Some.Namespace");
                b.SetBaseType(typeof(MinimalistRazorTemplate).FullName);
            });
            var razorTemplateEngine = new RazorTemplateEngine(razorEngine, razorProject);

            var references = AppDomain.CurrentDomain.GetAssemblies()
                .Where(a => !a.IsDynamic)
                .Select(a => MetadataReference.CreateFromFile(a.Location))
                .ToList();
            var emitOptions = new EmitOptions(debugInformationFormat: We.SupportFullPdb() ? DebugInformationFormat.Pdb : DebugInformationFormat.PortablePdb);
            _renderer = new RazorViewCompiler(razorTemplateEngine, references, emitOptions);
        }
        protected override RazorPageGeneratorResult Generate(string rootNamespace, string targetPath, Type modelType)
        {
            var baseTypeName = "KiraNet.GutsMvc.View.RazorPageViewBase";

            if (modelType != null)
            {
                baseTypeName = $"{baseTypeName}<{TypeHelper.GetCSharpTypeName(modelType)}>";
            }

            var className   = String.Empty;
            var razorEngine = RazorEngine.Create(builder =>
            {
                builder
                .SetNamespace(rootNamespace)
                .SetBaseType(baseTypeName)
                .ConfigureClass((document, @class) =>
                {
                    @class.ClassName = className = Path.GetFileNameWithoutExtension(document.Source.FilePath) + DateTime.Now.Ticks;
                    @class.Modifiers.Clear();
                    @class.Modifiers.Add("internal");
                });

                builder.Features.Add(new SuppressChecksumOptionsFeature());
            });

            var razorProject   = RazorProject.Create(ViewPath.Path);
            var templateEngine = new RazorTemplateEngine(razorEngine, razorProject);

            templateEngine.Options.DefaultImports = RazorSourceDocument.Create(@"
                @using System
                @using System.Threading.Tasks
                @using System.Collections.Generic
                @using System.Collections
                ", fileName: null);


            //templateEngine.Options.DefaultImports = RazorSourceDocument.Create("", null);
            var cshtmlFile  = razorProject.GetItem(targetPath);
            var razorResult = GenerateCodeFile(templateEngine, cshtmlFile);

            razorResult.ClassName = className;
            return(razorResult);
        }
        public override RazorTemplateEngine Create(string projectPath, Action <IRazorEngineBuilder> configure)
        {
            if (projectPath == null)
            {
                throw new ArgumentNullException(nameof(projectPath));
            }

            var engine = RazorEngine.CreateDesignTime(b =>
            {
                configure?.Invoke(b);

                // For now we're hardcoded to use MVC's extensibility.
                RazorExtensions.Register(b);
            });

            var templateEngine = new MvcRazorTemplateEngine(engine, RazorProject.Create(projectPath));

            templateEngine.Options.ImportsFileName = "_ViewImports.cshtml";
            return(templateEngine);
        }
예제 #12
0
        public static IList <RazorPageGeneratorResult> MainCore(RazorEngine razorEngine, string targetProjectDirectory)
        {
            var viewDirectories = Directory.EnumerateDirectories(targetProjectDirectory, "Views", SearchOption.AllDirectories);
            var razorProject    = RazorProject.Create(targetProjectDirectory);
            var templateEngine  = new RazorTemplateEngine(razorEngine, razorProject);

            templateEngine.Options.DefaultImports = RazorSourceDocument.Create(@"
@using System
@using System.Threading.Tasks
", fileName: null);

            var fileCount = 0;

            var results = new List <RazorPageGeneratorResult>();

            foreach (var viewDir in viewDirectories)
            {
                Console.WriteLine();
                Console.WriteLine("  Generating code files for views in {0}", viewDir);
                var viewDirPath = viewDir.Substring(targetProjectDirectory.Length).Replace('\\', '/');
                var cshtmlFiles = razorProject.EnumerateItems(viewDirPath);

                if (!cshtmlFiles.Any())
                {
                    Console.WriteLine("  No .cshtml files were found.");
                    continue;
                }

                foreach (var item in cshtmlFiles)
                {
                    Console.WriteLine("    Generating code file for view {0}...", item.FileName);
                    results.Add(GenerateCodeFile(templateEngine, item));
                    Console.WriteLine("      Done!");
                    fileCount++;
                }
            }

            return(results);
        }
예제 #13
0
        private int ExecuteCore(string projectDirectory, string outputDirectory, string tagHelperManifest, string[] sources)
        {
            var tagHelpers = GetTagHelpers(tagHelperManifest);

            var engine = RazorEngine.Create(b =>
            {
                RazorExtensions.Register(b);

                b.Features.Add(new StaticTagHelperFeature()
                {
                    TagHelpers = tagHelpers,
                });
            });

            var templateEngine = new MvcRazorTemplateEngine(engine, RazorProject.Create(projectDirectory));

            var sourceItems = GetRazorFiles(projectDirectory, sources);
            var results     = GenerateCode(templateEngine, sourceItems);

            var success = true;

            foreach (var result in results)
            {
                if (result.CSharpDocument.Diagnostics.Count > 0)
                {
                    success = false;
                    foreach (var error in result.CSharpDocument.Diagnostics)
                    {
                        Console.Error.WriteLine(error.ToString());
                    }
                }

                var outputFilePath = Path.Combine(outputDirectory, Path.ChangeExtension(result.ViewFileInfo.ViewEnginePath.Substring(1), ".cs"));
                File.WriteAllText(outputFilePath, result.CSharpDocument.GeneratedCode);
            }

            return(success ? 0 : -1);
        }
        public CodeGenerationBenchmark()
        {
            var current = new DirectoryInfo(AppContext.BaseDirectory);

            while (current != null && !File.Exists(Path.Combine(current.FullName, "MSN.cshtml")))
            {
                current = current.Parent;
            }

            var root = current;

            var engine = RazorEngine.Create(b => { RazorExtensions.Register(b); });

            var project = RazorProject.Create(root.FullName);

            DesignTimeTemplateEngine = new MvcRazorTemplateEngine(RazorEngine.CreateDesignTime(b => { RazorExtensions.Register(b); }), project);
            RuntimeTemplateEngine    = new MvcRazorTemplateEngine(RazorEngine.Create(b => { RazorExtensions.Register(b); }), project);

            var codeDocument = RuntimeTemplateEngine.CreateCodeDocument(Path.Combine(root.FullName, "MSN.cshtml"));

            Imports = codeDocument.Imports;
            MSN     = codeDocument.Source;
        }
        protected override async Task <TemplateResult> ProcessSingleTemplate(string content,
                                                                             dynamic templateModel)
        {
            var razorEngine = RazorEngine.Create((builder) =>
            {
                RazorExtensions.Register(builder);
            });

            // Don't care about the RazorProject as we already have the content of the .cshtml file
            // and don't need to deal with imports.
            var razorProject        = RazorProject.Create(Directory.GetCurrentDirectory());
            var razorTemplateEngine = new RazorTemplateEngine(razorEngine, razorProject);

            var imports = new RazorSourceDocument[]
            {
                RazorSourceDocument.Create(@"
@using System
@using System.Threading.Tasks
", fileName: null)
            };

            var razorDocument    = RazorCodeDocument.Create(RazorSourceDocument.Create(content, "Template"), imports);
            var generatorResults = razorTemplateEngine.GenerateCode(razorDocument);

            if (generatorResults.Diagnostics.Any())
            {
                var messages = generatorResults.Diagnostics.Select(d => d.GetMessage());
                return(new TemplateResult()
                {
                    GeneratedText = string.Empty,
                    ProcessingException = new TemplateProcessingException(messages, generatorResults.GeneratedCode)
                });
            }
            var templateResult = _compilationService.Compile(generatorResults.GeneratedCode);

            if (templateResult.Messages.Any())
            {
                return(new TemplateResult()
                {
                    GeneratedText = string.Empty,
                    ProcessingException = new TemplateProcessingException(templateResult.Messages, generatorResults.GeneratedCode)
                });
            }

            var compiledObject = Activator.CreateInstance(templateResult.CompiledType);
            var razorTemplate  = compiledObject as RazorTemplateBase;

            string result = String.Empty;

            if (razorTemplate != null)
            {
                razorTemplate.Model = templateModel;
                //ToDo: If there are errors executing the code, they are missed here.
                result = await razorTemplate.ExecuteTemplate();
            }

            return(new TemplateResult()
            {
                GeneratedText = result,
                ProcessingException = null
            });
        }
예제 #16
0
        /// <summary>
        /// Writes C# source code representing a Blazor component defined by a Razor file.
        /// </summary>
        /// <param name="inputRootPath">Path to a directory containing input files.</param>
        /// <param name="inputPaths">Paths to the input files relative to <paramref name="inputRootPath"/>. The generated namespaces will be based on these relative paths.</param>
        /// <param name="baseNamespace">The base namespace for the generated class.</param>
        /// <param name="resultOutput">A <see cref="TextWriter"/> to which C# source code will be written.</param>
        /// <param name="verboseOutput">If not null, additional information will be written to this <see cref="TextWriter"/>.</param>
        /// <returns>An enumerable of <see cref="RazorCompilerDiagnostic"/> instances representing any warnings or errors that were encountered.</returns>
        public IEnumerable <RazorCompilerDiagnostic> CompileSingleFile(
            string inputRootPath,
            string inputFilePath,
            Stream inputFileContents,
            string baseNamespace,
            TextWriter resultOutput,
            TextWriter verboseOutput)
        {
            if (inputFileContents == null)
            {
                throw new ArgumentNullException(nameof(inputFileContents));
            }

            if (resultOutput == null)
            {
                throw new ArgumentNullException(nameof(resultOutput));
            }

            if (string.IsNullOrEmpty(inputRootPath))
            {
                throw new ArgumentException("Cannot be null or empty.", nameof(inputRootPath));
            }

            if (string.IsNullOrEmpty(baseNamespace))
            {
                throw new ArgumentException("Cannot be null or empty.", nameof(baseNamespace));
            }

            try
            {
                verboseOutput?.WriteLine($"Compiling {inputFilePath}...");
                var(itemNamespace, itemClassName) = GetNamespaceAndClassName(inputRootPath, inputFilePath);
                var combinedNamespace = string.IsNullOrEmpty(itemNamespace)
                    ? baseNamespace
                    : $"{baseNamespace}.{itemNamespace}";

                // TODO: Pass through info about whether this is a design-time build, and if so,
                // just emit enough of a stub class that intellisense will show the correct type
                // name and any public members. Don't need to actually emit all the RenderTreeBuilder
                // invocations.

                var engine = new BlazorRazorEngine();
                var blazorTemplateEngine = new BlazorTemplateEngine(
                    engine.Engine,
                    RazorProject.Create(inputRootPath));
                var codeDoc = blazorTemplateEngine.CreateCodeDocument(
                    new BlazorProjectItem(inputRootPath, inputFilePath, inputFileContents));
                codeDoc.Items[BlazorCodeDocItems.Namespace] = combinedNamespace;
                codeDoc.Items[BlazorCodeDocItems.ClassName] = itemClassName;
                var csharpDocument = blazorTemplateEngine.GenerateCode(codeDoc);
                var generatedCode  = csharpDocument.GeneratedCode;

                // Add parameters to the primary method via string manipulation because
                // DefaultDocumentWriter's VisitMethodDeclaration can't emit parameters
                var primaryMethodSource = $"protected override void {BlazorComponent.BuildRenderTreeMethodName}";
                generatedCode = generatedCode.Replace(
                    $"{primaryMethodSource}()",
                    $"{primaryMethodSource}({typeof(RenderTreeBuilder).FullName} builder)");

                resultOutput.WriteLine(generatedCode);

                return(Enumerable.Empty <RazorCompilerDiagnostic>());
            }
            catch (RazorCompilerException ex)
            {
                return(new[] { ex.ToDiagnostic(inputFilePath) });
            }
            catch (Exception ex)
            {
                return(new[]
                {
                    new RazorCompilerDiagnostic(
                        RazorCompilerDiagnostic.DiagnosticType.Error,
                        inputFilePath,
                        1,
                        1,
                        $"Unexpected exception: {ex.Message}{Environment.NewLine}{ex.StackTrace}")
                });
            }
        }
예제 #17
0
        static int Main(string[] args)
        {
            var baseDirectory   = Path.GetFullPath(args[0]);
            var outputDirectory = Path.GetFullPath(args[1]);

            if (Directory.Exists(outputDirectory))
            {
                Directory.Delete(outputDirectory, true);
            }
            Directory.CreateDirectory(outputDirectory);



            CustomWriterPhase customWriter = null;
            var inheritsDirective          = new CustomInheritsDirective();
            var reactCtorPhase             = new GenerateReactComponentCtorFeature();
            var engine = RazorEngine.Create(builder =>
            {
                builder
                .SetNamespace(TempNamespace)
                .SetBaseType("Bridge.Razor.BaseView")
                .ConfigureClass((document, @class) =>
                {
                    @class.ClassName = ClassName;
                    @class.Modifiers.Clear();
                    @class.Modifiers.Add("public");
                });
                var defaultCSharpLoweringPhase = builder.Phases.OfType <IRazorCSharpLoweringPhase>().Single();
                builder.Phases.Remove(defaultCSharpLoweringPhase);
                builder.Phases.Add(customWriter = new CustomWriterPhase(defaultCSharpLoweringPhase));

                inheritsDirective.Register(builder);
                Microsoft.AspNetCore.Razor.Language.Extensions.FunctionsDirective.Register(builder);
                builder.Features.Add(reactCtorPhase);
            });

            var prj     = RazorProject.Create(baseDirectory);
            var tengine = new RazorTemplateEngine(engine, prj);

            var initCode = "";

            var cshtmlFiles = prj.EnumerateItems("/");

            foreach (var item in cshtmlFiles)
            {
                Console.WriteLine($"Generating code file for view {item.CombinedPath}");
                var path      = (item.CombinedPath).Replace("\\", "/");
                var className = Regex.Replace(path.Replace("/", "_"),
                                              "[^A-Za-z-0-9]+", "") + "_" +
                                Guid.NewGuid().ToString().Replace("-", "");
                var outputName = Utils.EscapePath(path);
                var ns         = DefaultNamespace;

                var suppressRegistration = false;
                inheritsDirective.PartialClassMode = false;
                reactCtorPhase.Enabled             = false;
                Func <string, string> postProcess = _ => _;

                var lines = File.ReadAllLines(item.PhysicalPath);
                foreach (var l in lines)
                {
                    var m = Regex.Match(l, @"^\s*@\*(.*)\*@\s*$");
                    if (!m.Success && !string.IsNullOrWhiteSpace(l))
                    {
                        break;
                    }
                    var directive = m.Groups[1].Value.Trim().Split(new[] { '=' }, 2).Select(x => x.Trim()).ToArray();
                    var key       = directive[0];
                    var value     = directive.Length > 1 ? directive[1] : null;
                    if (key == "type" && value == "partial")
                    {
                        inheritsDirective.PartialClassMode = true;
                        suppressRegistration = true;
                    }

                    if (key == "classname")
                    {
                        var parsed = new TypeReferenceInfo(value);
                        ns                   = parsed.Namespace;
                        className            = parsed.Name;
                        suppressRegistration = true;
                    }
                    if (key == "type" && value == "react-component")
                    {
                        reactCtorPhase.Enabled = true;
                    }
                }
                customWriter.Writer = new RazorDomWriter();
                var cSharpDocument = tengine.GenerateCode(item);
                if (cSharpDocument.Diagnostics.Any())
                {
                    var diagnostics = string.Join(Environment.NewLine, cSharpDocument.Diagnostics);
                    Console.Error.WriteLine(
                        $"One or more parse errors encountered. This will not prevent the generator from continuing: {Environment.NewLine}{diagnostics}.");
                    return(1);
                }
                else
                {
                    var code = cSharpDocument.GeneratedCode.Replace(ClassName, className);
                    code = postProcess(code.Replace(
                                           "public async override global::System.Threading.Tasks.Task ExecuteAsync(",
                                           "protected override void RenderRazor(Bridge.Razor.IDomBuilder Builder")
                                       .Replace(TempNamespace, ns)
                                       );

                    File.WriteAllText(Path.Combine(outputDirectory, outputName + ".generated.cs"), code);
                    if (!suppressRegistration)
                    {
                        initCode += "\nBridge.Razor.RuntimeSupport.ViewRegistry.Register(\""
                                    + path.Replace("\\", "/")
                                    + "\", () => new " + className + " ());";
                    }
                }
            }

            Console.WriteLine("Generating item registration...");

            initCode = "namespace Bridge.Razor.Generated\n{\nstatic class ViewRegistration\n{\n" +
                       "[Bridge.Init(Bridge.InitPosition.Bottom)]\n" +
                       "public static void Register(){\n" + initCode
                       + "\n}}}";
            File.WriteAllText(Path.Combine(outputDirectory, "Bridge.Razor.Generated.ViewRegistration.generated.cs"),
                              initCode);

            Console.WriteLine("Razor generation completed");

            return(0);
        }