public void ShouldChangeFileName(string fullPath, string fileName, string expected)
            {
                // Given
                NormalizedPath path = new NormalizedPath(fullPath);

                // When
                NormalizedPath result = path.ChangeFileName(fileName);

                // Then
                result.FullPath.ShouldBe(expected);
            }
        public async Task <string> TryImportAsync(string requestedFile, string parentPath)
        {
            // Modify the requested file if we have an import path function
            string modifiedParentPath = null;

            if (_importPathFunc != null)
            {
                requestedFile      = _importPathFunc(requestedFile);
                modifiedParentPath = _importPathFunc(parentPath);
            }
            if (string.IsNullOrWhiteSpace(requestedFile))
            {
                return(null);
            }

            // Get the input relative path to the parent file
            // Make sure to try checking for a previously processed parent post-modification
            NormalizedPath parentFilePath    = new NormalizedPath(parentPath);
            NormalizedPath requestedFilePath = new NormalizedPath(requestedFile);

            if (parentFilePath.IsRelative &&
                !_parentAbsolutePaths.TryGetValue(parentFilePath, out parentFilePath) &&
                (modifiedParentPath == null || !_parentAbsolutePaths.TryGetValue(modifiedParentPath, out parentFilePath)))
            {
                // Relative parent path and no available absolute path, try with the relative path
                parentFilePath = new NormalizedPath(parentPath);
            }

            // Try to get the relative path to the parent file from inside the input virtual file system
            // But if the parent file isn't under an input path, just use it directly
            NormalizedPath containingInputPath = _fileSystem.GetContainingInputPath(parentFilePath);
            NormalizedPath parentRelativePath  = containingInputPath.IsNull
                ? parentFilePath
                : containingInputPath.GetRelativePath(parentFilePath);

            // Find the requested file by first combining with the parent
            NormalizedPath filePath = parentRelativePath.ChangeFileName(requestedFilePath);
            string         scss     = await GetFileVariationsAsync(filePath, requestedFilePath);

            if (scss != null)
            {
                return(scss);
            }

            // That didn't work so try it again as a relative path from the input folder
            scss = await GetFileVariationsAsync(requestedFilePath, requestedFilePath);

            if (!requestedFilePath.IsAbsolute && scss != null)
            {
                return(scss);
            }

            return(null);
        }
        private async Task <string> GetFileVariationsAsync(NormalizedPath filePath, NormalizedPath requestedFilePath)
        {
            // ...as specified
            string scss = await GetFileAsync(filePath, requestedFilePath);

            if (scss != null)
            {
                return(scss);
            }

            // ...with extension (if not already)
            if (!filePath.HasExtension || filePath.Extension != ".scss")
            {
                NormalizedPath extensionPath = filePath.AppendExtension(".scss");
                scss = await GetFileAsync(extensionPath, requestedFilePath);

                if (scss != null)
                {
                    return(scss);
                }

                // ...and with underscore prefix (if not already)
                if (!extensionPath.FileName.FullPath.StartsWith("_"))
                {
                    extensionPath = extensionPath.ChangeFileName("_" + extensionPath.FileName.FullPath);
                    scss          = await GetFileAsync(extensionPath, requestedFilePath);

                    if (scss != null)
                    {
                        return(scss);
                    }
                }
            }

            // ...with underscore prefix (if not already)
            if (!filePath.FileName.FullPath.StartsWith("_"))
            {
                filePath = filePath.ChangeFileName("_" + filePath.FileName.FullPath);
                scss     = await GetFileAsync(filePath, requestedFilePath);

                if (scss != null)
                {
                    return(scss);
                }
            }

            return(null);
        }
Esempio n. 4
0
        private IFile GetInputFile(NormalizedPath filePath)
        {
            // Find the requested file
            // ...as specified
            IFile file = _fileSystem.GetInputFile(filePath);

            if (file.Exists)
            {
                return(file);
            }

            // ...with extension (if not already)
            if (!filePath.HasExtension || filePath.Extension != ".less")
            {
                NormalizedPath extensionPath = filePath.AppendExtension(".less");
                IFile          extensionFile = _fileSystem.GetInputFile(extensionPath);
                if (extensionFile.Exists)
                {
                    return(extensionFile);
                }

                // ...and with underscore prefix (if not already)
                if (!extensionPath.FileName.FullPath.StartsWith("_"))
                {
                    extensionPath = extensionPath.ChangeFileName("_" + extensionPath.FileName.FullPath);
                    extensionFile = _fileSystem.GetInputFile(extensionPath);
                    if (extensionFile.Exists)
                    {
                        return(extensionFile);
                    }
                }
            }

            // ...with underscore prefix (if not already)
            if (!filePath.FileName.FullPath.StartsWith("_"))
            {
                filePath = filePath.ChangeFileName("_" + filePath.FileName.FullPath);
                IFile underscoreFile = _fileSystem.GetInputFile(filePath);
                if (underscoreFile.Exists)
                {
                    return(underscoreFile);
                }
            }

            // Can't find it, default to the original
            return(file);
        }
