public static AngularWorkspace Create(StandardGlobalInfo globalInfo, NPMSolution npmSolution, NormalizedPath path)
        {
            NormalizedPath packageJsonPath = path.AppendPart("package.json");
            NormalizedPath angularJsonPath = path.AppendPart("angular.json");

            JObject packageJson = JObject.Parse(File.ReadAllText(packageJsonPath));
            JObject angularJson = JObject.Parse(File.ReadAllText(angularJsonPath));

            if (!(packageJson["private"]?.ToObject <bool>() ?? false))
            {
                throw new InvalidDataException("A workspace project should be private.");
            }
            List <NPMProject> projects = new List <NPMProject>();
            var jsonProject            = angularJson["projects"].ToObject <JObject>();

            foreach (var project in jsonProject.Properties())
            {
                var    projectPath       = project.Value["root"].ToString();
                var    options           = project.Value["architect"]["build"]["options"];
                string outputPathJson    = options["outputPath"]?.Value <string>();
                bool   havePath          = outputPathJson != null;
                string ngPackagePath     = options["project"]?.Value <string>();
                bool   haveNgPackageJson = ngPackagePath != null;
                if (havePath && haveNgPackageJson)
                {
                    throw new NotImplementedException();                                //I don't know what to do in this case.
                }
                NormalizedPath outputPath;
                NormalizedPath ngPackagePathFullPath = path.Combine(ngPackagePath);
                if (haveNgPackageJson)
                {
                    JObject ngPackage = JObject.Parse(File.ReadAllText(ngPackagePathFullPath));
                    string  dest      = ngPackage["dest"]?.Value <string>();
                    if (dest == null)
                    {
                        throw new InvalidDataException("ng package does not contain dest path.");
                    }
                    outputPath = ngPackagePathFullPath.RemoveLastPart().Combine(dest).ResolveDots();
                }
                else if (havePath)
                {
                    outputPath = path.Combine(outputPathJson);
                }
                else
                {
                    globalInfo.Cake.Warning($"No path found for angular project '{path}'.");
                    outputPath = path.Combine(projectPath);
                }

                projects.Add(
                    NPMPublishedProject.Create(
                        globalInfo,
                        npmSolution,
                        path.Combine(projectPath),
                        outputPath
                        )
                    );
            }
            return(new AngularWorkspace(NPMPublishedProject.Create(globalInfo, npmSolution, path, path), projects));
        }
예제 #2
0
        public static AngularWorkspace Create(StandardGlobalInfo globalInfo, NPMSolution npmSolution, NormalizedPath path)
        {
            NormalizedPath packageJsonPath = path.AppendPart("package.json");
            NormalizedPath angularJsonPath = path.AppendPart("angular.json");

            JObject packageJson = JObject.Parse(File.ReadAllText(packageJsonPath));
            JObject angularJson = JObject.Parse(File.ReadAllText(angularJsonPath));

            if (!(packageJson["private"]?.ToObject <bool>() ?? false))
            {
                throw new InvalidDataException("A workspace project should be private.");
            }
            List <NPMProject> projects = new List <NPMProject>();
            var jsonProject            = angularJson["projects"].ToObject <JObject>();

            foreach (var project in jsonProject.Properties())
            {
                var projectPath = project.Value["root"].ToString();
                var outputPath  = project.Value["architect"]?["build"]?["options"]?["outputPath"]?.Value <string>()
                                  ?? projectPath;
                projects.Add(
                    NPMPublishedProject.Create(
                        globalInfo,
                        npmSolution,
                        path.Combine(projectPath),
                        path.Combine(outputPath)
                        )
                    );
            }
            return(new AngularWorkspace(NPMPublishedProject.Create(globalInfo, npmSolution, path, path), projects));
        }
