Exemplo n.º 1
0
        /// <summary>
        /// This will never return null, it will raise an exception if unable to satisfy the request
        /// </summary>
        public ITextFileLoader Get()
        {
            var             scopingHtmlTagReplaceString = "REPLACEME";
            ITextFileLoader singleFileLoader            = new LessCssOpeningHtmlTagRenamer(
                _contentLoader,
                scopingHtmlTagReplaceString
                );
            var sourceMappingMarkerIdGenerator = new SourceMappingMarkerIdGenerator();

            if (_sourceMappingMarkerInjection == SourceMappingMarkerInjectionOptions.Inject)
            {
                singleFileLoader = new LessCssLineNumberingTextFileLoader(
                    new LessCssCommentRemovingTextFileLoader(singleFileLoader),
                    sourceMappingMarkerIdGenerator.MarkerGenerator,
                    selector => selector != scopingHtmlTagReplaceString                     // Don't insert marker ids on wrapper selectors that will be removed
                    );
            }
            return(new MediaQueryGroupingCssLoader(
                       new DotLessCssCssLoader(
                           new SameFolderImportFlatteningCssLoader(
                               singleFileLoader,
                               _sourceMappingMarkerInjection == SourceMappingMarkerInjectionOptions.Inject
                                                ? SameFolderImportFlatteningCssLoader.ContentLoaderCommentRemovalBehaviourOptions.CommentsAreAlreadyRemoved
                                                : SameFolderImportFlatteningCssLoader.ContentLoaderCommentRemovalBehaviourOptions.ContentIsUnprocessed,
                               _errorBehaviour,
                               _errorBehaviour,
                               _logger
                               ),
                           () => sourceMappingMarkerIdGenerator.GetInsertedMarkerIds(),
                           scopingHtmlTagReplaceString,
                           _errorBehaviour,
                           _logger
                           )
                       ));
        }
        /// <summary>
        /// This will never return null, it will raise an exception if unable to satisfy the request
        /// </summary>
        public ITextFileLoader Get()
        {
            ITextFileLoader singleFileLoader = new LessCssKeyFrameScoper(_contentLoader);
            var             sourceMappingMarkerIdGenerator = new SourceMappingMarkerIdGenerator();

            if (_sourceMappingMarkerInjection == SourceMappingMarkerInjectionOptions.Inject)
            {
                singleFileLoader = new LessCssLineNumberingTextFileLoader(
                    new LessCssCommentRemovingTextFileLoader(singleFileLoader),
                    sourceMappingMarkerIdGenerator.MarkerGenerator,
                    null                     // optionalSelectorMarkerInsertionCondition (null => insert markers for all selectors)
                    );
            }
            return(new DotLessCssCssLoader(
                       new SameFolderImportFlatteningCssLoader(
                           singleFileLoader,
                           _sourceMappingMarkerInjection == SourceMappingMarkerInjectionOptions.Inject
                                                ? SameFolderImportFlatteningCssLoader.ContentLoaderCommentRemovalBehaviourOptions.CommentsAreAlreadyRemoved
                                                : SameFolderImportFlatteningCssLoader.ContentLoaderCommentRemovalBehaviourOptions.ContentIsUnprocessed,
                           _errorBehaviour,
                           _errorBehaviour,
                           _logger
                           ),
                       () => sourceMappingMarkerIdGenerator.GetInsertedMarkerIds(),
                       null,          // optionalTagNameToRemove (null => no selectors need removing)
                       _errorBehaviour,
                       _logger
                       ));
        }
Exemplo n.º 3
0
        /// <summary>
        /// This will throw an exception for null content or if otherwise unable to satisfy the request, it will never return null
        /// </summary>
        private string Process(string relativePath, string content)
        {
            if (string.IsNullOrWhiteSpace(relativePath))
            {
                throw new ArgumentException($"Null/blank {nameof(relativePath)} specified");
            }
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            relativePath = relativePath.Trim();
            if (relativePath.EndsWith(".css", StringComparison.OrdinalIgnoreCase))
            {
                relativePath = relativePath.Substring(0, relativePath.Length - 4);
            }
            else if (relativePath.EndsWith(".less", StringComparison.OrdinalIgnoreCase))
            {
                relativePath = relativePath.Substring(0, relativePath.Length - 5);
            }

            var prefixToInsert = SourceMappingMarkerIdGenerator.TryToGetHtmlIdFriendlyVersion(relativePath);

            if (prefixToInsert == null)
            {
                // If the path string doesn't contain any content that may be used as a "custom ident" then make something up because we need to use something as
                // the prefix, otherwise the animation won't be scoped to the current files
                prefixToInsert = "scope" + relativePath.GetHashCode();
            }

            // Note: Since we have enumerate the segments set twice (if any animation names are found to be renamed) then I considered calling ToArray on it so that the parsing
            // work would only be done once - however, this means that the content has to be full loaded into an array in memory and I don't have any information that indicates
            // that the additional memory use would be a worthwhile tradeoff for the double-parsing work (the parsing isn't very expensive and so doing it twice isn't necessarily
            // the worst thing in the world). If no animation names are found that need to be renamed then the parsing work will only be performed once. Similar logic is applied
            // to the result of the RewriteKeyFrameNames method - it needs to be executed once to determine whether any animation names need to be changed and (if any are found)
            // then it will be executed a second time when RewriteAnimationNames is called (but the RewriteKeyFrameNames work isn't very expensive and so there isn't necessarily
            // any harm in doing it twice).
            var segments       = Parser.ParseLESS(content);
            var rewrittenNames = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);            // Case insensitive (see https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)

            segments = RewriteKeyFrameNames(
                segments,
                nestedAnimationName =>
            {
                var rewrittedName = prefixToInsert + "_" + nestedAnimationName;
                rewrittenNames[nestedAnimationName] = rewrittedName;
                return(rewrittedName);
            }
                );
            ForceEvaluation(segments);
            if (!rewrittenNames.Any())
            {
                return(content);
            }
            segments = RewriteAnimationNames(
                segments,
                animationName => rewrittenNames.ContainsKey(animationName) ? rewrittenNames[animationName] : animationName
                );
            var rewrittenContentBuilder = new StringBuilder();

            foreach (var segment in segments)
            {
                rewrittenContentBuilder.Append(segment.Value);
            }
            return(rewrittenContentBuilder.ToString());
        }