/// <summary> /// This will never return null. It will throw an exception for a null or blank relativePath. /// </summary> public TextFileContents Load(string relativePath) { if (string.IsNullOrWhiteSpace(relativePath)) { throw new ArgumentException("Null/blank relativePath specified"); } var initialFileContents = _contentLoader.Load(relativePath); var engine = new LessEngine( new Parser(), new DotLessCssPassThroughLogger(_logger, _reportedErrorBehaviour), true, // Compress false // Debug ); var markerIdLookup = new MarkerIdLookup(_markerIdRetriever()); engine.Plugins = new[] { new SelectorRewriterVisitorPluginConfigurator(markerIdLookup, _optionalTagNameToRemove) }; return(new TextFileContents( initialFileContents.RelativePath, initialFileContents.LastModified, engine.TransformToCss(initialFileContents.Content, null) )); }
public SelectorRewriterVisitorPlugin(MarkerIdLookup markerIdLookup, string optionalTagNameToRemove) { if (markerIdLookup == null) { throw new ArgumentNullException("markerIdLookup"); } _markerIdLookup = markerIdLookup; _optionalTagNameToRemove = optionalTagNameToRemove; }
public MarkerIdTidyingRuleset(NodeList <Selector> selectors, NodeList rules, MarkerIdLookup markerIdLookup, string optionalTagNameToRemove) : base(selectors, rules) { if (markerIdLookup == null) { throw new ArgumentNullException("markerIdLookup"); } _markerIdLookup = markerIdLookup; _optionalTagNameToRemove = optionalTagNameToRemove; }
public CombinedElementContent(MarkerIdLookup markerIdLookup) { if (markerIdLookup == null) { throw new ArgumentNullException("markerIdLookup"); } _markerIdLookup = markerIdLookup; _elements = new List <Element>(); _stringContentBuilder = new StringBuilder(); _contentIsTooLongToBeMarkerId = false; }
private IEnumerable <IEnumerable <Selector> > FilterPaths(IEnumerable <IEnumerable <Selector> > paths, MarkerIdLookup markerIdLookup) { if (paths == null) { throw new ArgumentNullException("paths"); } if (markerIdLookup == null) { throw new ArgumentNullException("markerIdLookup"); } var markerIdsAccountedFor = new HashSet <string>(); var combinedPaths = new List <Selector>(); foreach (var path in paths) { if (path == null) { throw new ArgumentException("Null reference encountered in paths set"); } var currentElementContent = new CombinedElementContent(markerIdLookup); var allElementInSelectorBuffer = new List <Element>(); Element[] markerIdElements = null; var selectorShouldBeIgnored = false; foreach (var selector in path) { if (selector == null) { throw new ArgumentException("Null reference encountered in selector set in paths"); } var isFirstElementInSelector = true; foreach (var element in selector.Elements) { if (element == null) { throw new ArgumentException("Null element reference encountered within selector set in paths"); } // The only time that a marker id should be present in a selector is if it's the last content (meaning that the current // selector is the one that the marker id is most specific for). If we have already identified marker id content in the // current selector and now we're encountering more content then this must be a selector to ignore (as the marker id // content was not right at the end). if (markerIdElements != null) { selectorShouldBeIgnored = true; break; } // We're potentially combining the elements from several distinct selectors into one long selector here, so ensure that // when elements from different selectors are combined that there is always some combinator character between them (a // blank string combinator will not work) Element elementToAdd; if (isFirstElementInSelector && (element.Combinator.Value == "") && allElementInSelectorBuffer.Any()) { elementToAdd = new Element(new Combinator(" "), element.Value); } else { elementToAdd = element; } // As we process the elements, we need to join up elements that form a single selector segment (eg. "#test1" and ".css_1") // to see if together they form a marker id. As soon as a combinator with a space is encountered, this is reset as this // indicates a new segment. if (elementToAdd.Combinator.Value == " ") { currentElementContent.Clear(); } currentElementContent.Add(element); // Test whether the current selector segment is a marker id var markerId = currentElementContent.TryToGetAsMarkerId(); if (markerId != null) { if (markerIdsAccountedFor.Contains(markerId)) { selectorShouldBeIgnored = true; break; } markerIdElements = currentElementContent.ToArray(); markerIdsAccountedFor.Add(markerId); } // If we haven't determined that we've encountered a selector to skip yet then keep building up the combined set of elements // for the current selector allElementInSelectorBuffer.Add(elementToAdd); isFirstElementInSelector = false; } if (selectorShouldBeIgnored) { break; } } if (!selectorShouldBeIgnored) { // If the selector is one that we've decided that we want, there's still potentially more work to do. If it's a selector that // relates to a marker id, we need to ensure that we only include the marker id content (eg. if we have "div h2 #test1.css_12", // the only important information is the marker "#test1.css_12"). There may be multiple selectors for the same marker id, we // only want one of them to be included in the final output. If the selector does not relate to a marker id then we need to // ensure that any elements that relate to the "optionalTagNameToRemove" (where non-null) are removed. if (markerIdElements == null) { if (_optionalTagNameToRemove == null) { combinedPaths.Add(new Selector(allElementInSelectorBuffer)); } else { combinedPaths.Add(new Selector(allElementInSelectorBuffer.Where(e => e.Value != _optionalTagNameToRemove))); } } else { combinedPaths.Add(new Selector(markerIdElements)); } } } return(combinedPaths.Select(selector => new[] { selector })); }