예제 #1
0
파일: Configurator.cs 프로젝트: tbolon/Wyam
        private void Evaluate(string code, FilePath configFilePath)
        {
            if (string.IsNullOrEmpty(code))
            {
                return;
            }

            Stopwatch stopwatch = Stopwatch.StartNew();

            using (Trace.WithIndent().Information("Evaluating configuration script"))
            {
                CacheManager cacheManager = new CacheManager(
                    _engine,
                    _scriptManager,
                    configFilePath?.AppendExtension(".dll"),
                    configFilePath?.AppendExtension(".hash"),
                    configFilePath?.AppendExtension(".generated.cs"));
                cacheManager.EvaluateCode(code, ClassCatalog.GetClasses <IModule>().ToList(), OutputScript, IgnoreConfigHash, NoOutputConfigAssembly);

                stopwatch.Stop();
                Trace.Information($"Evaluated configuration script in {stopwatch.ElapsedMilliseconds} ms");
            }
        }
예제 #2
0
        /// <inheritdoc />
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            HtmlParser parser = new HtmlParser();

            using (IJsEnginePool enginePool = context.GetJsEnginePool(x =>
            {
                if (string.IsNullOrWhiteSpace(_highlightJsFile))
                {
                    x.ExecuteResource("highlight-all.js", typeof(Highlight));
                }
                else
                {
                    x.ExecuteFile(_highlightJsFile);
                }
            }))
            {
                return(inputs.AsParallel().Select(context, input =>
                {
                    // We materialize the list before exiting the using statement, so safe to access enginePool
                    // ReSharper disable once AccessToDisposedClosure
                    using (IJsEngine engine = enginePool.GetEngine())
                    {
                        try
                        {
                            using (Stream stream = input.GetStream())
                                using (IHtmlDocument htmlDocument = parser.Parse(stream))
                                {
                                    foreach (AngleSharp.Dom.IElement element in htmlDocument.QuerySelectorAll(_codeQuerySelector))
                                    {
                                        // Don't highlight anything that potentially is already highlighted
                                        if (element.ClassList.Contains("hljs"))
                                        {
                                            continue;
                                        }


                                        // Make sure to use TextContent, otherwise you'll get escaped html which highlight.js won't parse
                                        engine.SetVariableValue("input", element.TextContent);

                                        // Check if they specified a language in their code block
                                        string language = element.ClassList.FirstOrDefault(i => i.StartsWith("language"));

                                        try
                                        {
                                            if (language != null)
                                            {
                                                engine.SetVariableValue("language", language.Replace("language-", ""));
                                                engine.Execute("result = hljs.highlight(language, input)");
                                            }
                                            else
                                            {
                                                language = "(auto)"; // set this to auto in case there is an exception below
                                                engine.Execute("result = hljs.highlightAuto(input)");
                                                string detectedLanguage = engine.Evaluate <string>("result.language");
                                                if (string.IsNullOrWhiteSpace(detectedLanguage) == false)
                                                {
                                                    element.ClassList.Add("language-" + detectedLanguage);
                                                }
                                            }

                                            element.ClassList.Add("hljs");
                                            string formatted = engine.Evaluate <string>("result.value");
                                            element.InnerHtml = formatted;
                                        }
                                        catch (Exception innerEx)
                                        {
                                            if (innerEx.Message.Contains("Unknown language: ") && _warnOnMissingLanguage)
                                            {
                                                Trace.Warning("Exception while highlighting source code for {0} using language {1}: {2}", input.SourceString(), language, innerEx.Message);
                                            }
                                            else
                                            {
                                                Trace.Information("Exception while highlighting source code for {0} using language {1}: {2}", input.SourceString(), language, innerEx.Message);
                                            }
                                        }
                                    }
                                    string content = htmlDocument.ToHtml();
                                    return context.GetDocument(input, content);
                                }
                        }
                        catch (Exception ex)
                        {
                            Trace.Warning("Exception while highlighting source code for {0}: {1}", input.SourceString(), ex.Message);
                            return input;
                        }
                    }
                }).ToList());
            }
        }