예제 #3
0
        public static AngularWorkspace Create(StandardGlobalInfo globalInfo, NPMSolution npmSolution, NormalizedPath path, NormalizedPath outputFolder)
        {
            NormalizedPath packageJsonPath = path.AppendPart("package.json");
            NormalizedPath angularJsonPath = path.AppendPart("angular.json");

            JObject packageJson = JObject.Parse(File.ReadAllText(packageJsonPath));
            JObject angularJson = JObject.Parse(File.ReadAllText(angularJsonPath));

            if (!(packageJson["private"]?.ToObject <bool>() ?? false))
            {
                throw new InvalidDataException("A workspace project should be private.");
            }
            string            solutionName  = packageJson["name"].ToString();
            List <string>     unscopedNames = angularJson["projects"].ToObject <JObject>().Properties().Select(p => p.Name).ToList();
            List <NPMProject> projects      = unscopedNames.Select(
                p => NPMPublishedProject.Create(
                    globalInfo,
                    npmSolution,
                    path.Combine(new NormalizedPath(angularJson["projects"][p]["root"].ToString())),
                    outputFolder.AppendPart(p)
                    )
                ).ToList();

            return(new AngularWorkspace(projects.Single(p => p.DirectoryPath == path), projects, outputFolder));
        }
예제 #4
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddSingleton <IWebFrontAuthLoginService, SqlWebFrontAuthLoginService>();
            services.AddSingleton <IAuthenticationTypeSystem, StdAuthenticationTypeSystem>();
            services.AddSingleton <IWebFrontAuthAutoCreateAccountService, AutoCreateAccountService>();

            services.Configure <SpaOptions>(o =>
            {
                o.Host = Configuration["Spa:Host"];
            });

            services.AddAuthentication(WebFrontAuthOptions.OnlyAuthenticationScheme)
            .AddOpenIdConnect("Oidc", options =>
            {
                options.SignInScheme         = WebFrontAuthOptions.OnlyAuthenticationScheme;
                options.Authority            = "https://login.microsoftonline.com/" + Configuration["Authentication:Outlook:TenantId"];
                options.ClientId             = Configuration["Authentication:Outlook:ClientId"];
                options.ResponseType         = OpenIdConnectResponseType.IdToken;
                options.CallbackPath         = "/auth/signin-callback";
                options.SignedOutRedirectUri = "https://localhost:8080/";
                options.TokenValidationParameters.NameClaimType = "name";
                options.Events.OnTicketReceived = c => c.WebFrontAuthRemoteAuthenticateAsync <ICustomUserOidcInfos>(payload =>
                {
                    payload.Email        = c.Principal.FindFirst(ClaimTypes.Name).Value;
                    payload.FirstName    = c.Principal.FindFirst(ClaimTypes.GivenName).Value;
                    payload.LastName     = c.Principal.FindFirst(ClaimTypes.Surname).Value;
                    payload.SchemeSuffix = "";
                    // Instead of "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
                    // Use standard System.Security.Claims.ClaimTypes.
                    payload.Sub = c.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
                });
            })
            .AddWebFrontAuth(options =>
            {
                options.ExpireTimeSpan        = TimeSpan.FromHours(1);
                options.SlidingExpirationTime = TimeSpan.FromHours(1);
            })
            .AddCookie();

            if (_env.IsDevelopment())
            {
                NormalizedPath dllPath = Configuration["StObjMap:Path"];
                if (!dllPath.IsEmptyPath)
                {
                    var solutionPath = new NormalizedPath(AppContext.BaseDirectory).RemoveLastPart(4);
                    dllPath = solutionPath.Combine(dllPath).AppendPart("CK.StObj.AutoAssembly.dll");
                    File.Copy(dllPath, Path.Combine(AppContext.BaseDirectory, "CK.StObj.AutoAssembly.dll"), overwrite: true);
                }
            }

            services.AddCKDatabase("CK.StObj.AutoAssembly");
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSingleton <Emailer>();
            services.Configure <EmailerOptions>(Configuration.GetSection("gmail"));

            services.AddOptions();
            services.AddSignalR();
        }
