private void RewriteScriptTags(ResponseAnalysisContext context, string html) { foreach (var index in FastHtmlParser.FindAllTagIndexes(html, "script")) { var type = FastHtmlParser.GetAttributeValueAtTag(html, "type", index); if (!type.Equals("text/javascript", StringComparison.OrdinalIgnoreCase)) { continue; } // get content var inner = FastHtmlParser.GetInnerHtml(html, index, "script"); if (inner == null || inner.Value.Trim().Length == 0) { continue; } // compute hash var inline = ContentHashCache.GetOrAdd(inner.Value.Trim().TrimHtmlCdata().Trim().Value, v => CreateContent(v)); InlineContentService.TryAddScriptByHash(inline.Hash, inline.Content); // add change context.AddChange(TextChange.Remove(html, inner.Value.Offset, inner.Value.Length)); context.AddChange(FastHtmlParser.CreateInsertAttributeChange(html, index, "script", "src", $"/.waf/scripts/{inline.Hash}")); } }
private void RewriteStyleAttributes(ResponseAnalysisContext context, string html) { var headIndex = html.IndexOf("</head>", StringComparison.OrdinalIgnoreCase); if (headIndex == -1) { return; } SortedList <string, StringSegment> inlineStyles = null; foreach (var index in FastHtmlParser.FindAllAttributeIndexes(html, "style")) { // get content var inner = FastHtmlParser.GetAttributeValueAtName(html, "style", index); if (inner.Length == 0) { continue; } if (inlineStyles == null) { inlineStyles = new SortedList <string, StringSegment>(); } // compute hash var hash = ComputeHash(inner.Trim()); if (!inlineStyles.ContainsKey(hash)) { inlineStyles.Add(hash, inner); } // add change context.AddChange(TextChange.Remove(html, index, inner.Offset + inner.Length + 1 - index)); var tagIndex = FastHtmlParser.FindOpenTagAtAttribute(html, index); var classAttribute = FastHtmlParser.GetAttributeValueAtTag(html, "class", tagIndex); if (classAttribute.Length > 0) { context.AddChange(TextChange.Insert(html, classAttribute.Offset + classAttribute.Length, "_" + hash)); } else { context.AddChange(FastHtmlParser.CreateInsertAttributeChange(html, tagIndex, "class", "_" + hash)); } } // assemble inline styles if (inlineStyles != null && inlineStyles.Count > 0) { var hashBuilder = new InplaceStringBuilder(inlineStyles.Count * HashBytes * 2); foreach (var entry in inlineStyles) { hashBuilder.Append(entry.Key); } var hash = ComputeHash(hashBuilder.ToString()); if (!InlineContentService.ContainsStyleByHash(hash)) { var contentBuilder = StringBuilderPool.Get(); foreach (var entry in inlineStyles) { contentBuilder.Append('.'); contentBuilder.Append('_'); contentBuilder.Append(entry.Key); contentBuilder.Append('{'); contentBuilder.Append(entry.Value.Value); contentBuilder.Append('}'); } InlineContentService.TryAddStyleByHash(hash, contentBuilder.ToString()); StringBuilderPool.Return(contentBuilder); } var tag = $"<link rel=\"stylesheet\" href=\"/.waf/styles/{hash}\" type=\"text/css\" />"; context.AddChange(TextChange.Insert(html, headIndex, tag)); } }