예제 #3
0
        internal void InstallPackages(FilePath configFilePath)
        {
            DirectoryPath packagesPath = GetAbsolutePackagesPath();

            Trace.Information($"Installing packages to {packagesPath.FullPath} (using {(UseLocalPackagesFolder ? "local" : "global")} packages folder)");

            try
            {
                // Add the global default sources if requested
                if (UseGlobalPackageSources)
                {
                    _sourceRepositories.AddGlobalDefaults();
                }

                // Add the default package sources
                if (!IgnoreDefaultSources)
                {
                    _sourceRepositories.AddDefaultPackageSources();
                }

                // Get the local repository
                SourceRepository localRepository = _sourceRepositories.CreateRepository(packagesPath.FullPath);

                // Cache the packages in a packages file
                FilePath packagesFilePath = configFilePath?.AppendExtension(".packages.xml");
                if (packagesFilePath == null)
                {
                    Trace.Verbose("Will not write packages file since no config file was provided");
                }
                else
                {
                    Trace.Verbose($"Writing packages file to {packagesFilePath.FullPath}");
                }
                using (InstalledPackagesCache installedPackages = new InstalledPackagesCache(packagesFilePath, UpdatePackages))
                {
                    // Get the package manager and repositories
                    WyamFolderNuGetProject nuGetProject   = new WyamFolderNuGetProject(_fileSystem, _assemblyLoader, _currentFramework, installedPackages, packagesPath.FullPath);
                    NuGetPackageManager    packageManager = new NuGetPackageManager(_sourceRepositories, _settings, packagesPath.FullPath)
                    {
                        PackagesFolderNuGetProject = nuGetProject
                    };
                    IReadOnlyList <SourceRepository> remoteRepositories = _sourceRepositories.GetDefaultRepositories();

                    // Resolve all the versions
                    IReadOnlyList <SourceRepository> installationRepositories = remoteRepositories;
                    try
                    {
                        ResolveVersions(localRepository, remoteRepositories);
                    }
                    catch (Exception ex)
                    {
                        Trace.Verbose($"Exception while resolving package versions: {ex.Message}");
                        Trace.Warning("Error while resolving package versions, attempting without remote repositories");
                        installationRepositories = new[] { localRepository };
                        ResolveVersions(localRepository, Array.Empty <SourceRepository>());
                    }

                    // Install the packages (doing this synchronously since doing it in parallel triggers file lock errors in NuGet on a clean system)
                    try
                    {
                        InstallPackages(packageManager, installationRepositories, installedPackages);
                    }
                    catch (Exception ex)
                    {
                        Trace.Verbose($"Exception while installing packages: {(ex is AggregateException aex ? aex.Flatten() : ex)}");
                        Trace.Warning("Error while installing packages, attempting without remote repositories");
                        InstallPackages(packageManager, Array.Empty <SourceRepository>(), installedPackages);
                    }

                    // Process the package (do this after all packages have been installed)
                    nuGetProject.ProcessAssembliesAndContent();
                }
            }
            catch (Exception ex)
            {
                Trace.Verbose($"Unexpected exception while installing packages: {(ex is AggregateException ? string.Join("; ", ((AggregateException)ex).InnerExceptions.Select(x => x.Message)) : ex.Message)}");
                Trace.Warning("Error while installing packages, attempting to continue anyway");
            }
        }