예제 #5
0
        private static IModule[] GetTitleAndDestinationModules(IDocument archiveDoc) => new IModule[]
        {
            new AddTitle(
                Config.FromDocument(doc =>
            {
                if (doc.ContainsKey(WebKeys.ArchiveTitle))
                {
                    return(doc.GetString(WebKeys.ArchiveTitle));
                }

                // Default title
                string title = doc.GetString(Keys.Title);
                if (doc.ContainsKey(Keys.GroupKey))
                {
                    title += " - " + doc.GetString(Keys.GroupKey);
                }
                int index = doc.GetInt(Keys.Index);
                return(index <= 1 ? title : (title + $" (Page {index})"));
            })).KeepExisting(false),
            new SetDestination(
                Config.FromDocument(doc =>
            {
                if (doc.ContainsKey(WebKeys.ArchiveDestination))
                {
                    return(doc.GetPath(WebKeys.ArchiveDestination));
                }

                // Default destination
                NormalizedPath destination = archiveDoc.Destination.ChangeExtension(null);
                if (doc.ContainsKey(Keys.GroupKey))
                {
                    destination.Combine(NormalizedPath.ReplaceInvalidFileNameChars(doc.GetString(Keys.GroupKey)));
                }
                int index = doc.GetInt(Keys.Index);
                if (index > 1)
                {
                    destination = destination.Combine(index.ToString());
                }
                return(destination.AppendExtension(".html"));
            }),
                true)
        };
            public void ShouldCombinePaths(string first, string second, string expected)
            {
                // Given
                NormalizedPath path = new NormalizedPath(first);

                // When
                NormalizedPath result = path.Combine(new NormalizedPath(second));

                // Then
                Assert.AreEqual(expected, result.FullPath);
            }
            public void ShouldThrowIfPathIsNull()
            {
                // Given
                NormalizedPath path = new NormalizedPath("assets");

                // When
                TestDelegate test = () => path.Combine(null);

                // Then
                Assert.Throws <ArgumentNullException>(test);
            }
        /// <summary>
        /// Gets the <see cref="Value"/> as an absolute path or relative to <see cref="BasePath"/>.
        /// <para>
        /// Placeholders {BuildConfiguration} and {TestProjectName} can appear anywhere in the Value
        /// and are replaced with <see cref="IBasicTestHelper.BuildConfiguration"/> and <see cref="IBasicTestHelper.TestProjectName"/>.
        /// </para>
        /// <para>
        /// The Value can start with {BinFolder}, {SolutionFolder} or {RepositoryFolder}: <see cref="IBasicTestHelper.BinFolder"/>,
        /// <see cref="IBasicTestHelper.SolutionFolder"/> or <see cref="IBasicTestHelper.RepositoryFolder"/> is expanded.
        /// If the Value does not start with one of this 3 paths and no { appear, the <see cref="BasePath"/> is prepended.
        /// </para>
        /// <para>
        /// If there is no '{' (ie. there is no unresolved placeholder), all '/../' are automatically resolved.
        /// If a '{'  remains in the path, the dots are not resolved: this is up to the code that will use the path to resolve the placeholders
        /// and the dots (see <see cref="NormalizedPath.ResolveDots(int, bool)"/>).
        /// </para>
        /// Note that if the value is not a valid path, result is what it is, without any warranty.
        /// </summary>
        /// <returns>The path.</returns>
        public string GetValueAsPath()
        {
            Debug.Assert(Value != null && !BasePath.IsEmptyPath);

            string v = Value.Replace("{BuildConfiguration}", BasicTestHelper._buildConfiguration)
                       .Replace("{TestProjectName}", BasicTestHelper._testProjectName);

            string SubPathNoRoot(string theV, int prefixLen)
            {
                if (theV.Length > prefixLen &&
                    (theV[prefixLen] == System.IO.Path.DirectorySeparatorChar ||
                     theV[prefixLen] == System.IO.Path.AltDirectorySeparatorChar))
                {
                    ++prefixLen;
                }
                return(v.Substring(prefixLen));
            }

            Debug.Assert("{BinFolder}".Length == 11);
            Debug.Assert("{SolutionFolder}".Length == 16);
            Debug.Assert("{RepositoryFolder}".Length == 18);
            NormalizedPath raw;

            if (v.StartsWith("{BinFolder}"))
            {
                raw = BasicTestHelper._binFolder.Combine(SubPathNoRoot(v, 11));
            }
            else if (v.StartsWith("{SolutionFolder}"))
            {
                raw = BasicTestHelper._solutionFolder.Combine(SubPathNoRoot(v, 16));
            }
            else if (v.StartsWith("{RepositoryFolder}"))
            {
                raw = BasicTestHelper._repositoryFolder.Combine(SubPathNoRoot(v, 18));
            }
            else
            {
                if (Path.IsPathRooted(v))
                {
                    return(Path.GetFullPath(v));
                }
                if (v.IndexOf('{') >= 0)
                {
                    return(v);
                }
                raw = BasePath.Combine(v);
            }
            return(raw.Path.IndexOf('{') < 0 ? raw.ResolveDots() : raw);
        }
