public void CachesMatchResults()
        {
            // Arrange
            var changeToken  = new Mock <IChangeToken>();
            var fileProvider = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));

            Mock.Get(fileProvider).Setup(f => f.Watch(It.IsAny <string>())).Returns(changeToken.Object);
            var value = new Mock <ICacheEntry>();

            value.Setup(c => c.Value).Returns(null);
            value.Setup(c => c.ExpirationTokens).Returns(new List <IChangeToken>());
            var cache = MakeCache();

            Mock.Get(cache).Setup(c => c.CreateEntry(
                                      /*key*/ It.IsAny <object>()))
            .Returns((object key) => value.Object)
            .Verifiable();
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                              url => Assert.Equal("/blank.css", url),
                              url => Assert.Equal("/site.css", url));
            Mock.Get(cache).VerifyAll();
        }
예제 #2
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);

            if (fallbackSrcs.Count > 0)
            {
                // Build the <script> tag that checks the test method and if it fails, renders the extra script.
                builder.AppendHtml(Environment.NewLine)
                .AppendHtml("<script>(")
                .AppendHtml(FallbackTestExpression)
                .AppendHtml("||document.write(\"");

                foreach (var src in fallbackSrcs)
                {
                    // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                    Debug.Assert(src != null);

                    StringWriter.Write("<script");

                    var addSrc = true;

                    // Perf: Avoid allocating enumerator
                    for (var i = 0; i < attributes.Count; i++)
                    {
                        var attribute = attributes[i];
                        if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                        {
                            StringWriter.Write(' ');
                            attribute.WriteTo(StringWriter, HtmlEncoder);
                        }
                        else
                        {
                            addSrc = false;
                            WriteVersionedSrc(attribute.Name, src, attribute.ValueStyle, StringWriter);
                        }
                    }

                    if (addSrc)
                    {
                        WriteVersionedSrc(SrcAttributeName, src, HtmlAttributeValueStyle.DoubleQuotes, StringWriter);
                    }

                    StringWriter.Write("></script>");
                }

                var stringBuilder = StringWriter.GetStringBuilder();
                var scriptTags    = stringBuilder.ToString();
                stringBuilder.Clear();
                var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);
                builder.AppendHtml(encodedScriptTags);

                builder.AppendHtml("\"));</script>");
            }
        }
예제 #3
0
 private void EnsureGlobbingUrlBuilder()
 {
     if (GlobbingUrlBuilder == null)
     {
         GlobbingUrlBuilder = new GlobbingUrlBuilder(
             HostingEnvironment.WebRootFileProvider,
             Cache,
             ViewContext.HttpContext.Request.PathBase);
     }
 }
예제 #4
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);

            if (fallbackSrcs.Count > 0)
            {
                // Build the <script> tag that checks the test method and if it fails, renders the extra script.
                builder.AppendHtml(Environment.NewLine)
                .AppendHtml("<script>(")
                .AppendHtml(FallbackTestExpression)
                .AppendHtml("||document.write(\"");

                foreach (var src in fallbackSrcs)
                {
                    // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                    Debug.Assert(src != null);

                    builder.AppendHtml("<script");

                    var addSrc = true;

                    // Perf: Avoid allocating enumerator
                    for (var i = 0; i < attributes.Count; i++)
                    {
                        var attribute = attributes[i];
                        if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                        {
                            var encodedKey     = JavaScriptEncoder.Encode(attribute.Name);
                            var attributeValue = GetAttributeValue(attribute.Value);
                            var encodedValue   = JavaScriptEncoder.Encode(attributeValue);

                            AppendAttribute(builder, encodedKey, encodedValue, escapeQuotes: true);
                        }
                        else
                        {
                            addSrc = false;
                            AppendEncodedVersionedSrc(attribute.Name, src, builder, generateForDocumentWrite: true);
                        }
                    }

                    if (addSrc)
                    {
                        AppendEncodedVersionedSrc(SrcAttributeName, src, builder, generateForDocumentWrite: true);
                    }

                    builder.AppendHtml("><\\/script>");
                }

                builder.AppendHtml("\"));</script>");
            }
        }
        public void ReturnsOnlyStaticUrlWhenPatternDoesntFindAnyMatches()
        {
            // Arrange
            var fileProvider       = MakeFileProvider();
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

            // Assert
            Assert.Collection(urlList, url => Assert.Equal("/site.css", url));
        }
        public void BuildUrlList_AddsToMemoryCache_WithSizeLimit()
        {
            // Arrange
            var cacheEntry = Mock.Of <ICacheEntry>(m => m.ExpirationTokens == new List <IChangeToken>());
            var cache      = Mock.Of <IMemoryCache>(m => m.CreateEntry(It.IsAny <object>()) == cacheEntry);

            var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

            // Assert
            Assert.Equal(38, cacheEntry.Size);
        }
        public void DedupesStaticUrlAndPatternMatches()
        {
            // Arrange
            var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList("/site.css", "**/*.css", excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                              url => Assert.Equal("/site.css", url),
                              url => Assert.Equal("/blank.css", url));
        }
        public void HandlesCommaSeparatedPatterns(string includePattern, string[] expectedOutput)
        {
            // Arrange
            var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.js", "site2.txt", "site.js"));
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: includePattern,
                excludePattern: null);

            // Assert
            Assert.Equal(expectedOutput, urlList, StringComparer.Ordinal);
        }
        public void OrdersGlobbedMatchResultsCorrectly(string staticUrl, FileNode dirStructure, string[] expectedPaths)
        {
            // Arrange
            var fileProvider       = MakeFileProvider(dirStructure);
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(staticUrl, "**/*.*", excludePattern: null);

            // Assert
            var collectionAssertions = expectedPaths.Select <string, Action <string> >(expected =>
                                                                                       actual => Assert.Equal(expected, actual));

            Assert.Collection(urlList, collectionAssertions.ToArray());
        }
        public void ResolvesMatchedUrlsAgainstPathBase(string pathBase)
        {
            // Arrange
            var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = new PathString(pathBase);
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(urlList,
                              url => Assert.Equal($"{pathBase}/blank.css", url),
                              url => Assert.Equal($"{pathBase}/site.css", url));
        }
        public void UsesCachedMatchResults()
        {
            // Arrange
            var fileProvider = MakeFileProvider();
            var expected     = new List <string> {
                "/blank.css", "/site.css"
            };
            var cache              = MakeCache(result: expected);
            var requestPathBase    = PathString.Empty;
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            // Act
            var actual = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: "**/*.css",
                excludePattern: null);

            // Assert
            Assert.Collection(actual,
                              url => Assert.Equal("/blank.css", url),
                              url => Assert.Equal("/site.css", url));
        }