예제 #4
0
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            // Register all the MVC and Razor services
            // In the future, if DI is implemented for all Wyam, the IExecutionContext would be registered as a service
            // and the IHostingEnviornment would be registered as transient with the execution context provided in ctor
            IServiceCollection serviceCollection = new ServiceCollection();
            IMvcCoreBuilder    builder           = serviceCollection
                                                   .AddMvcCore()
                                                   .AddRazorViewEngine();

            builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider(context));
            serviceCollection.Configure <RazorViewEngineOptions>(options =>
            {
                options.ViewLocationExpanders.Add(new ViewLocationExpander());
            });
            serviceCollection
            .AddSingleton <ILoggerFactory, TraceLoggerFactory>()
            .AddSingleton <DiagnosticSource, SilentDiagnosticSource>()
            .AddSingleton <IHostingEnvironment, HostingEnvironment>()
            .AddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>()
            .AddSingleton <IExecutionContext>(context)
            .AddSingleton <IBasePageTypeProvider>(new BasePageTypeProvider(_basePageType ?? typeof(WyamRazorPage <>)))
            .AddScoped <IMvcRazorHost, RazorHost>();
            IServiceProvider services = serviceCollection.BuildServiceProvider();

            // Eliminate input documents that we shouldn't process
            List <IDocument> validInputs = inputs
                                           .Where(x => _ignorePrefix == null ||
                                                  !x.ContainsKey(Keys.SourceFileName) ||
                                                  !x.FilePath(Keys.SourceFileName).FullPath.StartsWith(_ignorePrefix))
                                           .ToList();

            if (validInputs.Count < inputs.Count)
            {
                Trace.Information($"Ignoring {inputs.Count - validInputs.Count} inputs due to source file name prefix");
            }

            // Compile and evaluate the pages in parallel
            IServiceScopeFactory scopeFactory = services.GetRequiredService <IServiceScopeFactory>();

            return(validInputs.AsParallel().Select(input =>
            {
                Trace.Verbose("Processing Razor for {0}", input.SourceString());
                using (var scope = scopeFactory.CreateScope())
                {
                    // Get services
                    IRazorViewEngine viewEngine = scope.ServiceProvider.GetRequiredService <IRazorViewEngine>();
                    IRazorPageActivator pageActivator = scope.ServiceProvider.GetRequiredService <IRazorPageActivator>();
                    HtmlEncoder htmlEncoder = scope.ServiceProvider.GetRequiredService <HtmlEncoder>();
                    IRazorPageFactoryProvider pageFactoryProvider = scope.ServiceProvider.GetRequiredService <IRazorPageFactoryProvider>();
                    IRazorCompilationService razorCompilationService = scope.ServiceProvider.GetRequiredService <IRazorCompilationService>();
                    IHostingEnvironment hostingEnviornment = scope.ServiceProvider.GetRequiredService <IHostingEnvironment>();

                    // Compile the view
                    string relativePath = GetRelativePath(input, context);
                    FilePath viewStartLocationPath = _viewStartPath?.Invoke <FilePath>(input, context);
                    string viewStartLocation = viewStartLocationPath != null ? GetRelativePath(viewStartLocationPath, context) : null;
                    string layoutLocation = _layoutPath?.Invoke <FilePath>(input, context)?.FullPath;
                    IView view;
                    using (Stream stream = input.GetStream())
                    {
                        view = GetViewFromStream(relativePath, stream, viewStartLocation, layoutLocation, viewEngine, pageActivator,
                                                 htmlEncoder, pageFactoryProvider, hostingEnviornment.WebRootFileProvider, razorCompilationService);
                    }

                    // Render the view
                    object model = _model == null ? input : _model.Invoke(input, context);
                    using (StringWriter output = new StringWriter())
                    {
                        Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext =
                            GetViewContext(scope.ServiceProvider, view, model, input, context, output);
                        viewContext.View.RenderAsync(viewContext).GetAwaiter().GetResult();
                        return context.GetDocument(input, output.ToString());
                    }
                }
            }));
        }