예제 #9
0
        static internal AngularWorkspace LoadAngularSolution(NPMProjectsDriver driver, IActivityMonitor m, IAngularWorkspaceSpec spec)
        {
            NormalizedPath packageJsonPath = spec.Path.AppendPart("package.json");
            NormalizedPath angularJsonPath = spec.Path.AppendPart("angular.json");
            var            fs          = driver.GitFolder.FileSystem;
            NormalizedPath path        = driver.BranchPath;
            JObject        packageJson = fs.GetFileInfo(path.Combine(packageJsonPath)).ReadAsJObject();
            JObject        angularJson = fs.GetFileInfo(path.Combine(angularJsonPath)).ReadAsJObject();

            if (!(packageJson["private"]?.ToObject <bool?>() ?? false))
            {
                throw new InvalidDataException("A workspace project should be private.");
            }
            string        solutionName  = packageJson["name"].ToString();
            List <string> unscopedNames = angularJson["projects"].ToObject <JObject>().Properties().Select(p => p.Name).ToList();

            List <NPMProject> projects = unscopedNames.Select(
                unscopedName =>
            {
                var projPathRelativeToWorkspace = new NormalizedPath(angularJson["projects"][unscopedName]["root"].ToString());
                var projPathRelativeToGitRepo   = spec.Path.Combine(projPathRelativeToWorkspace);
                var projectPathVirtualPath      = driver.BranchPath.Combine(projPathRelativeToGitRepo);
                JObject json = fs.GetFileInfo(projectPathVirtualPath.AppendPart("package.json")).ReadAsJObject();
                return(new NPMProject(
                           driver,
                           m,
                           new NPMProjectSpec(
                               projPathRelativeToGitRepo,
                               json["name"].ToString(),
                               json["private"]?.ToObject <bool>() ?? false
                               )
                           ));
            }).ToList();

            return(new AngularWorkspace(driver, spec, projects));
        }
예제 #10
0
            public void ShouldReturnRelativePathWithDirectoryPath(string source, string target, string expected)
            {
                // Given
                NormalizedPath sourcePath = new NormalizedPath(source);
                NormalizedPath targetPath = new NormalizedPath(target);

                // When
                NormalizedPath relativePath = RelativePathResolver.Resolve(sourcePath, targetPath);

                // Then
                expected.ShouldBe((string)relativePath);
                if (targetPath.IsAbsolute)
                {
                    sourcePath.Combine(relativePath).ShouldBe(targetPath);
                }
            }
 static NormalizedPath MakeAbsolute(NormalizedPath basePath, NormalizedPath p)
 {
     if (basePath.IsEmptyPath)
     {
         throw new InvalidOperationException("Configuration BasePath is empty.");
     }
     if (!basePath.IsRooted)
     {
         throw new InvalidOperationException($"Configuration BasePath '{basePath}' is not rooted.");
     }
     if (!p.IsRooted)
     {
         p = basePath.Combine(p);
     }
     return(p.ResolveDots());
 }
                static string ReplacePattern(NormalizedPath basePath, string pattern, string v)
                {
                    int len = pattern.Length;

                    if (v.Length >= len)
                    {
                        NormalizedPath result;
                        if (v.StartsWith(pattern, StringComparison.OrdinalIgnoreCase))
                        {
                            if (v.Length > len && (v[len] == '\\' || v[len] == '/'))
                            {
                                ++len;
                            }
                            result = basePath.Combine(v.Substring(len)).ResolveDots();
                        }
                    }
                    return(v);
                }
