From 8a624696bdcfb8f2d4532ebf1c07373be63ae758 Mon Sep 17 00:00:00 2001 From: SSgumS Date: Thu, 10 Jun 2021 14:56:23 +0430 Subject: [PATCH 1/3] add direction support support complex text styling improve heading support better hr different environment newline support br double line fix improve hyperlink support --- MariGold.OpenXHTML/DocxElement.cs | 9 +- MariGold.OpenXHTML/Elements/DocxBr.cs | 8 +- MariGold.OpenXHTML/Elements/DocxHeading.cs | 16 +++- MariGold.OpenXHTML/Elements/DocxHr.cs | 21 +++-- MariGold.OpenXHTML/Elements/DocxOL.cs | 2 +- MariGold.OpenXHTML/Elements/DocxUL.cs | 5 +- MariGold.OpenXHTML/OpenXmlContext.cs | 34 ++++++++ MariGold.OpenXHTML/Styles/DocxDirection.cs | 53 ++++++++++++ MariGold.OpenXHTML/Styles/DocxFontStyle.cs | 18 ++-- .../Styles/DocxParagraphStyle.cs | 84 ++++++++++++++++++- MariGold.OpenXHTML/Styles/DocxRunStyle.cs | 12 +++ 11 files changed, 238 insertions(+), 24 deletions(-) create mode 100644 MariGold.OpenXHTML/Styles/DocxDirection.cs diff --git a/MariGold.OpenXHTML/DocxElement.cs b/MariGold.OpenXHTML/DocxElement.cs index 30806ca..488dd59 100644 --- a/MariGold.OpenXHTML/DocxElement.cs +++ b/MariGold.OpenXHTML/DocxElement.cs @@ -13,6 +13,7 @@ internal abstract class DocxElement protected const string whiteSpace = " "; protected readonly IOpenXmlContext context; internal EventHandler ParagraphCreated; + protected readonly Regex newLineRegex = new Regex("(?:\n|\r\n)"); protected void RunCreated(DocxNode node, Run run) { @@ -221,7 +222,7 @@ internal string ClearHtml(string html) html = html.Replace(" ", whiteSpace); html = html.Replace("&", "&"); - Regex regex = new Regex(Environment.NewLine + "\\s+"); + Regex regex = new Regex("(?:\n|\r\n)" + "\\s+"); Match match = regex.Match(html); while (match.Success) @@ -231,7 +232,7 @@ internal string ClearHtml(string html) match = regex.Match(html); } - html = html.Replace(Environment.NewLine, string.Empty); + html = newLineRegex.Replace(html, string.Empty); return html; } @@ -243,7 +244,7 @@ internal bool IsEmptyText(string html) return true; } - html = html.Replace(Environment.NewLine, string.Empty); + html = newLineRegex.Replace(html, string.Empty); if (string.IsNullOrEmpty(html.Trim())) { @@ -262,7 +263,7 @@ internal bool IsEmptyText(DocxNode node, out string text) return true; } - text = node.InnerHtml.Replace(Environment.NewLine, string.Empty); + text = newLineRegex.Replace(node.InnerHtml, string.Empty); if (!string.IsNullOrEmpty(text.Trim())) { diff --git a/MariGold.OpenXHTML/Elements/DocxBr.cs b/MariGold.OpenXHTML/Elements/DocxBr.cs index 434f51d..3960119 100644 --- a/MariGold.OpenXHTML/Elements/DocxBr.cs +++ b/MariGold.OpenXHTML/Elements/DocxBr.cs @@ -25,9 +25,11 @@ internal override void Process(DocxNode node, ref Paragraph paragraph, Dictionar paragraph = node.Parent.AppendChild(new Paragraph()); OnParagraphCreated(node.ParagraphNode, paragraph); } - - Run run = paragraph.AppendChild(new Run(new Break())); - RunCreated(node, run); + else + { + Run run = paragraph.AppendChild(new Run(new Break())); + RunCreated(node, run); + } } } diff --git a/MariGold.OpenXHTML/Elements/DocxHeading.cs b/MariGold.OpenXHTML/Elements/DocxHeading.cs index 9b75c1d..1d7f839 100644 --- a/MariGold.OpenXHTML/Elements/DocxHeading.cs +++ b/MariGold.OpenXHTML/Elements/DocxHeading.cs @@ -7,6 +7,7 @@ internal sealed class DocxHeading : DocxElement { private Regex isValid; + private int number; private int GetHeaderNumber(DocxNode node) { @@ -64,7 +65,7 @@ private void ApplyStyle(DocxNode node) if (string.IsNullOrEmpty(fontSizeValue)) { - string headingFontSize = CalculateFontSize(GetHeaderNumber(node)); + string headingFontSize = CalculateFontSize(number); string inheritedStyle = node.ExtractInheritedStyleValue(DocxFontStyle.fontSize); if (!string.IsNullOrEmpty(inheritedStyle)) @@ -88,6 +89,16 @@ private void ApplyStyle(DocxNode node) node.SetExtentedStyle(DocxFontStyle.fontWeight, fontWeightValue); } + private void OnHeadingParagraphCreated(object sender, ParagraphEventArgs args) + { + if (args.Paragraph.ParagraphProperties == null) + { + args.Paragraph.ParagraphProperties = new ParagraphProperties(); + } + + args.Paragraph.ParagraphProperties.Append(new ParagraphStyleId() { Val = $"Heading{number}" }); + } + internal DocxHeading(IOpenXmlContext context) : base(context) { @@ -108,8 +119,11 @@ internal override void Process(DocxNode node, ref Paragraph paragraph, Dictionar paragraph = null; Paragraph headerParagraph = null; + number = GetHeaderNumber(node); ApplyStyle(node); + ParagraphCreated = OnHeadingParagraphCreated; + ProcessBlockElement(node, ref headerParagraph, properties); } } diff --git a/MariGold.OpenXHTML/Elements/DocxHr.cs b/MariGold.OpenXHTML/Elements/DocxHr.cs index d7ab695..c17ef1b 100644 --- a/MariGold.OpenXHTML/Elements/DocxHr.cs +++ b/MariGold.OpenXHTML/Elements/DocxHr.cs @@ -2,7 +2,9 @@ { using System; using System.Collections.Generic; - using DocumentFormat.OpenXml.Wordprocessing; + using DocumentFormat.OpenXml.Vml; + using DocumentFormat.OpenXml.Vml.Office; + using DocumentFormat.OpenXml.Wordprocessing; internal sealed class DocxHr : DocxElement { @@ -32,12 +34,17 @@ internal override void Process(DocxNode node, ref Paragraph paragraph, Dictionar { hrParagraph.ParagraphProperties = new ParagraphProperties(); } - - ParagraphBorders paragraphBorders = new ParagraphBorders(); - DocxBorder.ApplyDefaultBorder(paragraphBorders); - hrParagraph.ParagraphProperties.Append(paragraphBorders); - - Run run = hrParagraph.AppendChild(new Run(new Text())); + + var rectangle = new Rectangle(); + rectangle.Style = "width:0;height:1.5pt"; + rectangle.Horizontal = true; + rectangle.HorizontalStandard = true; + rectangle.FillColor = "#a0a0a0"; + rectangle.Stroked = false; + rectangle.HorizontalAlignment = HorizontalRuleAlignmentValues.Center; + var picture = new Picture(rectangle); + + Run run = hrParagraph.AppendChild(new Run(picture)); RunCreated(node, run); } } diff --git a/MariGold.OpenXHTML/Elements/DocxOL.cs b/MariGold.OpenXHTML/Elements/DocxOL.cs index 6b2c3b7..ffa971c 100644 --- a/MariGold.OpenXHTML/Elements/DocxOL.cs +++ b/MariGold.OpenXHTML/Elements/DocxOL.cs @@ -24,7 +24,7 @@ private void DefineLevel(NumberFormatValues numberFormat, int levelIndex) Level level = new Level() { LevelIndex = gLevelId }; StartNumberingValue startNumberingValue = new StartNumberingValue() { Val = 1 }; NumberingFormat numberingFormat = new NumberingFormat() { Val = numberFormat }; - LevelText levelText = new LevelText() { Val = $"%{gLevelId + 1})" }; //Later we need a provison to configure this text. + LevelText levelText = new LevelText() { Val = $"%{gLevelId + 1}." }; //Later we need a provison to configure this text. LevelJustification levelJustification = new LevelJustification() { Val = LevelJustificationValues.Left }; PreviousParagraphProperties previousParagraphProperties = new PreviousParagraphProperties(); diff --git a/MariGold.OpenXHTML/Elements/DocxUL.cs b/MariGold.OpenXHTML/Elements/DocxUL.cs index 6778e36..f3aed85 100644 --- a/MariGold.OpenXHTML/Elements/DocxUL.cs +++ b/MariGold.OpenXHTML/Elements/DocxUL.cs @@ -103,7 +103,7 @@ private void InitNumberDefinitions(int levelIndex) Level level = new Level() { LevelIndex = levelIndex }; StartNumberingValue startNumberingValue = new StartNumberingValue() { Val = 1 }; NumberingFormat numberingFormat = new NumberingFormat() { Val = NumberFormatValues.Bullet }; - LevelText levelText = new LevelText() { Val = "·" }; + LevelText levelText = new LevelText() { Val = "" }; LevelJustification levelJustification = new LevelJustification() { Val = LevelJustificationValues.Left }; PreviousParagraphProperties previousParagraphProperties = new PreviousParagraphProperties(); @@ -122,7 +122,8 @@ private void InitNumberDefinitions(int levelIndex) { Hint = FontTypeHintValues.Default, Ascii = "Symbol", - HighAnsi = "Symbol" + HighAnsi = "Symbol", + ComplexScript = "Symbol" }; numberingSymbolRunProperties.Append(runFonts); diff --git a/MariGold.OpenXHTML/OpenXmlContext.cs b/MariGold.OpenXHTML/OpenXmlContext.cs index 15389d7..0362f3a 100644 --- a/MariGold.OpenXHTML/OpenXmlContext.cs +++ b/MariGold.OpenXHTML/OpenXmlContext.cs @@ -97,6 +97,39 @@ private void SaveNumberDefinitions() } } + private void SaveStyleDefinitions() + { + if (mainPart.StyleDefinitionsPart is null) + { + _ = mainPart.AddNewPart("styleDefinitionsPart"); + } + + var styles = new Styles(); + + // Hyperlink + var hyperlink = new Style { StyleId = "Hyperlink", Type = StyleValues.Character }; + hyperlink.StyleName = new StyleName { Val = "Hyperlink" }; + hyperlink.UnhideWhenUsed = new UnhideWhenUsed(); + if (hyperlink.StyleRunProperties is null) + { + hyperlink.StyleRunProperties = new StyleRunProperties(); + } + hyperlink.StyleRunProperties.Append(new Color { Val = "0563C1", ThemeColor = ThemeColorValues.Hyperlink }); + hyperlink.StyleRunProperties.Append(new Underline { Val = UnderlineValues.Single }); + styles.Append(hyperlink); + + // Headings + for (int i = 1; i <= 6; i++) + { + var heading = new Style { StyleId = $"Heading{i}", Type = StyleValues.Paragraph }; + heading.StyleName = new StyleName { Val = $"heading {i}" }; + heading.LinkedStyle = new LinkedStyle { Val = $"Heading{i}Char" }; + styles.Append(heading); + } + + mainPart.StyleDefinitionsPart.Styles = styles; + } + internal OpenXmlContext(WordprocessingDocument document) { this.document = document; @@ -203,6 +236,7 @@ public Int16 ListNumberId public void Save() { SaveNumberDefinitions(); + SaveStyleDefinitions(); Document.Save(); diff --git a/MariGold.OpenXHTML/Styles/DocxDirection.cs b/MariGold.OpenXHTML/Styles/DocxDirection.cs new file mode 100644 index 0000000..091c098 --- /dev/null +++ b/MariGold.OpenXHTML/Styles/DocxDirection.cs @@ -0,0 +1,53 @@ +using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Wordprocessing; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MariGold.OpenXHTML +{ + internal static class DocxDirection + { + internal const string direction = "direction"; + + internal const string ltr = "ltr"; + internal const string rtl = "rtl"; + + private static bool GetDirectionValue(string style, out DirectionValues direction) + { + direction = DirectionValues.Ltr; + bool assigned = false; + + switch (style.ToLower()) + { + case ltr: + assigned = true; + direction = DirectionValues.Ltr; + break; + + case rtl: + assigned = true; + direction = DirectionValues.Rtl; + break; + } + + return assigned; + } + + internal static void ApplyBidi(string style, OpenXmlElement styleElement) + { + if (GetDirectionValue(style, out DirectionValues direction) && direction == DirectionValues.Rtl) + { + styleElement.Append(new BiDi()); + } + } + + internal static void ApplyDirection(string style, OpenXmlElement styleElement) + { + if (GetDirectionValue(style, out DirectionValues direction) && direction == DirectionValues.Rtl) + { + styleElement.Append(new RightToLeftText()); + } + } + } +} diff --git a/MariGold.OpenXHTML/Styles/DocxFontStyle.cs b/MariGold.OpenXHTML/Styles/DocxFontStyle.cs index 3a84085..20af7bc 100644 --- a/MariGold.OpenXHTML/Styles/DocxFontStyle.cs +++ b/MariGold.OpenXHTML/Styles/DocxFontStyle.cs @@ -61,7 +61,8 @@ private static string CleanFonts(string fonts) internal static void ApplyFontFamily(string style, OpenXmlElement styleElement) { - styleElement.Append(new RunFonts() { Ascii = CleanFonts(style) }); + var fontFamilies = CleanFonts(style); + styleElement.Append(new RunFonts() { Ascii = fontFamilies, ComplexScript = fontFamilies }); } internal static void ApplyFontWeight(string style, OpenXmlElement styleElement) @@ -70,6 +71,7 @@ internal static void ApplyFontWeight(string style, OpenXmlElement styleElement) string.Compare(bolder, style, StringComparison.InvariantCultureIgnoreCase) == 0) { styleElement.Append(new Bold()); + styleElement.Append(new BoldComplexScript()); } } @@ -78,6 +80,7 @@ internal static void ApplyFontStyle(string style, OpenXmlElement styleElement) if (string.Compare(italic, style, StringComparison.InvariantCultureIgnoreCase) == 0) { styleElement.Append(new Italic()); + styleElement.Append(new ItalicComplexScript()); } } @@ -106,11 +109,13 @@ internal static void ApplyUnderline(OpenXmlElement styleElement) internal static void ApplyFontItalic(OpenXmlElement styleElement) { styleElement.Append(new Italic()); + styleElement.Append(new ItalicComplexScript()); } internal static void ApplyBold(OpenXmlElement styleElement) { styleElement.Append(new Bold()); + styleElement.Append(new BoldComplexScript()); } internal static void ApplyFontSize(string style, OpenXmlElement styleElement) @@ -120,20 +125,23 @@ internal static void ApplyFontSize(string style, OpenXmlElement styleElement) if (fontSize != 0) { fontSize = decimal.Round(fontSize); - styleElement.Append(new FontSize() { Val = fontSize.ToString("N0") }); + var fontSizeString = fontSize.ToString("N0"); + styleElement.Append(new FontSize() { Val = fontSizeString }); + styleElement.Append(new FontSizeComplexScript() { Val = fontSizeString }); } } internal static void ApplyFont(int size, bool isBold, OpenXmlElement styleElement) { - FontSize fontSize = new FontSize() { Val = size.ToString() }; - if (isBold) { styleElement.Append(new Bold()); + styleElement.Append(new BoldComplexScript()); } - styleElement.Append(fontSize); + var sizeString = size.ToString(); + styleElement.Append(new FontSize() { Val = sizeString }); + styleElement.Append(new FontSizeComplexScript() { Val = sizeString }); } } } diff --git a/MariGold.OpenXHTML/Styles/DocxParagraphStyle.cs b/MariGold.OpenXHTML/Styles/DocxParagraphStyle.cs index fb1d939..ce40e52 100644 --- a/MariGold.OpenXHTML/Styles/DocxParagraphStyle.cs +++ b/MariGold.OpenXHTML/Styles/DocxParagraphStyle.cs @@ -32,6 +32,59 @@ static internal void SetIndentation(Paragraph element, int indent) element.ParagraphProperties.Append(new Indentation() { Left = indent.ToString() }); } + private void CheckFonts(DocxNode node, ParagraphMarkRunProperties properties) + { + string fontFamily = node.ExtractStyleValue(DocxFontStyle.fontFamily); + string fontWeight = node.ExtractStyleValue(DocxFontStyle.fontWeight); + string fontStyle = node.ExtractStyleValue(DocxFontStyle.fontStyle); + + if (!string.IsNullOrEmpty(fontFamily)) + { + DocxFontStyle.ApplyFontFamily(fontFamily, properties); + } + + if (!string.IsNullOrEmpty(fontWeight)) + { + DocxFontStyle.ApplyFontWeight(fontWeight, properties); + } + + if (!string.IsNullOrEmpty(fontStyle)) + { + DocxFontStyle.ApplyFontStyle(fontStyle, properties); + } + } + + private void CheckFontStyle(DocxNode node, ParagraphMarkRunProperties properties) + { + string fontSize = node.ExtractStyleValue(DocxFontStyle.fontSize); + string textDecoration = node.ExtractStyleValue(DocxFontStyle.textDecoration); + + if (string.IsNullOrEmpty(textDecoration)) + { + textDecoration = node.ExtractStyleValue(DocxFontStyle.textDecorationLine); + } + + if (!string.IsNullOrEmpty(fontSize)) + { + DocxFontStyle.ApplyFontSize(fontSize, properties); + } + + if (!string.IsNullOrEmpty(textDecoration)) + { + DocxFontStyle.ApplyTextDecoration(textDecoration, properties); + } + } + + private void ProcessDirection(DocxNode node, ParagraphProperties properties) + { + string styleValue = node.ExtractStyleValue(DocxDirection.direction); + + if (!string.IsNullOrEmpty(styleValue)) + { + DocxDirection.ApplyBidi(styleValue, properties); + } + } + internal void Process(Paragraph element, DocxNode node) { ParagraphProperties properties = element.ParagraphProperties; @@ -64,7 +117,36 @@ internal void Process(Paragraph element, DocxNode node) { DocxAlignment.ApplyTextAlign(textAlign, properties); } - + + ProcessDirection(node, properties); + + #region Set Run Properties for the Paragraph Mark + var runProperties = properties.ParagraphMarkRunProperties; + + if (runProperties == null) + { + runProperties = new ParagraphMarkRunProperties(); + } + + //Order of assigning styles to run property is important. The order should not change. + CheckFonts(node, runProperties); + + string color = node.ExtractStyleValue(DocxColor.color); + + if (!string.IsNullOrEmpty(color)) + { + DocxColor.ApplyColor(color, runProperties); + } + + CheckFontStyle(node, runProperties); + + if (properties.ParagraphMarkRunProperties == null && runProperties.HasChildren) + { + properties.ParagraphMarkRunProperties = runProperties; + } + #endregion + + if (element.ParagraphProperties == null && properties.HasChildren) { element.ParagraphProperties = properties; diff --git a/MariGold.OpenXHTML/Styles/DocxRunStyle.cs b/MariGold.OpenXHTML/Styles/DocxRunStyle.cs index 5655dee..12a182f 100644 --- a/MariGold.OpenXHTML/Styles/DocxRunStyle.cs +++ b/MariGold.OpenXHTML/Styles/DocxRunStyle.cs @@ -72,6 +72,16 @@ private void ProcessVerticalAlign(DocxNode node, RunProperties properties) } } + private void ProcessDirection(DocxNode node, RunProperties properties) + { + string styleValue = node.ExtractStyleValue(DocxDirection.direction); + + if (!string.IsNullOrEmpty(styleValue)) + { + DocxDirection.ApplyDirection(styleValue, properties); + } + } + internal void Process(Run element, DocxNode node) { RunProperties properties = element.RunProperties; @@ -97,6 +107,8 @@ internal void Process(Run element, DocxNode node) ProcessVerticalAlign(node, properties); + ProcessDirection(node, properties); + if (element.RunProperties == null && properties.HasChildren) { element.RunProperties = properties; From 99470fe0087fdf6942af44e384c67d6e53f1363b Mon Sep 17 00:00:00 2001 From: SSgumS Date: Mon, 14 Jun 2021 04:50:31 +0430 Subject: [PATCH 2/3] better redundant whitespace support better stream support --- MariGold.OpenXHTML/DocxElement.cs | 72 +++++++++---------------- MariGold.OpenXHTML/Elements/DocxBody.cs | 22 +++++--- MariGold.OpenXHTML/Elements/DocxDiv.cs | 2 +- MariGold.OpenXHTML/IOpenXmlContext.cs | 2 +- MariGold.OpenXHTML/OpenXmlContext.cs | 16 +++--- MariGold.OpenXHTML/WordDocument.cs | 20 ++++++- 6 files changed, 69 insertions(+), 65 deletions(-) diff --git a/MariGold.OpenXHTML/DocxElement.cs b/MariGold.OpenXHTML/DocxElement.cs index 488dd59..d8b2976 100644 --- a/MariGold.OpenXHTML/DocxElement.cs +++ b/MariGold.OpenXHTML/DocxElement.cs @@ -13,7 +13,8 @@ internal abstract class DocxElement protected const string whiteSpace = " "; protected readonly IOpenXmlContext context; internal EventHandler ParagraphCreated; - protected readonly Regex newLineRegex = new Regex("(?:\n|\r\n)"); + protected readonly Regex newLineRegex = new Regex(@"(?:\n|\r\n)"); + protected readonly Regex whitespaceRegex = new Regex(@"[\r\n ]+"); protected void RunCreated(DocxNode node, Run run) { @@ -143,21 +144,29 @@ protected void ProcessBlockElement(DocxNode node, ref Paragraph paragraph, Dicti protected void ProcessParagraph(DocxNode child, DocxNode node, DocxNode paragraphNode, ref Paragraph paragraph) { - if (!IsEmptyText(child, out string text)) + if (TryGetText(child, out string text)) { - if (paragraph == null) + if (paragraph == null && !IsEmptyText(text)) { paragraph = node.Parent.AppendChild(new Paragraph()); OnParagraphCreated(paragraphNode, paragraph); } - Run run = paragraph.AppendChild(new Run(new Text() + if (paragraph != null) { - Text = ClearHtml(text), - Space = SpaceProcessingModeValues.Preserve - })); + if (child.Previous != null && child.Previous.InnerHtml.EndsWith(whiteSpace)) + { + text = text.TrimStart(); + } + + Run run = paragraph.AppendChild(new Run(new Text() + { + Text = ClearHtml(text), + Space = SpaceProcessingModeValues.Preserve + })); - RunCreated(node, run); + RunCreated(node, run); + } } } @@ -217,67 +226,36 @@ internal string ClearHtml(string html) { return string.Empty; } - - html = WebUtility.HtmlDecode(html); - html = html.Replace(" ", whiteSpace); - html = html.Replace("&", "&"); - Regex regex = new Regex("(?:\n|\r\n)" + "\\s+"); - Match match = regex.Match(html); + html = whitespaceRegex.Replace(html, " "); - while (match.Success) - { - //match.Length - 1 for leave a single space. Otherwise the sentences will collide. - html = html.Remove(match.Index, match.Length - 1); - match = regex.Match(html); - } - - html = newLineRegex.Replace(html, string.Empty); + html = WebUtility.HtmlDecode(html); return html; } internal bool IsEmptyText(string html) { - if (string.IsNullOrEmpty(html)) - { - return true; - } - - html = newLineRegex.Replace(html, string.Empty); - - if (string.IsNullOrEmpty(html.Trim())) - { - return true; - } - - return false; + return string.IsNullOrEmpty(html.Trim()); } - internal bool IsEmptyText(DocxNode node, out string text) + internal bool TryGetText(DocxNode node, out string text) { - text = string.Empty; - - if (string.IsNullOrEmpty(node.InnerHtml)) - { - return true; - } - - text = newLineRegex.Replace(node.InnerHtml, string.Empty); + text = node.InnerHtml; if (!string.IsNullOrEmpty(text.Trim())) { - return false; + return true; } else if (!string.IsNullOrEmpty(text) && node.Previous != null && !node.Previous.IsText && !node.Previous.InnerHtml.EndsWith(whiteSpace) && node.Next != null && !node.Next.IsText && !node.Next.InnerHtml.StartsWith(whiteSpace)) { text = whiteSpace; - return false; + return true; } - return true; + return false; } internal abstract bool CanConvert(DocxNode node); diff --git a/MariGold.OpenXHTML/Elements/DocxBody.cs b/MariGold.OpenXHTML/Elements/DocxBody.cs index 50bf2a2..03da383 100644 --- a/MariGold.OpenXHTML/Elements/DocxBody.cs +++ b/MariGold.OpenXHTML/Elements/DocxBody.cs @@ -16,21 +16,29 @@ private void ProcessBody(DocxNode node, ref Paragraph paragraph, Dictionary Date: Mon, 14 Jun 2021 23:32:19 +0430 Subject: [PATCH 3/3] better regex performance --- MariGold.OpenXHTML/DocxElement.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MariGold.OpenXHTML/DocxElement.cs b/MariGold.OpenXHTML/DocxElement.cs index d8b2976..8fef2a2 100644 --- a/MariGold.OpenXHTML/DocxElement.cs +++ b/MariGold.OpenXHTML/DocxElement.cs @@ -13,8 +13,8 @@ internal abstract class DocxElement protected const string whiteSpace = " "; protected readonly IOpenXmlContext context; internal EventHandler ParagraphCreated; - protected readonly Regex newLineRegex = new Regex(@"(?:\n|\r\n)"); - protected readonly Regex whitespaceRegex = new Regex(@"[\r\n ]+"); + protected static readonly Regex newLineRegex = new Regex(@"(?:\n|\r\n)", RegexOptions.Compiled); + protected static readonly Regex whitespaceRegex = new Regex(@"[\r\n ]+", RegexOptions.Compiled); protected void RunCreated(DocxNode node, Run run) {