Esempio n. 5
0
        /// <inheritdoc />
        public override IDocument Execute(KeyValuePair <string, string>[] args, string content, IDocument document, IExecutionContext context)
        {
            // Get the included path relative to the document
            NormalizedPath includedPath = new NormalizedPath(args.SingleValue());

            if (_sourcePath.IsNull)
            {
                // Cache the source path for this shortcode instance since it'll be the same for all future shortcodes
                _sourcePath = document.GetPath("IncludeShortcodeSource", document.Source);
            }

            // Try to find the file relative to the current document path
            IFile includedFile = null;

            if (includedPath.IsRelative && !_sourcePath.IsNull)
            {
                includedFile = context.FileSystem.GetFile(_sourcePath.ChangeFileName(includedPath));
            }

            // If that didn't work, try relative to the input folder
            if (includedFile?.Exists != true)
            {
                includedFile = context.FileSystem.GetInputFile(includedPath);
            }

            // Get the included file
            if (!includedFile.Exists)
            {
                context.LogWarning($"Included file {includedPath.FullPath} does not exist");
                return(context.CreateDocument());
            }

            // Set the currently included shortcode source so nested includes can use it
            return(context
                   .CreateDocument(
                       new MetadataItems
            {
                { "IncludeShortcodeSource", includedFile.Path.FullPath }
            },
                       includedFile.GetContentProvider()));
        }
        /// <inheritdoc />
        public override async Task <ShortcodeResult> ExecuteAsync(KeyValuePair <string, string>[] args, string content, IDocument document, IExecutionContext context)
        {
            // See if this is a web include
            string included = args.SingleValue();

            if (included.StartsWith(Uri.UriSchemeHttp + "://") || included.StartsWith(Uri.UriSchemeHttps + "://"))
            {
                // This is a URI, so just get the web resource
                HttpResponseMessage response = await context.SendHttpRequestWithRetryAsync(included);

                if (!response.IsSuccessStatusCode)
                {
                    context.LogWarning($"Included web resource {included} returned {response.StatusCode}");
                    return(null);
                }

                // Got the resource, copy to a stream and create a document result
                using (Stream contentStream = await context.GetContentStreamAsync())
                {
                    await response.Content.CopyToAsync(contentStream);

                    return(contentStream);
                }
            }

            // Get the included path relative to the document
            NormalizedPath includedPath = new NormalizedPath(included);

            if (_sourcePath.IsNull)
            {
                // Cache the source path for this shortcode instance since it'll be the same for all future shortcodes
                _sourcePath = document.GetPath("IncludeShortcodeSource", document.Source);
            }

            // Try to find the file relative to the current document path
            IFile includedFile = null;

            if (includedPath.IsRelative && !_sourcePath.IsNull)
            {
                includedFile = context.FileSystem.GetFile(_sourcePath.ChangeFileName(includedPath));
            }

            // If that didn't work, try relative to the input folder
            if (includedFile?.Exists != true)
            {
                includedFile = context.FileSystem.GetInputFile(includedPath);
            }

            // Get the included file
            if (!includedFile.Exists)
            {
                context.LogWarning($"Included file {includedPath.FullPath} does not exist");
                return(null);
            }

            // Set the currently included shortcode source so nested includes can use it
            return(new ShortcodeResult(
                       includedFile.GetContentProvider(),
                       new MetadataItems
            {
                { "IncludeShortcodeSource", includedFile.Path.FullPath }
            }));
        }
Esempio n. 7
0
        // Returns null if the content wasn't modified
        private async Task <string> ProcessIncludesAsync(string content, NormalizedPath source, IExecutionContext context)
        {
            bool modified = false;

            int start = 0;

            while (start >= 0)
            {
                start = content.IndexOf("^\"", start, StringComparison.Ordinal);
                if (start >= 0)
                {
                    // Check if the include is escaped
                    if (start > 0 && content[start - 1] == '\\')
                    {
                        modified = true;
                        content  = content.Remove(start - 1, 1);
                        start++;
                    }
                    else
                    {
                        // This is a valid include
                        int end = content.IndexOf('\"', start + 2);
                        if (end > 0)
                        {
                            modified = true;

                            // Get the correct included path
                            NormalizedPath includedPath = new NormalizedPath(content.Substring(start + 2, end - (start + 2)));
                            if (includedPath.IsRelative)
                            {
                                if (source.IsNull)
                                {
                                    throw new ExecutionException($"Cannot include file at relative path {includedPath.FullPath} because document source is null");
                                }
                                includedPath = source.ChangeFileName(includedPath);
                            }

                            // Get and read the file content
                            IFile  includedFile    = context.FileSystem.GetFile(includedPath);
                            string includedContent = string.Empty;
                            if (!includedFile.Exists)
                            {
                                context.LogWarning($"Included file {includedFile.Path.FullPath} does not exist");
                            }
                            else
                            {
                                includedContent = await includedFile.ReadAllTextAsync();
                            }

                            // Recursively process include statements
                            if (_recursion)
                            {
                                string nestedContent = await ProcessIncludesAsync(includedContent, includedPath, context);

                                if (nestedContent != null)
                                {
                                    includedContent = nestedContent;
                                }
                            }

                            // Do the replacement
                            content = content.Remove(start, end - start + 1).Insert(start, includedContent);
                            start  += includedContent.Length;
                        }
                    }
                }
            }

            return(modified ? content : null);
        }