예제 #13
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();

            if (_env.IsDevelopment())
            {
                NormalizedPath dllPath = _configuration["StObjMap:Path"];
                if (!dllPath.IsEmpty)
                {
                    var solutionPath = new NormalizedPath(AppContext.BaseDirectory).RemoveLastPart(4);
                    dllPath = solutionPath.Combine(dllPath).AppendPart("CK.StObj.AutoAssembly.dll");
                    File.Copy(dllPath, Path.Combine(AppContext.BaseDirectory, "CK.StObj.AutoAssembly.dll"), overwrite: true);
                }
            }
            services.AddStObjMap("CK.StObj.AutoAssembly");
            services.AddCors();
            services.AddAmbientValues(_ => { });
            services.AddMvc();
        }
예제 #14
0
        private string GetRelativePath(NormalizedPath path, IExecutionContext context)
        {
            // Calculate a relative path from the input path(s) (or root) to the provided path
            if (!path.IsNull)
            {
                NormalizedPath inputPath = context.FileSystem.GetContainingInputPath(path);
                if (inputPath.IsNull)
                {
                    inputPath = NormalizedPath.AbsoluteRoot;
                }
                if (path.IsRelative)
                {
                    // If the path is relative, combine it with the input path to make it absolute
                    path = inputPath.Combine(path);
                }
                return($"/{inputPath.GetRelativePath(path).FullPath}");
            }

            // If there's no path, give this document a placeholder name
            return($"/{Path.GetRandomFileName()}.cshtml");
        }
예제 #15
0
 /// <summary>
 /// Initializes a new <see cref="PluginFolderBase"/> on a folder path inside a branch path.
 /// </summary>
 /// <param name="f">The folder.</param>
 /// <param name="branchPath">The actual branch path (relative to the <see cref="FileSystem"/>).</param>
 /// <param name="folderPath">
 /// The actual sub folder path (ie. 'CodeCakeBuilder') where resources must be updated.</param>
 /// <param name="resourcePrefix">
 /// Optional resource prfix that defaults to <paramref name="resourceHolder"/>.Namespace + ".Res.".
 /// When not null, this path prefix is combined withe the namespace of the resourceHolder.
 /// </param>
 /// <param name="resourceHolder">
 /// Optional type used to locate resources.
 /// By default it is the actual type of this folder object: the defining assembly and namespace are used.
 /// </param>
 public PluginFolderBase(GitFolder f, NormalizedPath branchPath, NormalizedPath subFolderPath, NormalizedPath?resourcePrefix = null, Type resourceHolder = null)
     : base(f, branchPath)
 {
     FolderPath = branchPath.Combine(subFolderPath).ResolveDots(branchPath.Parts.Count);
     if (resourceHolder == null)
     {
         resourceHolder = GetType();
     }
     _resourceAssembly = resourceHolder.Assembly;
     if (!resourcePrefix.HasValue)
     {
         _resourcePrefix = resourceHolder.Namespace + ".Res.";
     }
     else
     {
         NormalizedPath p = resourceHolder.Namespace.Replace('.', '/');
         _resourcePrefix = p.Combine(resourcePrefix.Value).ResolveDots().Path.Replace('/', '.') + '.';
     }
     _csResourcePrefix      = _csProtocol + _resourcePrefix;
     _csResourcePrefixSlash = _csProtocolSlash + _resourcePrefix;
 }
