private void CollectCssDeclarations(INode rootNode, ResourceResolver resourceResolver) { this.css = new CssStyleSheet(); LinkedList <INode> q = new LinkedList <INode>(); if (rootNode != null) { q.Add(rootNode); } while (!q.IsEmpty()) { INode currentNode = q.JRemoveFirst(); if (currentNode is IElementNode) { IElementNode headChildElement = (IElementNode)currentNode; if (SvgConstants.Tags.STYLE.Equals(headChildElement.Name())) { //XML parser will parse style tag contents as text nodes if (!currentNode.ChildNodes().IsEmpty() && (currentNode.ChildNodes()[0] is IDataNode || currentNode.ChildNodes ()[0] is ITextNode)) { String styleData; if (currentNode.ChildNodes()[0] is IDataNode) { styleData = ((IDataNode)currentNode.ChildNodes()[0]).GetWholeData(); } else { styleData = ((ITextNode)currentNode.ChildNodes()[0]).WholeText(); } CssStyleSheet styleSheet = CssStyleSheetParser.Parse(styleData); //TODO (DEVSIX-2263): media query wrap //styleSheet = wrapStyleSheetInMediaQueryIfNecessary(headChildElement, styleSheet); this.css.AppendCssStyleSheet(styleSheet); } } else { if (SvgCssUtils.IsStyleSheetLink(headChildElement)) { String styleSheetUri = headChildElement.GetAttribute(SvgConstants.Attributes.HREF); try { Stream stream = resourceResolver.RetrieveStyleSheet(styleSheetUri); byte[] bytes = StreamUtil.InputStreamToArray(stream); CssStyleSheet styleSheet = CssStyleSheetParser.Parse(new MemoryStream(bytes), resourceResolver.ResolveAgainstBaseUri (styleSheetUri).ToExternalForm()); this.css.AppendCssStyleSheet(styleSheet); } catch (System.IO.IOException exc) { ILog logger = LogManager.GetLogger(typeof(iText.Svg.Css.Impl.SvgStyleResolver)); logger.Error(iText.StyledXmlParser.LogMessageConstant.UNABLE_TO_PROCESS_EXTERNAL_CSS_FILE, exc); } } } } foreach (INode child in currentNode.ChildNodes()) { if (child is IElementNode) { q.Add(child); } } } }
/* (non-Javadoc) * @see com.itextpdf.html2pdf.css.resolve.ICssResolver#resolveStyles(com.itextpdf.html2pdf.html.node.INode, com.itextpdf.html2pdf.css.resolve.CssContext) */ private IDictionary <String, String> ResolveStyles(INode element, CssContext context) { IList <CssRuleSet> ruleSets = new List <CssRuleSet>(); ruleSets.Add(new CssRuleSet(null, UserAgentCss.GetStyles(element))); if (element is IElementNode) { ruleSets.Add(new CssRuleSet(null, HtmlStylesToCssConverter.Convert((IElementNode)element))); } ruleSets.AddAll(cssStyleSheet.GetCssRuleSets(element, deviceDescription)); if (element is IElementNode) { String styleAttribute = ((IElementNode)element).GetAttribute(AttributeConstants.STYLE); if (styleAttribute != null) { ruleSets.Add(new CssRuleSet(null, CssRuleSetParser.ParsePropertyDeclarations(styleAttribute))); } } IDictionary <String, String> elementStyles = CssStyleSheet.ExtractStylesFromRuleSets(ruleSets); if (CssConstants.CURRENTCOLOR.Equals(elementStyles.Get(CssConstants.COLOR))) { // css-color-3/#currentcolor: // If the ‘currentColor’ keyword is set on the ‘color’ property itself, it is treated as ‘color: inherit’. elementStyles.Put(CssConstants.COLOR, CssConstants.INHERIT); } String parentFontSizeStr = null; if (element.ParentNode() is IStylesContainer) { IStylesContainer parentNode = (IStylesContainer)element.ParentNode(); IDictionary <String, String> parentStyles = parentNode.GetStyles(); if (parentStyles == null && !(element.ParentNode() is IDocumentNode)) { ILog logger = LogManager.GetLogger(typeof(iText.Html2pdf.Css.Resolve.DefaultCssResolver)); logger.Error(iText.Html2pdf.LogMessageConstant.ERROR_RESOLVING_PARENT_STYLES); } if (parentStyles != null) { foreach (KeyValuePair <String, String> entry in parentStyles) { MergeParentCssDeclaration(elementStyles, entry.Key, entry.Value, parentStyles); } parentFontSizeStr = parentStyles.Get(CssConstants.FONT_SIZE); } } String elementFontSize = elementStyles.Get(CssConstants.FONT_SIZE); if (CssUtils.IsRelativeValue(elementFontSize) || CssConstants.LARGER.Equals(elementFontSize) || CssConstants .SMALLER.Equals(elementFontSize)) { float baseFontSize; if (CssUtils.IsRemValue(elementFontSize)) { baseFontSize = context.GetRootFontSize(); } else { if (parentFontSizeStr == null) { baseFontSize = FontStyleApplierUtil.ParseAbsoluteFontSize(CssDefaults.GetDefaultValue(CssConstants.FONT_SIZE )); } else { baseFontSize = CssUtils.ParseAbsoluteLength(parentFontSizeStr); } } float absoluteFontSize = FontStyleApplierUtil.ParseRelativeFontSize(elementFontSize, baseFontSize); // Format to 4 decimal places to prevent differences between Java and C# elementStyles.Put(CssConstants.FONT_SIZE, DecimalFormatUtil.FormatNumber(absoluteFontSize, "0.####") + CssConstants .PT); } else { elementStyles.Put(CssConstants.FONT_SIZE, Convert.ToString(FontStyleApplierUtil.ParseAbsoluteFontSize(elementFontSize ), System.Globalization.CultureInfo.InvariantCulture) + CssConstants.PT); } // Update root font size if (element is IElementNode && TagConstants.HTML.Equals(((IElementNode)element).Name())) { context.SetRootFontSize(elementStyles.Get(CssConstants.FONT_SIZE)); } ICollection <String> keys = new HashSet <String>(); foreach (KeyValuePair <String, String> entry in elementStyles) { if (CssConstants.INITIAL.Equals(entry.Value) || CssConstants.INHERIT.Equals(entry.Value)) { // if "inherit" is not resolved till now, parents don't have it keys.Add(entry.Key); } } foreach (String key in keys) { elementStyles.Put(key, CssDefaults.GetDefaultValue(key)); } // This is needed for correct resolving of content property, so doing it right here CounterProcessorUtil.ProcessCounters(elementStyles, context, element); ResolveContentProperty(elementStyles, element, context); return(elementStyles); }
/// <summary> /// Wraps a /// <see cref="iText.StyledXmlParser.Css.Media.CssMediaRule"/> /// into the style sheet if the head child element has a media attribute. /// </summary> /// <param name="headChildElement">the head child element</param> /// <param name="styleSheet">the style sheet</param> /// <returns>the css style sheet</returns> private CssStyleSheet WrapStyleSheetInMediaQueryIfNecessary(IElementNode headChildElement, CssStyleSheet styleSheet ) { String mediaAttribute = headChildElement.GetAttribute(AttributeConstants.MEDIA); if (mediaAttribute != null && mediaAttribute.Length > 0) { CssMediaRule mediaRule = new CssMediaRule(mediaAttribute); mediaRule.AddStatementsToBody(styleSheet.GetStatements()); styleSheet = new CssStyleSheet(); styleSheet.AddStatement(mediaRule); } return(styleSheet); }
/// <summary> /// Creates a /// <see cref="SvgStyleResolver"/> /// with a given default CSS. /// </summary> /// <param name="defaultCssStream">the default CSS</param> public SvgStyleResolver(Stream defaultCssStream) { this.css = CssStyleSheetParser.Parse(defaultCssStream); }
internal CssRule(CssStyleSheet parentStyleSheet) { ParentStyleSheet = parentStyleSheet; }
public virtual void PagesInCountersSpacesPresenceTest() { CssStyleSheet styleSheet = CssStyleSheetParser.Parse(".x::before { content: counters( pages,'.') }"); NUnit.Framework.Assert.IsTrue(CssStyleSheetAnalyzer.CheckPagesCounterPresence(styleSheet)); }
public virtual void CounterWithoutPagesTest() { CssStyleSheet styleSheet = CssStyleSheetParser.Parse(".x::before { content: counter(othercounter) }"); NUnit.Framework.Assert.IsFalse(CssStyleSheetAnalyzer.CheckPagesCounterPresence(styleSheet)); }
/// <summary> /// Takes a text source and transforms it into a CSS sheet. /// </summary> internal ICssStyleSheet ParseStylesheet(TextSource source) { var sheet = new CssStyleSheet(this); return(ParseStylesheet(sheet, source)); }
public virtual void SimpleNegativeTest() { CssStyleSheet styleSheet = CssStyleSheetParser.Parse("* { color: red; }"); NUnit.Framework.Assert.IsFalse(CssStyleSheetAnalyzer.CheckPagesCounterPresence(styleSheet)); }
/// <summary>Helper method to check if non-page(s) target-counter(s) is present anywhere in the CSS.</summary> /// <remarks> /// Helper method to check if non-page(s) target-counter(s) is present anywhere in the CSS. /// If presence is detected, it may require additional treatment /// </remarks> /// <param name="styleSheet">CSS stylesheet to analyze</param> /// <returns> /// <c>true</c> in case any non-page(s) target-counter(s) are present in CSS declarations, /// or <c>false</c> otherwise /// </returns> public static bool CheckNonPagesTargetCounterPresence(CssStyleSheet styleSheet) { return(CheckNonPagesTargetCounterPresence(styleSheet.GetStatements())); }
public void AddCssStyleSheet(CssStyleSheet ss) { styleSheets.Add(ss); }
internal virtual void SetStyleSheet(CssStyleSheet aSheet) { mSheet = aSheet; }
public virtual void SrcPropertyTest() { String fontSrc = "web-fonts/droid-serif-invalid."; CssStyleSheet styleSheet = CssStyleSheetParser.Parse(new FileStream(sourceFolder + "srcs.css", FileMode.Open , FileAccess.Read)); CssFontFaceRule fontFaceRule = (CssFontFaceRule)styleSheet.GetStatements()[0]; CssDeclaration src = fontFaceRule.GetProperties()[0]; NUnit.Framework.Assert.AreEqual("src", src.GetProperty(), "src expected"); String[] sources = iText.IO.Util.StringUtil.Split(src.GetExpression(), ","); NUnit.Framework.Assert.AreEqual(27, sources.Length, "27 sources expected"); for (int i = 0; i < sources.Length; i++) { Match m = iText.IO.Util.StringUtil.Match(FontFace.FontFaceSrc.UrlPattern, sources[i]); NUnit.Framework.Assert.IsTrue(m.Success, "Expression doesn't match pattern: " + sources[i]); String format = iText.IO.Util.StringUtil.Group(m, FontFace.FontFaceSrc.FormatGroup); String source2 = MessageFormatUtil.Format("{0}({1}){2}", iText.IO.Util.StringUtil.Group(m, FontFace.FontFaceSrc .TypeGroup), iText.IO.Util.StringUtil.Group(m, FontFace.FontFaceSrc.UrlGroup), format != null ? MessageFormatUtil .Format(" format({0})", format) : ""); String url = FontFace.FontFaceSrc.Unquote(iText.IO.Util.StringUtil.Group(m, FontFace.FontFaceSrc.UrlGroup) ); NUnit.Framework.Assert.IsTrue(url.StartsWith(fontSrc), "Invalid url: " + url); NUnit.Framework.Assert.IsTrue(format == null || FontFace.FontFaceSrc.ParseFormat(format) != FontFace.FontFormat .None, "Invalid format: " + format); NUnit.Framework.Assert.AreEqual(sources[i], source2, "Group check fails: "); FontFace.FontFaceSrc fontFaceSrc = FontFace.FontFaceSrc.Create(sources[i]); NUnit.Framework.Assert.IsTrue(fontFaceSrc.src.StartsWith(fontSrc), "Invalid url: " + fontSrc); String type = "url"; if (fontFaceSrc.isLocal) { type = "local"; } NUnit.Framework.Assert.IsTrue(sources[i].StartsWith(type), "Type '" + type + "' expected: " + sources[i]); switch (fontFaceSrc.format) { case FontFace.FontFormat.OpenType: { NUnit.Framework.Assert.IsTrue(sources[i].Contains("opentype"), "Format " + fontFaceSrc.format + " expected: " + sources[i]); break; } case FontFace.FontFormat.TrueType: { NUnit.Framework.Assert.IsTrue(sources[i].Contains("truetype"), "Format " + fontFaceSrc.format + " expected: " + sources[i]); break; } case FontFace.FontFormat.SVG: { NUnit.Framework.Assert.IsTrue(sources[i].Contains("svg"), "Format " + fontFaceSrc.format + " expected: " + sources[i]); break; } case FontFace.FontFormat.None: { NUnit.Framework.Assert.IsFalse(sources[i].Contains("format("), "Format " + fontFaceSrc.format + " expected: " + sources[i]); break; } } } }
/** -------------------------------------------------------------------- **/ private async Task _ProcessCssPage() { MacroscopeHttpTwoClient Client = this.DocCollection.GetJobMaster().GetHttpClient(); MacroscopeHttpTwoClientResponse Response = null; string ResponseErrorCondition = null; DebugMsg(string.Format("ProcessCssPage: {0}", "")); try { Response = await Client.Get( this.GetUri(), this.ConfigureCssPageRequestHeadersCallback, this.PostProcessRequestHttpHeadersCallback ); } catch (MacroscopeDocumentException ex) { this.DebugMsg(string.Format("_ProcessCssPage :: MacroscopeDocumentException: {0}", ex.Message)); ResponseErrorCondition = ex.Message; this.SetStatusCode(HttpStatusCode.BadRequest); this.AddRemark("_ProcessCssPage", ex.Message); } catch (Exception ex) { this.DebugMsg(string.Format("_ProcessCssPage :: Exception: {0}", ex.Message)); ResponseErrorCondition = ex.Message; this.SetStatusCode(HttpStatusCode.BadRequest); this.AddRemark("_ProcessCssPage", ex.Message); } /** Set Base URL ----------------------------------------------------- **/ if (Response != null) { Uri CssUri = this.GetUri(); string CssLocalPath = CssUri.LocalPath; string CssPath = System.IO.Path.GetDirectoryName(CssLocalPath); Uri NewCssUri = new Uri(new UriBuilder(scheme: CssUri.Scheme, host: CssUri.Host, port: CssUri.Port, pathValue: CssPath).ToString()); this.SetBaseHref(NewCssUri.ToString()); } /** Process The Response Body ---------------------------------------- **/ if (Response != null) { string RawData = ""; this.ProcessResponseHttpHeaders(Response: Response); /** Get Response Body ---------------------------------------------- **/ try { DebugMsg(string.Format("MIME TYPE: {0}", this.MimeType)); RawData = Response.GetContentAsString(); this.SetContentLength(Length: RawData.Length); // May need to find bytes length this.SetWasDownloaded(true); } catch (Exception ex) { DebugMsg(string.Format("Exception: {0}", ex.Message)); this.SetStatusCode(HttpStatusCode.Ambiguous); this.SetContentLength(Length: 0); } if (!string.IsNullOrEmpty(RawData)) { try { CssLoader Parser = new CssLoader(); CssStyleSheet Stylesheet = Parser.ParseSheet(RawData, this.GetUri(), this.GetUri()); this.ProcessCssOutlinks(Stylesheet: Stylesheet); } catch (Exception ex) { this.DebugMsg(string.Format("ProcessHtmlAttributeCssLinks: {0}", ex.Message)); this.AddRemark("ProcessHtmlAttributeCssLinks", ex.Message); } } else { DebugMsg(string.Format("ProcessCssPage: ERROR: {0}", this.GetUrl())); } /** Custom Filters ------------------------------------------------- **/ if (!string.IsNullOrEmpty(RawData)) { if ( MacroscopePreferencesManager.GetCustomFiltersEnable() && MacroscopePreferencesManager.GetCustomFiltersApplyToCss()) { MacroscopeCustomFilters CustomFilter = this.DocCollection.GetJobMaster().GetCustomFilter(); if ((CustomFilter != null) && (CustomFilter.IsEnabled())) { this.ProcessGenericCustomFiltered( CustomFilter: CustomFilter, GenericText: RawData ); } } } /** Data Extractors ------------------------------------------------ **/ if (!string.IsNullOrEmpty(RawData)) { if ( MacroscopePreferencesManager.GetDataExtractorsEnable() && MacroscopePreferencesManager.GetDataExtractorsApplyToCss()) { this.ProcessGenericDataExtractors(GenericText: RawData); } } /** Title ---------------------------------------------------------- **/ { MatchCollection reMatches = Regex.Matches(this.DocUrl, "/([^/]+)$"); string DocumentTitle = null; foreach (Match match in reMatches) { if (match.Groups[1].Value.Length > 0) { DocumentTitle = match.Groups[1].Value.ToString(); break; } } if (DocumentTitle != null) { this.SetTitle(DocumentTitle, MacroscopeConstants.TextProcessingMode.NO_PROCESSING); DebugMsg(string.Format("TITLE: {0}", this.GetTitle())); } else { DebugMsg(string.Format("TITLE: {0}", "MISSING")); } } } if (ResponseErrorCondition != null) { this.ProcessErrorCondition(ResponseErrorCondition); } }
/**************************************************************************/ private void ProcessCssOutlinks(CssStyleSheet Stylesheet) { // https://github.com/Athari/CsCss // https://developer.mozilla.org/en-US/docs/Web/CSS/url List <string> BackgroundImageUrls = null; if (this.GetIsExternal()) { return; } try { BackgroundImageUrls = Stylesheet.AllStyleRules .Where(StyleRule => StyleRule.Declaration.BackgroundImage != null) .SelectMany(StyleRule => StyleRule.Declaration.AllData) .SelectMany(Property => Property.Value.Unit == CssUnit.List ? Property.Value.List : new[] { Property.Value }) .Where(Value => Value.Unit == CssUnit.Url) .Select(Value => Value.OriginalUri) .ToList(); } catch (Exception ex) { DebugMsg(string.Format("ProcessCssOutlinks: {0}", ex.Message)); } if (BackgroundImageUrls != null) { foreach (string BackgroundImageUrl in BackgroundImageUrls) { string LinkUrlAbs = this.ProcessCssBackgroundImageUrl(BackgroundImageUrl); DebugMsg(string.Format("ProcessCssOutlinks: (background-image): {0}", BackgroundImageUrl)); DebugMsg(string.Format("ProcessCssOutlinks: (background-image): {0}", LinkUrlAbs)); if (LinkUrlAbs != null) { MacroscopeHyperlinkOut HyperlinkOut = null; MacroscopeLink Outlink = null; HyperlinkOut = this.HyperlinksOut.Add( LinkType: MacroscopeConstants.HyperlinkType.CSS, UrlTarget: LinkUrlAbs ); Outlink = this.AddDocumentOutlink( AbsoluteUrl: LinkUrlAbs, LinkType: MacroscopeConstants.InOutLinkType.IMAGE, Follow: true ); if (Outlink != null) { Outlink.SetRawTargetUrl(BackgroundImageUrl); } } } } return; }
/// <summary> /// Creates a /// <see cref="SvgStyleResolver"/> /// with a given default CSS. /// </summary> /// <param name="defaultCssStream">the default CSS</param> /// <param name="context">the processor context</param> public SvgStyleResolver(Stream defaultCssStream, SvgProcessorContext context) { this.css = CssStyleSheetParser.Parse(defaultCssStream); this.resourceResolver = context.GetResourceResolver(); }