예제 #5
0
        /// <inheritdoc />
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            HtmlParser parser = new HtmlParser();

            using (IJavaScriptEnginePool enginePool = context.GetJavaScriptEnginePool(x =>
            {
                if (string.IsNullOrWhiteSpace(_highlightJsFile))
                {
                    x.ExecuteResource("highlight-all.js", typeof(Highlight));
                }
                else
                {
                    x.ExecuteFile(_highlightJsFile);
                }
            }))
            {
                return(inputs.AsParallel().Select(context, input =>
                {
                    try
                    {
                        using (Stream stream = input.GetStream())
                        {
                            using (IHtmlDocument htmlDocument = parser.Parse(stream))
                            {
                                foreach (AngleSharp.Dom.IElement element in htmlDocument.QuerySelectorAll(_codeQuerySelector))
                                {
                                    // Don't highlight anything that potentially is already highlighted
                                    if (element.ClassList.Contains("hljs"))
                                    {
                                        continue;
                                    }

                                    try
                                    {
                                        HighlightElement(enginePool, element);
                                    }
                                    catch (Exception innerEx)
                                    {
                                        if (innerEx.Message.Contains("Unknown language: ") && _warnOnMissingLanguage)
                                        {
                                            Trace.Warning($"Exception while highlighting source code: {innerEx.Message}");
                                        }
                                        else
                                        {
                                            Trace.Information($"Exception while highlighting source code: {innerEx.Message}");
                                        }
                                    }
                                }

                                Stream contentStream = context.GetContentStream();
                                using (StreamWriter writer = contentStream.GetWriter())
                                {
                                    htmlDocument.ToHtml(writer, HtmlMarkupFormatter.Instance);
                                    writer.Flush();
                                    return context.GetDocument(input, contentStream);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace.Warning("Exception while highlighting source code for {0}: {1}", input.SourceString(), ex.Message);
                        return input;
                    }
                }).ToList());
            }
        }
예제 #6
0
        protected override ExitCode RunCommand(Preprocessor preprocessor)
        {
            // Get the standard input stream
            _configOptions.Stdin = StandardInputReader.Read();

            // Fix the root folder and other files
            DirectoryPath currentDirectory = Environment.CurrentDirectory;

            _configOptions.RootPath       = _configOptions.RootPath == null ? currentDirectory : currentDirectory.Combine(_configOptions.RootPath);
            _logFilePath                  = _logFilePath == null ? null : _configOptions.RootPath.CombineFile(_logFilePath);
            _configOptions.ConfigFilePath = _configOptions.RootPath.CombineFile(_configOptions.ConfigFilePath ?? "config.wyam");

            // Set up the log file
            if (_logFilePath != null)
            {
                Trace.AddListener(new SimpleFileTraceListener(_logFilePath.FullPath));
            }

            // Get the engine and configurator
            EngineManager engineManager = EngineManager.Get(preprocessor, _configOptions);

            if (engineManager == null)
            {
                return(ExitCode.CommandLineError);
            }

            // Configure and execute
            if (!engineManager.Configure())
            {
                return(ExitCode.ConfigurationError);
            }

            if (_verifyConfig)
            {
                Trace.Information("No errors. Exiting.");
                return(ExitCode.Normal);
            }

            Trace.Information($"Root path:{Environment.NewLine}  {engineManager.Engine.FileSystem.RootPath}");
            Trace.Information($"Input path(s):{Environment.NewLine}  {string.Join(Environment.NewLine + "  ", engineManager.Engine.FileSystem.InputPaths)}");
            Trace.Information($"Output path:{Environment.NewLine}  {engineManager.Engine.FileSystem.OutputPath}");
            if (!engineManager.Execute())
            {
                return(ExitCode.ExecutionError);
            }

            bool messagePump = false;

            // Start the preview server
            IDisposable previewServer = null;

            if (_preview)
            {
                messagePump = true;
                DirectoryPath previewPath = _previewRoot == null
                    ? engineManager.Engine.FileSystem.GetOutputDirectory().Path
                    : engineManager.Engine.FileSystem.GetOutputDirectory(_previewRoot).Path;

                previewServer = PreviewServer.Start(previewPath, _previewPort, _previewForceExtension);
            }

            // Start the watchers
            IDisposable inputFolderWatcher = null;
            IDisposable configFileWatcher  = null;

            if (_watch)
            {
                messagePump = true;

                Trace.Information("Watching paths(s) {0}", string.Join(", ", engineManager.Engine.FileSystem.InputPaths));
                inputFolderWatcher = new ActionFileSystemWatcher(engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                                                                 engineManager.Engine.FileSystem.GetInputDirectories().Select(x => x.Path), true, "*.*", path =>
                {
                    _changedFiles.Enqueue(path);
                    _messageEvent.Set();
                });

                if (_configOptions.ConfigFilePath != null)
                {
                    Trace.Information("Watching configuration file {0}", _configOptions.ConfigFilePath);
                    configFileWatcher = new ActionFileSystemWatcher(engineManager.Engine.FileSystem.GetOutputDirectory().Path,
                                                                    new[] { _configOptions.ConfigFilePath.Directory }, false, _configOptions.ConfigFilePath.FileName.FullPath, path =>
                    {
                        FilePath filePath = new FilePath(path);
                        if (_configOptions.ConfigFilePath.Equals(filePath))
                        {
                            _newEngine.Set();
                            _messageEvent.Set();
                        }
                    });
                }
            }

            // Start the message pump if an async process is running
            ExitCode exitCode = ExitCode.Normal;

            if (messagePump)
            {
                // Only wait for a key if console input has not been redirected, otherwise it's on the caller to exit
                if (!Console.IsInputRedirected)
                {
                    // Start the key listening thread
                    var thread = new Thread(() =>
                    {
                        Trace.Information("Hit any key to exit");
                        Console.ReadKey();
                        _exit.Set();
                        _messageEvent.Set();
                    })
                    {
                        IsBackground = true
                    };
                    thread.Start();
                }

                // Wait for activity
                while (true)
                {
                    _messageEvent.WaitOne();  // Blocks the current thread until a signal
                    if (_exit)
                    {
                        break;
                    }

                    // See if we need a new engine
                    if (_newEngine)
                    {
                        // Get a new engine
                        Trace.Information("Configuration file {0} has changed, re-running", _configOptions.ConfigFilePath);
                        engineManager.Dispose();
                        engineManager = EngineManager.Get(preprocessor, _configOptions);

                        // Configure and execute
                        if (!engineManager.Configure())
                        {
                            exitCode = ExitCode.ConfigurationError;
                            break;
                        }
                        Console.WriteLine($"Root path:{Environment.NewLine}  {engineManager.Engine.FileSystem.RootPath}");
                        Console.WriteLine($"Input path(s):{Environment.NewLine}  {string.Join(Environment.NewLine + "  ", engineManager.Engine.FileSystem.InputPaths)}");
                        Console.WriteLine($"Root path:{Environment.NewLine}  {engineManager.Engine.FileSystem.OutputPath}");
                        if (!engineManager.Execute())
                        {
                            exitCode = ExitCode.ExecutionError;
                            break;
                        }

                        // Clear the changed files since we just re-ran
                        string changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                        }

                        _newEngine.Unset();
                    }
                    else
                    {
                        // Execute if files have changed
                        HashSet <string> changedFiles = new HashSet <string>();
                        string           changedFile;
                        while (_changedFiles.TryDequeue(out changedFile))
                        {
                            if (changedFiles.Add(changedFile))
                            {
                                Trace.Verbose("{0} has changed", changedFile);
                            }
                        }
                        if (changedFiles.Count > 0)
                        {
                            Trace.Information("{0} files have changed, re-executing", changedFiles.Count);
                            if (!engineManager.Execute())
                            {
                                exitCode = ExitCode.ExecutionError;
                                break;
                            }
                        }
                    }

                    // Check one more time for exit
                    if (_exit)
                    {
                        break;
                    }
                    Trace.Information("Hit any key to exit");
                    _messageEvent.Reset();
                }

                // Shutdown
                Trace.Information("Shutting down");
                engineManager.Dispose();
                inputFolderWatcher?.Dispose();
                configFileWatcher?.Dispose();
                previewServer?.Dispose();
            }

            return(exitCode);
        }