예제 #16
0
        private static void ApplyCommandSettings(Engine engine, IConfigurationSettings configurationSettings, EngineCommandSettings commandSettings)
        {
            // Set folders
            NormalizedPath currentDirectory = Environment.CurrentDirectory;

            engine.FileSystem.RootPath = string.IsNullOrEmpty(commandSettings.RootPath)
                ? currentDirectory
                : currentDirectory.Combine(commandSettings.RootPath);
            if (commandSettings.InputPaths?.Length > 0)
            {
                // Clear existing default paths if new ones are set
                // and reverse the inputs so the last one is first to match the semantics of multiple occurrence single options
                engine.FileSystem.InputPaths.Clear();
                engine.FileSystem.InputPaths.AddRange(commandSettings.InputPaths.Select(x => new NormalizedPath(x)).Reverse());
            }
            if (!string.IsNullOrEmpty(commandSettings.OutputPath))
            {
                engine.FileSystem.OutputPath = commandSettings.OutputPath;
            }
            if (commandSettings.NoClean)
            {
                configurationSettings[Keys.CleanOutputPath] = false;
            }

            // Set no cache if requested
            if (commandSettings.NoCache)
            {
                configurationSettings[Keys.UseCache] = false;
            }

            // Set serial mode
            if (commandSettings.SerialExecution)
            {
                engine.SerialExecution = true;
            }
        }
예제 #17
0
        protected override async Task <int> ExecuteEngineAsync(
            CommandContext commandContext,
            ServeCommandSettings commandSettings,
            IEngineManager engineManager)
        {
            ExitCode exitCode = ExitCode.Normal;
            ILogger  logger   = engineManager.Engine.Services.GetRequiredService <ILogger <Bootstrapper> >();

            // Set folders
            IFileSystem    fileSystem       = engineManager.Engine.FileSystem;
            NormalizedPath currentDirectory = Environment.CurrentDirectory;
            IDirectory     serveDirectory;

            if (string.IsNullOrEmpty(commandSettings.RootPath))
            {
                fileSystem.RootPath = currentDirectory;
                serveDirectory      = fileSystem.GetOutputDirectory();
            }
            else
            {
                fileSystem.RootPath = currentDirectory.Combine(commandSettings.RootPath);
                serveDirectory      = fileSystem.GetRootDirectory();
            }

            Dictionary <string, string> contentTypes = commandSettings.ContentTypes?.Length > 0
                ? PreviewCommand.GetContentTypes(commandSettings.ContentTypes)
                : new Dictionary <string, string>();
            ILoggerProvider loggerProvider = engineManager.Engine.Services.GetRequiredService <ILoggerProvider>();

            Server            previewServer      = null;
            FileSystemWatcher serveFolderWatcher = null;

            if (serveDirectory.Exists)
            {
                // Starts Preview server
                previewServer = await PreviewCommand.StartPreviewServerAsync(
                    serveDirectory.Path,
                    commandSettings.Port,
                    commandSettings.ForceExt,
                    commandSettings.VirtualDirectory,
                    !commandSettings.NoReload,
                    contentTypes,
                    loggerProvider,
                    logger);

                // Start the watchers
                if (!commandSettings.NoReload)
                {
                    logger.LogInformation("Watching path {0}", serveDirectory.Path);
                    serveFolderWatcher = new FileSystemWatcher(serveDirectory.Path.FullPath, "*.*")
                    {
                        IncludeSubdirectories = true,
                        EnableRaisingEvents   = true
                    };

                    serveFolderWatcher.Changed += OnFileChanged;
                    serveFolderWatcher.Created += OnFileChanged;
                }

                // Start the message pump
                CommandUtilities.WaitForControlC(
                    () =>
                {
                    _exit.Set();
                    _messageEvent.Set();
                },
                    logger);

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

                    // Execute if files have changed
                    HashSet <string> changedFiles = new HashSet <string>();
                    while (_changedFiles.TryDequeue(out string changedFile))
                    {
                        if (changedFiles.Add(changedFile))
                        {
                            logger.LogDebug($"{changedFile} has changed");
                        }
                    }

                    if (changedFiles.Count > 0)
                    {
                        logger.LogInformation($"{changedFiles.Count} files have changed, re-loading");
                        await previewServer.TriggerReloadAsync();
                    }

                    // Check one more time for exit
                    if (_exit)
                    {
                        break;
                    }
                    logger.LogInformation("Hit Ctrl-C to exit");
                    _messageEvent.Reset();
                }
            }
            else
            {
                logger.LogError($"Directory {serveDirectory.Path} does not exist.");
            }

            // Shutdown
            logger.LogInformation("Shutting down");

            if (serveFolderWatcher != null)
            {
                serveFolderWatcher.EnableRaisingEvents = false;
                serveFolderWatcher.Changed            -= OnFileChanged;
                serveFolderWatcher.Created            -= OnFileChanged;
                serveFolderWatcher.Dispose();
            }

            previewServer?.Dispose();

            return((int)exitCode);
        }