예제 #12
0
        private void BuildGlobbedScriptTags(
            TagHelperAttributeList attributes,
            TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            // Build a <script> tag for each matched src as well as the original one in the source file
            var urls = GlobbingUrlBuilder.BuildUrlList(null, SrcInclude, SrcExclude);

            foreach (var url in urls)
            {
                // "url" values come from bound attributes and globbing. Must always be non-null.
                Debug.Assert(url != null);

                if (string.Equals(url, Src, StringComparison.OrdinalIgnoreCase))
                {
                    // Don't build duplicate script tag for the original source url.
                    continue;
                }

                BuildScriptTag(url, attributes, builder);
            }
        }
예제 #13
0
        private void BuildGlobbedLinkTags(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            // Build a <link /> tag for each matched href.
            var urls = GlobbingUrlBuilder.BuildUrlList(null, HrefInclude, HrefExclude);

            for (var i = 0; i < urls.Count; i++)
            {
                var url = urls[i];

                // "url" values come from bound attributes and globbing. Must always be non-null.
                Debug.Assert(url != null);

                if (string.Equals(Href, url, StringComparison.OrdinalIgnoreCase))
                {
                    // Don't build duplicate link tag for the original href url.
                    continue;
                }

                BuildLinkTag(url, attributes, builder);
            }
        }
        public void TrimsLeadingTildeAndSlashFromPatterns(string prefix)
        {
            // Arrange
            var fileProvider       = MakeFileProvider(MakeDirectoryContents("site.css", "blank.css"));
            var cache              = new MemoryCache(new MemoryCacheOptions());
            var requestPathBase    = PathString.Empty;
            var includePatterns    = new List <string>();
            var excludePatterns    = new List <string>();
            var matcher            = MakeMatcher(includePatterns, excludePatterns);
            var globbingUrlBuilder = new GlobbingUrlBuilder(fileProvider, cache, requestPathBase);

            globbingUrlBuilder.MatcherBuilder = () => matcher;

            // Act
            var urlList = globbingUrlBuilder.BuildUrlList(
                staticUrl: null,
                includePattern: $"{prefix}**/*.css",
                excludePattern: $"{prefix}**/*.min.css");

            // Assert
            Assert.Collection(includePatterns, pattern => Assert.Equal("**/*.css", pattern));
            Assert.Collection(excludePatterns, pattern => Assert.Equal("**/*.min.css", pattern));
        }
예제 #15
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();
            var fallbackHrefs = GlobbingUrlBuilder.BuildUrlList(
                FallbackHref,
                FallbackHrefInclude,
                FallbackHrefExclude);

            if (fallbackHrefs.Count == 0)
            {
                return;
            }

            builder.AppendHtml(HtmlString.NewLine);

            // Build the <meta /> tag that's used to test for the presence of the stylesheet
            builder
            .AppendHtml("<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"")
            .Append(FallbackTestClass)
            .AppendHtml("\" />");

            // Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
            // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
            // indicating that the primary stylesheet failed to load.
            // GetEmbeddedJavaScript returns JavaScript to which we add '"{0}","{1}",{2});'
            builder
            .AppendHtml("<script>")
            .AppendHtml(JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName))
            .AppendHtml("\"")
            .AppendHtml(JavaScriptEncoder.Encode(FallbackTestProperty))
            .AppendHtml("\",\"")
            .AppendHtml(JavaScriptEncoder.Encode(FallbackTestValue))
            .AppendHtml("\",");

            AppendFallbackHrefs(builder, fallbackHrefs);

            builder.AppendHtml(", \"");

            // Perf: Avoid allocating enumerator
            for (var i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                if (string.Equals(attribute.Name, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                if (SuppressFallbackIntegrity && string.Equals(attribute.Name, IntegrityAttributeName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                attribute.WriteTo(StringWriter, HtmlEncoder);
                StringWriter.Write(' ');
            }

            var stringBuilder = StringWriter.GetStringBuilder();
            var scriptTags    = stringBuilder.ToString();

            stringBuilder.Clear();
            var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);

            builder.AppendHtml(encodedScriptTags);

            builder.AppendHtml("\");</script>");
        }