예제 #18
0
 //TODO: Introduce a "common" project for extension method duplicated across projects
 internal static NormalizedPath ToAbsolutePath(this NormalizedPath path, NormalizedPath absoluteTo)
 {
     return(path.IsAbsolute ? path : absoluteTo.Combine(path));
 }
예제 #19
0
        protected override async Task <IEnumerable <IDocument> > ExecuteInputAsync(IDocument input, IExecutionContext context)
        {
            context.LogDebug($"Processing Sass for {input.ToSafeDisplayString()}");

            NormalizedPath inputPath = await _inputPath.GetValueAsync(input, context);

            if (inputPath.IsNull || inputPath.IsRelative)
            {
                inputPath = context.FileSystem.GetInputFile(new NormalizedPath(Path.GetRandomFileName())).Path;
                context.LogWarning($"No input path found for document {input.ToSafeDisplayString()}, using {inputPath.FileName.FullPath}");
            }

            string content = await input.GetContentStringAsync();

            // Sass conversion
            FileImporter importer = new FileImporter(context.FileSystem, _importPathFunc);
            ScssOptions  options  = new ScssOptions
            {
                OutputStyle       = _outputStyle,
                GenerateSourceMap = _generateSourceMap,
                SourceComments    = _includeSourceComments,
                InputFile         = inputPath.FullPath,
                TryImport         = importer.TryImport
            };
            IEnumerable <string> includePaths = _includePaths
                                                .Where(x => !x.IsNull)
                                                .Select(x =>
            {
                if (x.IsAbsolute)
                {
                    return(x.FullPath);
                }
                NormalizedPath containingInputPath = context.FileSystem.GetContainingInputPath(x);
                return(containingInputPath.IsNull ? null : containingInputPath.Combine(x).FullPath);
            })
                                                .Where(x => x != null);

            options.IncludePaths.AddRange(includePaths);
            ScssResult result = Scss.ConvertToCss(content, options);

            // Process the result
            NormalizedPath relativeDirectory = context.FileSystem.GetContainingInputPath(inputPath);
            NormalizedPath relativePath      = relativeDirectory.IsNull ? NormalizedPath.Null : relativeDirectory.GetRelativePath(inputPath);

            if (relativePath.IsNull)
            {
                relativePath = inputPath.FileName;
            }

            NormalizedPath cssPath     = relativePath.ChangeExtension("css");
            IDocument      cssDocument = input.Clone(
                cssPath,
                await context.GetContentProviderAsync(result.Css ?? string.Empty, MediaTypes.Css));

            // Generate a source map if requested
            if (_generateSourceMap && result.SourceMap != null)
            {
                NormalizedPath sourceMapPath     = relativePath.ChangeExtension("map");
                IDocument      sourceMapDocument = input.Clone(
                    sourceMapPath,
                    await context.GetContentProviderAsync(result.SourceMap));
                return(new[] { cssDocument, sourceMapDocument });
            }

            return(cssDocument.Yield());
        }